Handle "p S::method()::static_var" in the C++ parser
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 7c25641738bebbf4167c57af79728a2d1ad23106..f7f098ba525aea86947db5a7254709a951ac4038 100644 (file)
@@ -70,7 +70,7 @@ int yyparse (void);
 
 static int yylex (void);
 
-void yyerror (char *);
+void yyerror (const char *);
 
 static int type_aggregate_p (struct type *);
 
@@ -127,7 +127,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 #endif
 %}
 
-%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
+%type <voidval> exp exp1 type_exp start variable qualified_name lcurly function_method
 %type <lval> rcurly
 %type <tval> type typebase
 %type <tvec> nonempty_typelist func_mod parameter_typelist
@@ -498,6 +498,18 @@ exp        :       exp '('
                          write_exp_elt_opcode (pstate, OP_FUNCALL); }
        ;
 
+/* This is here to disambiguate with the production for
+   "func()::static_var" further below, which uses
+   function_method_void.  */
+exp    :       exp '(' ')' %prec ARROW
+                       { start_arglist ();
+                         write_exp_elt_opcode (pstate, OP_FUNCALL);
+                         write_exp_elt_longcst (pstate,
+                                                (LONGEST) end_arglist ());
+                         write_exp_elt_opcode (pstate, OP_FUNCALL); }
+       ;
+
+
 exp    :       UNKNOWN_CPP_NAME '('
                        {
                          /* This could potentially be a an argument defined
@@ -539,7 +551,7 @@ arglist     :       arglist ',' exp   %prec ABOVE_COMMA
                        { arglist_len++; }
        ;
 
-exp     :       exp '(' parameter_typelist ')' const_or_volatile
+function_method:       exp '(' parameter_typelist ')' const_or_volatile
                        { int i;
                          VEC (type_ptr) *type_list = $3;
                          struct type *type_elt;
@@ -557,6 +569,33 @@ exp     :       exp '(' parameter_typelist ')' const_or_volatile
                        }
        ;
 
+function_method_void:      exp '(' ')' const_or_volatile
+                      { write_exp_elt_opcode (pstate, TYPE_INSTANCE);
+                        write_exp_elt_longcst (pstate, 0);
+                        write_exp_elt_longcst (pstate, 0);
+                        write_exp_elt_opcode (pstate, TYPE_INSTANCE);
+                      }
+       ;
+
+exp     :       function_method
+       ;
+
+/* Normally we must interpret "func()" as a function call, instead of
+   a type.  The user needs to write func(void) to disambiguate.
+   However, in the "func()::static_var" case, there's no
+   ambiguity.  */
+function_method_void_or_typelist: function_method
+       |               function_method_void
+       ;
+
+exp     :       function_method_void_or_typelist COLONCOLON name
+                       {
+                         write_exp_elt_opcode (pstate, OP_FUNC_STATIC_VAR);
+                         write_exp_string (pstate, $3);
+                         write_exp_elt_opcode (pstate, OP_FUNC_STATIC_VAR);
+                       }
+       ;
+
 rcurly :       '}'
                        { $$ = end_arglist () - 1; }
        ;
@@ -1038,18 +1077,38 @@ variable:       name_not_typename
                            }
                          else
                            {
-                             struct bound_minimal_symbol msymbol;
                              char *arg = copy_name ($1.stoken);
 
-                             msymbol =
-                               lookup_bound_minimal_symbol (arg);
-                             if (msymbol.minsym != NULL)
-                               write_exp_msymbol (pstate, msymbol);
-                             else if (!have_full_symbols () && !have_partial_symbols ())
-                               error (_("No symbol table is loaded.  Use the \"file\" command."));
+                             bound_minimal_symbol msymbol
+                               = lookup_bound_minimal_symbol (arg);
+                             if (msymbol.minsym == NULL)
+                               {
+                                 if (!have_full_symbols () && !have_partial_symbols ())
+                                   error (_("No symbol table is loaded.  Use the \"file\" command."));
+                                 else
+                                   error (_("No symbol \"%s\" in current context."),
+                                          copy_name ($1.stoken));
+                               }
+
+                             /* This minsym might be an alias for
+                                another function.  See if we can find
+                                the debug symbol for the target, and
+                                if so, use it instead, since it has
+                                return type / prototype info.  This
+                                is important for example for "p
+                                *__errno_location()".  */
+                             symbol *alias_target
+                               = find_function_alias_target (msymbol);
+                             if (alias_target != NULL)
+                               {
+                                 write_exp_elt_opcode (pstate, OP_VAR_VALUE);
+                                 write_exp_elt_block
+                                   (pstate, SYMBOL_BLOCK_VALUE (alias_target));
+                                 write_exp_elt_sym (pstate, alias_target);
+                                 write_exp_elt_opcode (pstate, OP_VAR_VALUE);
+                               }
                              else
-                               error (_("No symbol \"%s\" in current context."),
-                                      copy_name ($1.stoken));
+                               write_exp_msymbol (pstate, msymbol);
                            }
                        }
        ;
@@ -1625,13 +1684,12 @@ write_destructor_name (struct parser_state *par_state, struct stoken token)
 static struct stoken
 operator_stoken (const char *op)
 {
-  static const char *operator_string = "operator";
   struct stoken st = { NULL, 0 };
   char *buf;
 
-  st.length = strlen (operator_string) + strlen (op);
+  st.length = CP_OPERATOR_LEN + strlen (op);
   buf = (char *) malloc (st.length + 1);
-  strcpy (buf, operator_string);
+  strcpy (buf, CP_OPERATOR_STR);
   strcat (buf, op);
   st.ptr = buf;
 
@@ -2217,7 +2275,7 @@ DEF_ENUM_FLAGS_TYPE (enum token_flag, token_flags);
 
 struct token
 {
-  char *oper;
+  const char *oper;
   int token;
   enum exp_opcode opcode;
   token_flags flags;
@@ -2806,7 +2864,7 @@ static int popping;
 
 /* Temporary storage for c_lex; this holds symbol names as they are
    built up.  */
-static struct obstack name_obstack;
+auto_obstack name_obstack;
 
 /* Classify a NAME token.  The contents of the token are in `yylval'.
    Updates yylval and returns the new token type.  BLOCK is the block
@@ -3067,7 +3125,7 @@ yylex (void)
   current = *VEC_index (token_and_value, token_fifo, next_to_examine);
   ++next_to_examine;
 
-  obstack_free (&name_obstack, obstack_base (&name_obstack));
+  name_obstack.clear ();
   checkpoint = 0;
   if (current.token == FILENAME)
     search_block = current.value.bval;
@@ -3169,6 +3227,9 @@ c_parse (struct parser_state *par_state)
   gdb_assert (par_state != NULL);
   pstate = par_state;
 
+  /* Note that parsing (within yyparse) freely installs cleanups
+     assuming they'll be run here (below).  */
+
   back_to = make_cleanup (free_current_contents, &expression_macro_scope);
   make_cleanup_clear_parser_state (&pstate);
 
@@ -3188,8 +3249,8 @@ c_parse (struct parser_state *par_state)
   gdb_assert (! macro_original_text);
   make_cleanup (scan_macro_cleanup, 0);
 
-  make_cleanup_restore_integer (&yydebug);
-  yydebug = parser_debug;
+  scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
+                                                       parser_debug);
 
   /* Initialize some state used by the lexer.  */
   last_was_structop = 0;
@@ -3197,8 +3258,7 @@ c_parse (struct parser_state *par_state)
 
   VEC_free (token_and_value, token_fifo);
   popping = 0;
-  obstack_init (&name_obstack);
-  make_cleanup_obstack_free (&name_obstack);
+  name_obstack.clear ();
 
   result = yyparse ();
   do_cleanups (back_to);
@@ -3265,7 +3325,7 @@ c_print_token (FILE *file, int type, YYSTYPE value)
 #endif
 
 void
-yyerror (char *msg)
+yyerror (const char *msg)
 {
   if (prev_lexptr)
     lexptr = prev_lexptr;
This page took 0.031704 seconds and 4 git commands to generate.