A ton of changes to improve C++ debugging. See ChangeLog.
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 865b021471637020b8c565eb607490a4fe4708b2..c49ad89839ef2452b4e56afd998c8ffd6439e02f 100644 (file)
@@ -38,15 +38,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "parser-defs.h"
 #include "value.h"
 #include "language.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
 
-/* Ensure that if the generated parser contains any calls to malloc/realloc,
-   that they get mapped to xmalloc/xrealloc. */
+/* If current_type is non-NULL, it is a signal to the lexer that we have
+   just parsed: 'TYPE ::' and so if an identifier is seen, the lexer must
+   search for it in TYPE.  This lex-time search is needed to parse
+   C++ nested types, as in: 'TYPE :: NESTED_TYPE', since this must
+   parse as a type, not a (non-type) identifier. */   
 
-#define malloc xmalloc
-#define realloc        xrealloc
+static struct type *current_type = NULL;
 
-/* These MUST be included in any grammar file!!!! 
-   Please choose unique names! */
+/* These MUST be included in any grammar file!!!! Please choose unique names!
+   Note that this are a combined list of variables that can be produced
+   by any one of bison, byacc, or yacc. */
 #define        yymaxdepth c_maxdepth
 #define        yyparse c_parse
 #define        yylex   c_lex
@@ -74,7 +80,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define        yy_yyv  c_yyv
 #define        yyval   c_val
 #define        yylloc  c_lloc
+#define yyss   c_yyss          /* byacc */
+#define        yyssp   c_yysp          /* byacc */
+#define        yyvs    c_yyvs          /* byacc */
+#define        yyvsp   c_yyvsp         /* byacc */
 
+int
 yyparse PARAMS ((void));
 
 int
@@ -117,7 +128,7 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 %}
 
 %type <voidval> exp exp1 type_exp start variable qualified_name
-%type <tval> type typebase
+%type <tval> type typebase typebase_coloncolon qualified_type
 %type <tvec> nonempty_typelist
 /* %type <bval> block */
 
@@ -141,6 +152,7 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 %token <sval> STRING
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
 %token <tsym> TYPENAME
+%token <tval> NESTED_TYPE
 %type <sval> name
 %type <ssym> name_not_typename
 %type <tsym> typename
@@ -152,13 +164,13 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 
 %token <ssym> NAME_OR_INT NAME_OR_UINT
 
-%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
 %token TEMPLATE
 %token ERROR
 
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
-%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
 
 %token <lval> LAST REGNAME
 
@@ -189,6 +201,19 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 %token <ssym> BLOCKNAME 
 %type <bval> block
 %left COLONCOLON
+
+%{
+/* Ensure that if the generated parser contains any calls to malloc/realloc,
+   that they get mapped to xmalloc/xrealloc.  We have to do this here
+   rather than earlier in the file because this is the first point after
+   the place where the SVR4 yacc includes <malloc.h>, and if we do it
+   before that, then the remapped declarations in <malloc.h> will collide
+   with the ones in "defs.h". */
+
+#define malloc xmalloc
+#define realloc        xrealloc
+%}
+
 \f
 %%
 
@@ -249,16 +274,16 @@ exp       :       SIZEOF exp       %prec UNARY
 
 exp    :       exp ARROW name
                        { write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_exp_elt_type (NULL);
                          write_exp_string ($3);
                          write_exp_elt_opcode (STRUCTOP_PTR); }
        ;
 
-exp    :       exp ARROW qualified_name
-                       { /* exp->type::name becomes exp->*(&type::name) */
-                         /* Note: this doesn't work if name is a
-                            static member!  FIXME */
-                         write_exp_elt_opcode (UNOP_ADDR);
-                         write_exp_elt_opcode (STRUCTOP_MPTR); }
+exp    :       exp ARROW typebase_coloncolon name
+                       { write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_exp_elt_type ($3);
+                         write_exp_string ($4);
+                         write_exp_elt_opcode (STRUCTOP_PTR); }
        ;
 exp    :       exp ARROW '*' exp
                        { write_exp_elt_opcode (STRUCTOP_MPTR); }
@@ -266,16 +291,16 @@ exp       :       exp ARROW '*' exp
 
 exp    :       exp '.' name
                        { write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_elt_type (NULL);
                          write_exp_string ($3);
                          write_exp_elt_opcode (STRUCTOP_STRUCT); }
        ;
 
-exp    :       exp '.' qualified_name
-                       { /* exp.type::name becomes exp.*(&type::name) */
-                         /* Note: this doesn't work if name is a
-                            static member!  FIXME */
-                         write_exp_elt_opcode (UNOP_ADDR);
-                         write_exp_elt_opcode (STRUCTOP_MEMBER); }
+exp    :       exp '.'  typebase_coloncolon name
+                       { write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_elt_type ($3);
+                         write_exp_string ($4);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); }
        ;
 
 exp    :       exp '.' '*' exp
@@ -560,7 +585,9 @@ variable:   block COLONCOLON name
                          write_exp_elt_opcode (OP_VAR_VALUE); }
        ;
 
-qualified_name:        typebase COLONCOLON name
+typebase_coloncolon : typebase COLONCOLON  { current_type = $1; $$ = $1; }
+
+qualified_name:        typebase_coloncolon name
                        {
                          struct type *type = $1;
                          if (TYPE_CODE (type) != TYPE_CODE_STRUCT
@@ -570,10 +597,11 @@ qualified_name:   typebase COLONCOLON name
 
                          write_exp_elt_opcode (OP_SCOPE);
                          write_exp_elt_type (type);
-                         write_exp_string ($3);
+                         write_exp_string ($2);
                          write_exp_elt_opcode (OP_SCOPE);
+                         current_type = NULL;
                        }
-       |       typebase COLONCOLON '~' name
+       |       typebase_coloncolon '~' name
                        {
                          struct type *type = $1;
                          struct stoken tmp_token;
@@ -582,19 +610,20 @@ qualified_name:   typebase COLONCOLON name
                            error ("`%s' is not defined as an aggregate type.",
                                   TYPE_NAME (type));
 
-                         if (strcmp (type_name_no_tag (type), $4.ptr))
+                         if (strcmp (type_name_no_tag (type), $3.ptr))
                            error ("invalid destructor `%s::~%s'",
-                                  type_name_no_tag (type), $4.ptr);
+                                  type_name_no_tag (type), $3.ptr);
 
-                         tmp_token.ptr = (char*) alloca ($4.length + 2);
-                         tmp_token.length = $4.length + 1;
+                         tmp_token.ptr = (char*) alloca ($3.length + 2);
+                         tmp_token.length = $3.length + 1;
                          tmp_token.ptr[0] = '~';
-                         memcpy (tmp_token.ptr+1, $4.ptr, $4.length);
+                         memcpy (tmp_token.ptr+1, $3.ptr, $3.length);
                          tmp_token.ptr[tmp_token.length] = 0;
                          write_exp_elt_opcode (OP_SCOPE);
                          write_exp_elt_type (type);
                          write_exp_string (tmp_token);
                          write_exp_elt_opcode (OP_SCOPE);
+                         current_type = NULL;
                        }
        ;
 
@@ -806,9 +835,15 @@ func_mod:  '(' ')'
                        { free ((PTR)$2); $$ = 0; }
        ;
 
+qualified_type: typebase_coloncolon NESTED_TYPE
+                       { $$ = $2; current_type = NULL; }
+       ;
+
 type   :       ptype
-       |       typebase COLONCOLON '*'
-                       { $$ = lookup_member_type (builtin_type_int, $1); }
+       |       qualified_type
+       |       typebase_coloncolon '*'
+                       { $$ = lookup_member_type (builtin_type_int, $1);
+                         current_type = NULL; }
        |       type '(' typebase COLONCOLON '*' ')'
                        { $$ = lookup_member_type ($1, $3); }
        |       type '(' typebase COLONCOLON '*' ')' '(' ')'
@@ -818,6 +853,9 @@ type        :       ptype
                        { $$ = lookup_member_type
                            (lookup_function_type ($1), $3);
                          free ((PTR)$8); }
+       /* "const" and "volatile" are curently ignored. */
+       |       CONST_KEYWORD type { $$ = $2; }
+       |       VOLATILE_KEYWORD type { $$ = $2; }
        ;
 
 typebase
@@ -848,18 +886,25 @@ typebase
        |       STRUCT name
                        { $$ = lookup_struct (copy_name ($2),
                                              expression_context_block); }
+       |       CLASS name
+                       { $$ = lookup_struct (copy_name ($2),
+                                             expression_context_block); }
        |       UNION name
                        { $$ = lookup_union (copy_name ($2),
                                             expression_context_block); }
        |       ENUM name
                        { $$ = lookup_enum (copy_name ($2),
                                            expression_context_block); }
+       |       STRUCT qualified_type { $$ = check_struct ($2); }
+       |       CLASS qualified_type { $$ = check_struct ($2); }
+       |       UNION qualified_type { $$ = check_union ($2); }
+       |       ENUM qualified_type { $$ = check_enum ($2); }
        |       UNSIGNED typename
                        { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
        |       UNSIGNED
                        { $$ = builtin_type_unsigned_int; }
        |       SIGNED_KEYWORD typename
-                       { $$ = $2.type; }
+                       { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
        |       SIGNED_KEYWORD
                        { $$ = builtin_type_int; }
        |       TEMPLATE name '<' type '>'
@@ -891,13 +936,13 @@ typename: TYPENAME
 
 nonempty_typelist
        :       type
-               { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
-                 $$[0] = (struct type *)0;
+               { $$ = (struct type **) xmalloc (sizeof (struct type *) * 2);
+                 $<ivec>$[0] = 1;      /* Number of types in vector */
                  $$[1] = $1;
                }
        |       nonempty_typelist ',' type
-               { int len = sizeof (struct type *) * ++($<ivec>1[0]);
-                 $$ = (struct type **)xrealloc ((char *) $1, len);
+               { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+                 $$ = (struct type **) xrealloc ((char *) $1, len);
                  $$[$<ivec>$[0]] = $3;
                }
        ;
@@ -1108,6 +1153,9 @@ yylex ()
       goto retry;
 
     case '\'':
+      /* We either have a character constant ('0' or '\177' for example)
+        or we have a quoted symbol reference ('foo(int,int)' in C++
+        for example). */
       lexptr++;
       c = *lexptr++;
       if (c == '\\')
@@ -1115,7 +1163,17 @@ yylex ()
       yylval.lval = c;
       c = *lexptr++;
       if (c != '\'')
-       error ("Invalid character constant.");
+       {
+         namelen = skip_quoted (tokstart) - tokstart;
+         if (namelen > 2)
+           {
+             lexptr = tokstart + namelen;
+             namelen -= 2;
+             tokstart++;
+             goto tryname;
+           }
+         error ("Invalid character constant.");
+       }
       return CHAR;
 
     case '(':
@@ -1192,7 +1250,7 @@ yylex ()
          {
            char *err_copy = (char *) alloca (p - tokstart + 1);
 
-           bcopy (tokstart, err_copy, p - tokstart);
+           memcpy (err_copy, tokstart, p - tokstart);
            err_copy[p - tokstart] = 0;
            error ("Invalid number \"%s\".", err_copy);
          }
@@ -1268,6 +1326,7 @@ yylex ()
      and $$digits (equivalent to $<-digits> if you could type that).
      Make token type LAST, and put the number (the digits) in yylval.  */
 
+  tryname:
   if (*tokstart == '$')
     {
       register int negate = 0;
@@ -1326,6 +1385,8 @@ yylex ()
       if (current_language->la_language == language_cplus
          && !strncmp (tokstart, "template", 8))
        return TEMPLATE;
+      if (!strncmp (tokstart, "volatile", 8))
+       return VOLATILE_KEYWORD;
       break;
     case 6:
       if (!strncmp (tokstart, "struct", 6))
@@ -1336,10 +1397,15 @@ yylex ()
        return SIZEOF;
       break;
     case 5:
+      if (current_language->la_language == language_cplus
+         && !strncmp (tokstart, "class", 5))
+       return CLASS;
       if (!strncmp (tokstart, "union", 5))
        return UNION;
       if (!strncmp (tokstart, "short", 5))
        return SHORT;
+      if (!strncmp (tokstart, "const", 5))
+       return CONST_KEYWORD;
       break;
     case 4:
       if (!strncmp (tokstart, "enum", 4))
@@ -1376,6 +1442,17 @@ yylex ()
       return VARIABLE;
     }
 
+  if (current_type)
+    {
+      struct type *t =
+         find_nested_type (current_type, copy_name (yylval.sval));
+      if (t)
+       {
+         yylval.tval = t;
+         return NESTED_TYPE;
+        }
+    }
+
   /* Use token-type BLOCKNAME for symbols that happen to be defined as
      functions or symtabs.  If this is not so, then ...
      Use token-type TYPENAME for symbols that happen to be defined
This page took 0.02952 seconds and 4 git commands to generate.