* symfile.h (struct sym_fns): Delete member "sym_flavour".
[binutils-gdb.git] / gdb / c-exp.y
index 313a63f10d511c0fe2dc34dec635c606cdec6ffb..3a51878da5cf68ea03f826f95e09330fbd850ab9 100644 (file)
@@ -167,6 +167,7 @@ void yyerror (char *);
 static int parse_number (char *, int, int, YYSTYPE *);
 static struct stoken operator_stoken (const char *);
 static void check_parameter_typelist (VEC (type_ptr) *);
+static void write_destructor_name (struct stoken);
 
 static void c_print_token (FILE *file, int type, YYSTYPE value);
 #define YYPRINT(FILE, TYPE, VALUE) c_print_token (FILE, TYPE, VALUE)
@@ -233,6 +234,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 %token ENTRY
 %token TYPEOF
 %token DECLTYPE
+%token TYPEID
 
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
@@ -345,6 +347,14 @@ exp        :       exp DECREMENT    %prec UNARY
                        { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
        ;
 
+exp    :       TYPEID '(' exp ')' %prec UNARY
+                       { write_exp_elt_opcode (OP_TYPEID); }
+       ;
+
+exp    :       TYPEID '(' type_exp ')' %prec UNARY
+                       { write_exp_elt_opcode (OP_TYPEID); }
+       ;
+
 exp    :       SIZEOF exp       %prec UNARY
                        { write_exp_elt_opcode (UNOP_SIZEOF); }
        ;
@@ -372,6 +382,19 @@ exp        :       exp ARROW COMPLETE
                          write_exp_elt_opcode (STRUCTOP_PTR); }
        ;
 
+exp    :       exp ARROW '~' name
+                       { write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_destructor_name ($4);
+                         write_exp_elt_opcode (STRUCTOP_PTR); }
+       ;
+
+exp    :       exp ARROW '~' name COMPLETE
+                       { mark_struct_expression ();
+                         write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_destructor_name ($4);
+                         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
@@ -407,6 +430,19 @@ exp        :       exp '.' COMPLETE
                          write_exp_elt_opcode (STRUCTOP_STRUCT); }
        ;
 
+exp    :       exp '.' '~' name
+                       { write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_destructor_name ($4);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); }
+       ;
+
+exp    :       exp '.' '~' name COMPLETE
+                       { mark_struct_expression ();
+                         write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_destructor_name ($4);
+                         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
@@ -968,7 +1004,7 @@ variable:  qualified_name
                        {
                          char *name = copy_name ($2.stoken);
                          struct symbol *sym;
-                         struct minimal_symbol *msymbol;
+                         struct bound_minimal_symbol msymbol;
 
                          sym =
                            lookup_symbol (name, (const struct block *) NULL,
@@ -982,8 +1018,8 @@ variable:  qualified_name
                              break;
                            }
 
-                         msymbol = lookup_minimal_symbol (name, NULL, NULL);
-                         if (msymbol != NULL)
+                         msymbol = lookup_bound_minimal_symbol (name);
+                         if (msymbol.minsym != NULL)
                            write_exp_msymbol (msymbol);
                          else if (!have_full_symbols () && !have_partial_symbols ())
                            error (_("No symbol table is loaded.  Use the \"file\" command."));
@@ -1030,12 +1066,12 @@ variable:       name_not_typename
                            }
                          else
                            {
-                             struct minimal_symbol *msymbol;
+                             struct bound_minimal_symbol msymbol;
                              char *arg = copy_name ($1.stoken);
 
                              msymbol =
-                               lookup_minimal_symbol (arg, NULL, NULL);
-                             if (msymbol != NULL)
+                               lookup_bound_minimal_symbol (arg);
+                             if (msymbol.minsym != NULL)
                                write_exp_msymbol (msymbol);
                              else if (!have_full_symbols () && !have_partial_symbols ())
                                error (_("No symbol table is loaded.  Use the \"file\" command."));
@@ -1592,6 +1628,22 @@ name_not_typename :      NAME
 
 %%
 
+/* Like write_exp_string, but prepends a '~'.  */
+
+static void
+write_destructor_name (struct stoken token)
+{
+  char *copy = alloca (token.length + 1);
+
+  copy[0] = '~';
+  memcpy (&copy[1], token.ptr, token.length);
+
+  token.ptr = copy;
+  ++token.length;
+
+  write_exp_string (token);
+}
+
 /* Returns a stoken of the operator name given by OP (which does not
    include the string "operator").  */ 
 static struct stoken
@@ -2247,7 +2299,9 @@ static const struct token ident_tokens[] =
     {"__typeof", TYPEOF, OP_TYPEOF, 0 },
     {"typeof", TYPEOF, OP_TYPEOF, FLAG_SHADOW },
     {"__decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX },
-    {"decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX | FLAG_SHADOW }
+    {"decltype", DECLTYPE, OP_DECLTYPE, FLAG_CXX | FLAG_SHADOW },
+
+    {"typeid", TYPEID, OP_TYPEID, FLAG_CXX}
   };
 
 /* When we find that lexptr (the global var defined in parse.c) is
@@ -2917,58 +2971,91 @@ static int
 yylex (void)
 {
   token_and_value current;
-  int first_was_coloncolon, last_was_coloncolon, first_iter;
+  int first_was_coloncolon, last_was_coloncolon;
   struct type *context_type = NULL;
+  int last_to_examine, next_to_examine, checkpoint;
+  const struct block *search_block;
 
   if (popping && !VEC_empty (token_and_value, token_fifo))
-    {
-      token_and_value tv = *VEC_index (token_and_value, token_fifo, 0);
-      VEC_ordered_remove (token_and_value, token_fifo, 0);
-      yylval = tv.value;
-      return tv.token;
-    }
+    goto do_pop;
   popping = 0;
 
+  /* Read the first token and decide what to do.  Most of the
+     subsequent code is C++-only; but also depends on seeing a "::" or
+     name-like token.  */
   current.token = lex_one_token ();
   if (current.token == NAME)
     current.token = classify_name (expression_context_block);
   if (parse_language->la_language != language_cplus
-      || (current.token != TYPENAME && current.token != COLONCOLON))
+      || (current.token != TYPENAME && current.token != COLONCOLON
+         && current.token != FILENAME))
     return current.token;
 
-  first_was_coloncolon = current.token == COLONCOLON;
-  last_was_coloncolon = first_was_coloncolon;
+  /* Read any sequence of alternating "::" and name-like tokens into
+     the token FIFO.  */
+  current.value = yylval;
+  VEC_safe_push (token_and_value, token_fifo, &current);
+  last_was_coloncolon = current.token == COLONCOLON;
+  while (1)
+    {
+      current.token = lex_one_token ();
+      current.value = yylval;
+      VEC_safe_push (token_and_value, token_fifo, &current);
+
+      if ((last_was_coloncolon && current.token != NAME)
+         || (!last_was_coloncolon && current.token != COLONCOLON))
+       break;
+      last_was_coloncolon = !last_was_coloncolon;
+    }
+  popping = 1;
+
+  /* We always read one extra token, so compute the number of tokens
+     to examine accordingly.  */
+  last_to_examine = VEC_length (token_and_value, token_fifo) - 2;
+  next_to_examine = 0;
+
+  current = *VEC_index (token_and_value, token_fifo, next_to_examine);
+  ++next_to_examine;
+
   obstack_free (&name_obstack, obstack_base (&name_obstack));
-  if (!last_was_coloncolon)
+  checkpoint = 0;
+  if (current.token == FILENAME)
+    search_block = current.value.bval;
+  else if (current.token == COLONCOLON)
+    search_block = NULL;
+  else
     {
-      obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length);
-      context_type = yylval.tsym.type;
+      gdb_assert (current.token == TYPENAME);
+      search_block = expression_context_block;
+      obstack_grow (&name_obstack, current.value.sval.ptr,
+                   current.value.sval.length);
+      context_type = current.value.tsym.type;
+      checkpoint = 1;
     }
-  current.value = yylval;
-  first_iter = 1;
-  while (1)
+
+  first_was_coloncolon = current.token == COLONCOLON;
+  last_was_coloncolon = first_was_coloncolon;
+
+  while (next_to_examine <= last_to_examine)
     {
-      token_and_value next;
+      token_and_value *next;
 
-      next.token = lex_one_token ();
-      next.value = yylval;
+      next = VEC_index (token_and_value, token_fifo, next_to_examine);
+      ++next_to_examine;
 
-      if (next.token == NAME && last_was_coloncolon)
+      if (next->token == NAME && last_was_coloncolon)
        {
          int classification;
 
-         classification = classify_inner_name (first_was_coloncolon
-                                               ? NULL
-                                               : expression_context_block,
-                                               context_type);
+         yylval = next->value;
+         classification = classify_inner_name (search_block, context_type);
          /* 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 && classification != NAME)
-           {
-             /* Push the final component and leave the loop.  */
-             VEC_safe_push (token_and_value, token_fifo, &next);
-             break;
-           }
+           break;
+
+         /* Accept up to this token.  */
+         checkpoint = next_to_examine;
 
          /* Update the partial name we are constructing.  */
          if (context_type != NULL)
@@ -2976,8 +3063,8 @@ yylex (void)
              /* We don't want to put a leading "::" into the name.  */
              obstack_grow_str (&name_obstack, "::");
            }
-         obstack_grow (&name_obstack, next.value.sval.ptr,
-                       next.value.sval.length);
+         obstack_grow (&name_obstack, next->value.sval.ptr,
+                       next->value.sval.length);
 
          yylval.sval.ptr = obstack_base (&name_obstack);
          yylval.sval.length = obstack_object_size (&name_obstack);
@@ -2991,38 +3078,32 @@ yylex (void)
 
          context_type = yylval.tsym.type;
        }
-      else if (next.token == COLONCOLON && !last_was_coloncolon)
+      else if (next->token == COLONCOLON && !last_was_coloncolon)
        last_was_coloncolon = 1;
       else
        {
          /* We've reached the end of the name.  */
-         VEC_safe_push (token_and_value, token_fifo, &next);
          break;
        }
-
-      first_iter = 0;
     }
 
-  popping = 1;
-
-  /* If we ended with a "::", insert it too.  */
-  if (last_was_coloncolon)
+  /* If we have a replacement token, install it as the first token in
+     the FIFO, and delete the other constituent tokens.  */
+  if (checkpoint > 0)
     {
-      token_and_value cc;
-      memset (&cc, 0, sizeof (token_and_value));
-      if (first_was_coloncolon && first_iter)
-       {
-         yylval = cc.value;
-         return COLONCOLON;
-       }
-      cc.token = COLONCOLON;
-      VEC_safe_insert (token_and_value, token_fifo, 0, &cc);
+      current.value.sval.ptr = obstack_copy0 (&expansion_obstack,
+                                             current.value.sval.ptr,
+                                             current.value.sval.length);
+
+      VEC_replace (token_and_value, token_fifo, 0, &current);
+      if (checkpoint > 1)
+       VEC_block_remove (token_and_value, token_fifo, 1, checkpoint - 1);
     }
 
+ do_pop:
+  current = *VEC_index (token_and_value, token_fifo, 0);
+  VEC_ordered_remove (token_and_value, token_fifo, 0);
   yylval = current.value;
-  yylval.sval.ptr = obstack_copy0 (&expansion_obstack,
-                                  yylval.sval.ptr,
-                                  yylval.sval.length);
   return current.token;
 }