Sync with GCC:
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index f5abacf37828f67a139e9aaf925641eb10d8c233..d657c923f935949a6ccb193f6a689bb884e2326d 100644 (file)
@@ -157,6 +157,7 @@ void yyerror (char *);
 %{
 /* YYSTYPE gets defined by %union */
 static int parse_number (char *, int, int, YYSTYPE *);
+static struct stoken operator_stoken (const char *);
 %}
 
 %type <voidval> exp exp1 type_exp start variable qualified_name lcurly
@@ -199,9 +200,12 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <ssym> NAME_OR_INT 
 
+%token OPERATOR
 %token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
 %token TEMPLATE
 %token ERROR
+%token NEW DELETE
+%type <sval> operator
 
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
@@ -401,6 +405,18 @@ arglist    :       arglist ',' exp   %prec ABOVE_COMMA
                        { arglist_len++; }
        ;
 
+exp     :       exp '(' nonempty_typelist ')' const_or_volatile
+                       { int i;
+                         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_opcode (TYPE_INSTANCE);
+                         free ($3);
+                       }
+       ;
+
 rcurly :       '}'
                        { $$ = end_arglist () - 1; }
        ;
@@ -777,9 +793,9 @@ variable:   name_not_typename
                            {
                              if (symbol_read_needs_frame (sym))
                                {
-                                 if (innermost_block == 0 ||
-                                     contained_in (block_found, 
-                                                   innermost_block))
+                                 if (innermost_block == 0
+                                     || contained_in (block_found, 
+                                                      innermost_block))
                                    innermost_block = block_found;
                                }
 
@@ -796,8 +812,9 @@ variable:   name_not_typename
                              /* C++: it hangs off of `this'.  Must
                                 not inadvertently convert from a method call
                                 to data ref.  */
-                             if (innermost_block == 0 || 
-                                 contained_in (block_found, innermost_block))
+                             if (innermost_block == 0
+                                 || contained_in (block_found,
+                                                  innermost_block))
                                innermost_block = block_found;
                              write_exp_elt_opcode (OP_THIS);
                              write_exp_elt_opcode (OP_THIS);
@@ -1119,10 +1136,130 @@ const_or_volatile_noopt:       const_and_volatile
                        { push_type (tp_volatile); }
        ;
 
+operator:      OPERATOR NEW
+                       { $$ = operator_stoken (" new"); }
+       |       OPERATOR DELETE
+                       { $$ = operator_stoken (" delete"); }
+       |       OPERATOR NEW '[' ']'
+                       { $$ = operator_stoken (" new[]"); }
+       |       OPERATOR DELETE '[' ']'
+                       { $$ = operator_stoken (" delete[]"); }
+       |       OPERATOR '+'
+                       { $$ = operator_stoken ("+"); }
+       |       OPERATOR '-'
+                       { $$ = operator_stoken ("-"); }
+       |       OPERATOR '*'
+                       { $$ = operator_stoken ("*"); }
+       |       OPERATOR '/'
+                       { $$ = operator_stoken ("/"); }
+       |       OPERATOR '%'
+                       { $$ = operator_stoken ("%"); }
+       |       OPERATOR '^'
+                       { $$ = operator_stoken ("^"); }
+       |       OPERATOR '&'
+                       { $$ = operator_stoken ("&"); }
+       |       OPERATOR '|'
+                       { $$ = operator_stoken ("|"); }
+       |       OPERATOR '~'
+                       { $$ = operator_stoken ("~"); }
+       |       OPERATOR '!'
+                       { $$ = operator_stoken ("!"); }
+       |       OPERATOR '='
+                       { $$ = operator_stoken ("="); }
+       |       OPERATOR '<'
+                       { $$ = operator_stoken ("<"); }
+       |       OPERATOR '>'
+                       { $$ = operator_stoken (">"); }
+       |       OPERATOR ASSIGN_MODIFY
+                       { const char *op = "unknown";
+                         switch ($2)
+                           {
+                           case BINOP_RSH:
+                             op = ">>=";
+                             break;
+                           case BINOP_LSH:
+                             op = "<<=";
+                             break;
+                           case BINOP_ADD:
+                             op = "+=";
+                             break;
+                           case BINOP_SUB:
+                             op = "-=";
+                             break;
+                           case BINOP_MUL:
+                             op = "*=";
+                             break;
+                           case BINOP_DIV:
+                             op = "/=";
+                             break;
+                           case BINOP_REM:
+                             op = "%=";
+                             break;
+                           case BINOP_BITWISE_IOR:
+                             op = "|=";
+                             break;
+                           case BINOP_BITWISE_AND:
+                             op = "&=";
+                             break;
+                           case BINOP_BITWISE_XOR:
+                             op = "^=";
+                             break;
+                           default:
+                             break;
+                           }
+
+                         $$ = operator_stoken (op);
+                       }
+       |       OPERATOR LSH
+                       { $$ = operator_stoken ("<<"); }
+       |       OPERATOR RSH
+                       { $$ = operator_stoken (">>"); }
+       |       OPERATOR EQUAL
+                       { $$ = operator_stoken ("=="); }
+       |       OPERATOR NOTEQUAL
+                       { $$ = operator_stoken ("!="); }
+       |       OPERATOR LEQ
+                       { $$ = operator_stoken ("<="); }
+       |       OPERATOR GEQ
+                       { $$ = operator_stoken (">="); }
+       |       OPERATOR ANDAND
+                       { $$ = operator_stoken ("&&"); }
+       |       OPERATOR OROR
+                       { $$ = operator_stoken ("||"); }
+       |       OPERATOR INCREMENT
+                       { $$ = operator_stoken ("++"); }
+       |       OPERATOR DECREMENT
+                       { $$ = operator_stoken ("--"); }
+       |       OPERATOR ','
+                       { $$ = operator_stoken (","); }
+       |       OPERATOR ARROW_STAR
+                       { $$ = operator_stoken ("->*"); }
+       |       OPERATOR ARROW
+                       { $$ = operator_stoken ("->"); }
+       |       OPERATOR '(' ')'
+                       { $$ = operator_stoken ("()"); }
+       |       OPERATOR '[' ']'
+                       { $$ = operator_stoken ("[]"); }
+       |       OPERATOR ptype
+                       { char *name;
+                         long length;
+                         struct ui_file *buf = mem_fileopen ();
+
+                         c_print_type ($2, NULL, buf, -1, 0);
+                         name = ui_file_xstrdup (buf, &length);
+                         ui_file_delete (buf);
+                         $$ = operator_stoken (name);
+                         free (name);
+                       }
+       ;
+
+
+
 name   :       NAME { $$ = $1.stoken; }
        |       BLOCKNAME { $$ = $1.stoken; }
        |       TYPENAME { $$ = $1.stoken; }
        |       NAME_OR_INT  { $$ = $1.stoken; }
+       |       operator { $$ = $1; }
        ;
 
 name_not_typename :    NAME
@@ -1138,6 +1275,23 @@ name_not_typename :      NAME
 
 %%
 
+/* Returns a stoken of the operator name given by OP (which does not
+   include the string "operator").  */ 
+static struct stoken
+operator_stoken (const char *op)
+{
+  static const char *operator_string = "operator";
+  struct stoken st = { NULL, 0 };
+  st.length = strlen (operator_string) + strlen (op);
+  st.ptr = malloc (st.length + 1);
+  strcpy (st.ptr, operator_string);
+  strcat (st.ptr, op);
+
+  /* The toplevel (c_parse) will free the memory allocated here.  */
+  make_cleanup (free, st.ptr);
+  return st;
+};
+
 /* Take care of parsing a number (anything that starts with a digit).
    Set yylval and return the token type; update lexptr.
    LEN is the number of characters in it.  */
@@ -1716,6 +1870,9 @@ static const struct token ident_tokens[] =
     {"long", LONG, OP_NULL, 0},
     {"true", TRUEKEYWORD, OP_NULL, 1},
     {"int", INT_KEYWORD, OP_NULL, 0},
+    {"new", NEW, OP_NULL, 1},
+    {"delete", DELETE, OP_NULL, 1},
+    {"operator", OPERATOR, OP_NULL, 1},
 
     {"and", ANDAND, BINOP_END, 1},
     {"and_eq", ASSIGN_MODIFY, BINOP_BITWISE_AND, 1},
@@ -2093,6 +2250,24 @@ yylex (void)
       return 0;
     }
 
+  /* For the same reason (breakpoint conditions), "thread N"
+     terminates the expression.  "thread" could be an identifier, but
+     an identifier is never followed by a number without intervening
+     punctuation.  "task" is similar.  Handle abbreviations of these,
+     similarly to breakpoint.c:find_condition_and_thread.  */
+  if (namelen >= 1
+      && (strncmp (tokstart, "thread", namelen) == 0
+         || strncmp (tokstart, "task", namelen) == 0)
+      && (tokstart[namelen] == ' ' || tokstart[namelen] == '\t')
+      && ! scanning_macro_expansion ())
+    {
+      char *p = tokstart + namelen + 1;
+      while (*p == ' ' || *p == '\t')
+       p++;
+      if (*p >= '0' && *p <= '9')
+       return 0;
+    }
+
   lexptr += namelen;
 
   tryname:
@@ -2174,9 +2349,9 @@ yylex (void)
     /* Input names that aren't symbols but ARE valid hex numbers,
        when the input radix permits them, can be names or numbers
        depending on the parse.  Note we support radixes > 16 here.  */
-    if (!sym && 
-        ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
-         (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+    if (!sym 
+        && ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
+           || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
       {
        YYSTYPE newlval;        /* Its value is ignored.  */
        hextype = parse_number (tokstart, namelen, 0, &newlval);
This page took 0.02767 seconds and 4 git commands to generate.