PR exp/9608:
[platform/upstream/binutils.git] / gdb / c-exp.y
index e912657..8890f74 100644 (file)
@@ -155,8 +155,10 @@ void yyerror (char *);
     struct internalvar *ivar;
 
     struct stoken_vector svec;
-    struct type **tvec;
+    VEC (type_ptr) *tvec;
     int *ivec;
+
+    struct type_stack *type_stack;
   }
 
 %{
@@ -168,13 +170,15 @@ static struct stoken operator_stoken (const char *);
 %type <voidval> exp exp1 type_exp start variable qualified_name lcurly
 %type <lval> rcurly
 %type <tval> type typebase
-%type <tvec> nonempty_typelist
+%type <tvec> nonempty_typelist func_mod
 /* %type <bval> block */
 
 /* Fancy type parsing.  */
-%type <voidval> func_mod direct_abs_decl abs_decl
 %type <tval> ptype
 %type <lval> array_mod
+%type <tval> conversion_type_id
+
+%type <type_stack> ptr_operator_ts abs_decl direct_abs_decl
 
 %token <typed_val_int> INT
 %token <typed_val_float> FLOAT
@@ -438,13 +442,19 @@ arglist   :       arglist ',' exp   %prec ABOVE_COMMA
 
 exp     :       exp '(' nonempty_typelist ')' const_or_volatile
                        { int i;
+                         VEC (type_ptr) *type_list = $3;
+                         struct type *type_elt;
+                         LONGEST len = VEC_length (type_ptr, type_list);
+
                          write_exp_elt_opcode (TYPE_INSTANCE);
-                         write_exp_elt_longcst ((LONGEST) $<ivec>3[0]);
-                         for (i = 0; i < $<ivec>3[0]; ++i)
-                           write_exp_elt_type ($<tvec>3[i + 1]);
-                         write_exp_elt_longcst((LONGEST) $<ivec>3[0]);
+                         write_exp_elt_longcst (len);
+                         for (i = 0;
+                              VEC_iterate (type_ptr, type_list, i, type_elt);
+                              ++i)
+                           write_exp_elt_type (type_elt);
+                         write_exp_elt_longcst(len);
                          write_exp_elt_opcode (TYPE_INSTANCE);
-                         free ($3);
+                         VEC_free (type_ptr, type_list);
                        }
        ;
 
@@ -931,9 +941,7 @@ variable:   name_not_typename
        ;
 
 space_identifier : '@' NAME
-               { push_type_address_space (copy_name ($2.stoken));
-                 push_type (tp_space_identifier);
-               }
+               { insert_type_address_space (copy_name ($2.stoken)); }
        ;
 
 const_or_volatile: const_or_volatile_noopt
@@ -952,14 +960,31 @@ const_or_volatile_or_space_identifier:
        |
        ;
 
-abs_decl:      '*'
-                       { push_type (tp_pointer); $$ = 0; }
-       |       '*' abs_decl
-                       { push_type (tp_pointer); $$ = $2; }
+ptr_operator:
+               ptr_operator '*'
+                       { insert_type (tp_pointer); }
+               const_or_volatile_or_space_identifier
+       |       '*' 
+                       { insert_type (tp_pointer); }
+               const_or_volatile_or_space_identifier
        |       '&'
-                       { push_type (tp_reference); $$ = 0; }
-       |       '&' abs_decl
-                       { push_type (tp_reference); $$ = $2; }
+                       { insert_type (tp_reference); }
+       |       '&' ptr_operator
+                       { insert_type (tp_reference); }
+       ;
+
+ptr_operator_ts: ptr_operator
+                       {
+                         $$ = get_type_stack ();
+                         /* This cleanup is eventually run by
+                            c_parse.  */
+                         make_cleanup (type_stack_cleanup, $$);
+                       }
+       ;
+
+abs_decl:      ptr_operator_ts direct_abs_decl
+                       { $$ = append_type_stack ($2, $1); }
+       |       ptr_operator_ts 
        |       direct_abs_decl
        ;
 
@@ -967,20 +992,29 @@ direct_abs_decl: '(' abs_decl ')'
                        { $$ = $2; }
        |       direct_abs_decl array_mod
                        {
+                         push_type_stack ($1);
                          push_type_int ($2);
                          push_type (tp_array);
+                         $$ = get_type_stack ();
                        }
        |       array_mod
                        {
                          push_type_int ($1);
                          push_type (tp_array);
-                         $$ = 0;
+                         $$ = get_type_stack ();
                        }
 
        |       direct_abs_decl func_mod
-                       { push_type (tp_function); }
+                       {
+                         push_type_stack ($1);
+                         push_typelist ($2);
+                         $$ = get_type_stack ();
+                       }
        |       func_mod
-                       { push_type (tp_function); }
+                       {
+                         push_typelist ($1);
+                         $$ = get_type_stack ();
+                       }
        ;
 
 array_mod:     '[' ']'
@@ -990,9 +1024,9 @@ array_mod: '[' ']'
        ;
 
 func_mod:      '(' ')'
-                       { $$ = 0; }
+                       { $$ = NULL; }
        |       '(' nonempty_typelist ')'
-                       { free ($2); $$ = 0; }
+                       { $$ = $2; }
        ;
 
 /* We used to try to recognize pointer to member types here, but
@@ -1191,44 +1225,56 @@ typename:       TYPENAME
 
 nonempty_typelist
        :       type
-               { $$ = (struct type **) malloc (sizeof (struct type *) * 2);
-                 $<ivec>$[0] = 1;      /* Number of types in vector */
-                 $$[1] = $1;
+               {
+                 VEC (type_ptr) *typelist = NULL;
+                 VEC_safe_push (type_ptr, typelist, $1);
+                 $$ = typelist;
                }
        |       nonempty_typelist ',' type
-               { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
-                 $$ = (struct type **) realloc ((char *) $1, len);
-                 $$[$<ivec>$[0]] = $3;
+               {
+                 VEC_safe_push (type_ptr, $1, $3);
+                 $$ = $1;
                }
        ;
 
 ptype  :       typebase
-       |       ptype const_or_volatile_or_space_identifier abs_decl const_or_volatile_or_space_identifier
+       |       ptype abs_decl
+               {
+                 push_type_stack ($2);
+                 $$ = follow_types ($1);
+               }
+       ;
+
+conversion_type_id: typebase conversion_declarator
                { $$ = follow_types ($1); }
        ;
 
+conversion_declarator:  /* Nothing.  */
+       | ptr_operator conversion_declarator
+       ;
+
 const_and_volatile:    CONST_KEYWORD VOLATILE_KEYWORD
        |               VOLATILE_KEYWORD CONST_KEYWORD
        ;
 
 const_or_volatile_noopt:       const_and_volatile 
-                       { push_type (tp_const);
-                         push_type (tp_volatile); 
+                       { insert_type (tp_const);
+                         insert_type (tp_volatile); 
                        }
        |               CONST_KEYWORD
-                       { push_type (tp_const); }
+                       { insert_type (tp_const); }
        |               VOLATILE_KEYWORD
-                       { push_type (tp_volatile); }
+                       { insert_type (tp_volatile); }
        ;
 
 operator:      OPERATOR NEW
                        { $$ = operator_stoken (" new"); }
        |       OPERATOR DELETE
-                       { $$ = operator_stoken (" delete "); }
+                       { $$ = operator_stoken (" delete"); }
        |       OPERATOR NEW '[' ']'
                        { $$ = operator_stoken (" new[]"); }
        |       OPERATOR DELETE '[' ']'
-                       { $$ = operator_stoken (" delete[] "); }
+                       { $$ = operator_stoken (" delete[]"); }
        |       OPERATOR '+'
                        { $$ = operator_stoken ("+"); }
        |       OPERATOR '-'
@@ -1325,7 +1371,7 @@ operator: OPERATOR NEW
                        { $$ = operator_stoken ("()"); }
        |       OPERATOR '[' ']'
                        { $$ = operator_stoken ("[]"); }
-       |       OPERATOR ptype
+       |       OPERATOR conversion_type_id
                        { char *name;
                          long length;
                          struct ui_file *buf = mem_fileopen ();
@@ -2505,9 +2551,8 @@ classify_name (struct block *block)
 
 /* Like classify_name, but used by the inner loop of the lexer, when a
    name might have already been seen.  FIRST_NAME is true if the token
-   in `yylval' is the first component of a name, false otherwise.  If
-   this function returns NAME, it might not have updated `yylval'.
-   This is ok because the caller only cares about TYPENAME.  */
+   in `yylval' is the first component of a name, false otherwise.  */
+
 static int
 classify_inner_name (struct block *block, int first_name)
 {
@@ -2521,18 +2566,28 @@ classify_inner_name (struct block *block, int first_name)
   if (TYPE_CODE (type) != TYPE_CODE_STRUCT
       && TYPE_CODE (type) != TYPE_CODE_UNION
       && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
-    /* We know the caller won't expect us to update yylval.  */
-    return NAME;
+    return ERROR;
 
   copy = copy_name (yylval.tsym.stoken);
-  new_type = cp_lookup_nested_type (yylval.tsym.type, copy, block);
+  yylval.ssym.sym = cp_lookup_nested_symbol (yylval.tsym.type, copy, block);
+  if (yylval.ssym.sym == NULL)
+    return ERROR;
 
-  if (new_type == NULL)
-    /* We know the caller won't expect us to update yylval.  */
-    return NAME;
+  switch (SYMBOL_CLASS (yylval.ssym.sym))
+    {
+    case LOC_BLOCK:
+    case LOC_LABEL:
+      return ERROR;
 
-  yylval.tsym.type = new_type;
-  return TYPENAME;
+    case LOC_TYPEDEF:
+      yylval.tsym.type = SYMBOL_TYPE (yylval.ssym.sym);;
+      return TYPENAME;
+
+    default:
+      yylval.ssym.is_a_field_of_this = 0;
+      return NAME;
+    }
+  internal_error (__FILE__, __LINE__, _("not reached"));
 }
 
 /* The outer level of a two-level lexer.  This calls the inner lexer
@@ -2592,7 +2647,7 @@ yylex (void)
                                                first_iter);
          /* We keep going until we either run out of names, or until
             we have a qualified name which is not a type.  */
-         if (classification != TYPENAME)
+         if (classification != TYPENAME && classification != NAME)
            {
              /* Push the final component and leave the loop.  */
              VEC_safe_push (token_and_value, token_fifo, &next);