X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=0326ee090e175e3344051485e7473d75e56ff93d;hb=a40bf0c2e93daac4ae4ce7dd1c43ab6135e76720;hp=283b7375c0a11697d91848daa19108fe3acbd0a8;hpb=156d9eab863f40fc812245cf1213abbe12d192b3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 283b7375c0..0326ee090e 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -1,5 +1,5 @@ /* YACC parser for C expressions, for GDB. - Copyright (C) 1986-2017 Free Software Foundation, Inc. + Copyright (C) 1986-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -42,13 +42,13 @@ #include "parser-defs.h" #include "language.h" #include "c-lang.h" +#include "c-support.h" #include "bfd.h" /* Required by objfiles.h. */ #include "symfile.h" /* Required by objfiles.h. */ #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ #include "charset.h" #include "block.h" #include "cp-support.h" -#include "dfp.h" #include "macroscope.h" #include "objc-lang.h" #include "typeprint.h" @@ -70,7 +70,7 @@ int yyparse (void); static int yylex (void); -void yyerror (const char *); +static void yyerror (const char *); static int type_aggregate_p (struct type *); @@ -87,14 +87,10 @@ static int type_aggregate_p (struct type *); LONGEST val; struct type *type; } typed_val_int; - struct { - DOUBLEST dval; - struct type *type; - } typed_val_float; struct { gdb_byte val[16]; struct type *type; - } typed_val_decfloat; + } typed_val_float; struct type *tval; struct stoken sval; struct typed_stoken tsval; @@ -127,7 +123,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); #endif %} -%type exp exp1 type_exp start variable qualified_name lcurly +%type exp exp1 type_exp start variable qualified_name lcurly function_method %type rcurly %type type typebase %type nonempty_typelist func_mod parameter_typelist @@ -142,7 +138,6 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %token INT %token FLOAT -%token DECFLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, and both convey their data as strings. @@ -179,7 +174,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %token NAME_OR_INT %token OPERATOR -%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON +%token STRUCT CLASS UNION ENUM SIZEOF ALIGNOF UNSIGNED COLONCOLON %token TEMPLATE %token ERROR %token NEW DELETE @@ -313,6 +308,10 @@ exp : SIZEOF exp %prec UNARY { write_exp_elt_opcode (pstate, UNOP_SIZEOF); } ; +exp : ALIGNOF '(' type_exp ')' %prec UNARY + { write_exp_elt_opcode (pstate, UNOP_ALIGNOF); } + ; + exp : exp ARROW name { write_exp_elt_opcode (pstate, STRUCTOP_PTR); write_exp_string (pstate, $3); @@ -498,6 +497,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,13 +550,18 @@ 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; LONGEST len = VEC_length (type_ptr, type_list); write_exp_elt_opcode (pstate, TYPE_INSTANCE); + /* Save the const/volatile qualifiers as + recorded by the const_or_volatile + production's actions. */ + write_exp_elt_longcst (pstate, + follow_type_instance_flags ()); write_exp_elt_longcst (pstate, len); for (i = 0; VEC_iterate (type_ptr, type_list, i, type_elt); @@ -557,6 +573,36 @@ exp : exp '(' parameter_typelist ')' const_or_volatile } ; +function_method_void: exp '(' ')' const_or_volatile + { write_exp_elt_opcode (pstate, TYPE_INSTANCE); + /* See above. */ + write_exp_elt_longcst (pstate, + follow_type_instance_flags ()); + 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; } ; @@ -702,17 +748,10 @@ exp : NAME_OR_INT exp : FLOAT - { write_exp_elt_opcode (pstate, OP_DOUBLE); - write_exp_elt_type (pstate, $1.type); - write_exp_elt_dblcst (pstate, $1.dval); - write_exp_elt_opcode (pstate, OP_DOUBLE); } - ; - -exp : DECFLOAT - { write_exp_elt_opcode (pstate, OP_DECFLOAT); + { write_exp_elt_opcode (pstate, OP_FLOAT); write_exp_elt_type (pstate, $1.type); - write_exp_elt_decfloatcst (pstate, $1.val); - write_exp_elt_opcode (pstate, OP_DECFLOAT); } + write_exp_elt_floatcst (pstate, $1.val); + write_exp_elt_opcode (pstate, OP_FLOAT); } ; exp : variable @@ -915,12 +954,8 @@ variable: block COLONCOLON name error (_("No symbol \"%s\" in specified context."), copy_name ($3)); if (symbol_read_needs_frame (sym.symbol)) - { - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; - } + + innermost_block.update (sym); write_exp_elt_opcode (pstate, OP_VAR_VALUE); write_exp_elt_block (pstate, sym.block); @@ -1009,27 +1044,31 @@ variable: name_not_typename if (sym.symbol) { if (symbol_read_needs_frame (sym.symbol)) + innermost_block.update (sym); + + /* If we found a function, see if it's + an ifunc resolver that has the same + address as the ifunc symbol itself. + If so, prefer the ifunc symbol. */ + + bound_minimal_symbol resolver + = find_gnu_ifunc (sym.symbol); + if (resolver.minsym != NULL) + write_exp_msymbol (pstate, resolver); + else { - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; + write_exp_elt_opcode (pstate, OP_VAR_VALUE); + write_exp_elt_block (pstate, sym.block); + write_exp_elt_sym (pstate, sym.symbol); + write_exp_elt_opcode (pstate, OP_VAR_VALUE); } - - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - write_exp_elt_block (pstate, sym.block); - write_exp_elt_sym (pstate, sym.symbol); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); } else if ($1.is_a_field_of_this) { /* C++: it hangs off of `this'. Must not inadvertently convert from a method call to data ref. */ - if (innermost_block == 0 - || contained_in (sym.block, - innermost_block)) - innermost_block = sym.block; + innermost_block.update (sym); write_exp_elt_opcode (pstate, OP_THIS); write_exp_elt_opcode (pstate, OP_THIS); write_exp_elt_opcode (pstate, STRUCTOP_PTR); @@ -1038,18 +1077,41 @@ 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 + = ((msymbol.minsym->type != mst_text_gnu_ifunc + && msymbol.minsym->type != mst_data_gnu_ifunc) + ? find_function_alias_target (msymbol) + : NULL); + 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); } } ; @@ -1487,7 +1549,7 @@ oper: OPERATOR NEW | OPERATOR '>' { $$ = operator_stoken (">"); } | OPERATOR ASSIGN_MODIFY - { const char *op = "unknown"; + { const char *op = " unknown"; switch ($2) { case BINOP_RSH: @@ -1563,7 +1625,13 @@ oper: OPERATOR NEW c_print_type ($2, NULL, &buf, -1, 0, &type_print_raw_options); - $$ = operator_stoken (buf.c_str ()); + + /* This also needs canonicalization. */ + std::string canon + = cp_canonicalize_string (buf.c_str ()); + if (canon.empty ()) + canon = std::move (buf.string ()); + $$ = operator_stoken ((" " + canon).c_str ()); } ; @@ -1625,13 +1693,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; @@ -1720,49 +1787,49 @@ parse_number (struct parser_state *par_state, if (parsed_float) { - /* If it ends at "df", "dd" or "dl", take it as type of decimal floating - point. Return DECFLOAT. */ - + /* Handle suffixes for decimal floating-point: "df", "dd" or "dl". */ if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f') { - p[len - 2] = '\0'; - putithere->typed_val_decfloat.type + putithere->typed_val_float.type = parse_type (par_state)->builtin_decfloat; - decimal_from_string (putithere->typed_val_decfloat.val, 4, - gdbarch_byte_order (parse_gdbarch (par_state)), - p); - p[len - 2] = 'd'; - return DECFLOAT; + len -= 2; } - - if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd') + else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd') { - p[len - 2] = '\0'; - putithere->typed_val_decfloat.type + putithere->typed_val_float.type = parse_type (par_state)->builtin_decdouble; - decimal_from_string (putithere->typed_val_decfloat.val, 8, - gdbarch_byte_order (parse_gdbarch (par_state)), - p); - p[len - 2] = 'd'; - return DECFLOAT; + len -= 2; } - - if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l') + else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l') { - p[len - 2] = '\0'; - putithere->typed_val_decfloat.type + putithere->typed_val_float.type = parse_type (par_state)->builtin_declong; - decimal_from_string (putithere->typed_val_decfloat.val, 16, - gdbarch_byte_order (parse_gdbarch (par_state)), - p); - p[len - 2] = 'd'; - return DECFLOAT; + len -= 2; + } + /* Handle suffixes: 'f' for float, 'l' for long double. */ + else if (len >= 1 && TOLOWER (p[len - 1]) == 'f') + { + putithere->typed_val_float.type + = parse_type (par_state)->builtin_float; + len -= 1; + } + else if (len >= 1 && TOLOWER (p[len - 1]) == 'l') + { + putithere->typed_val_float.type + = parse_type (par_state)->builtin_long_double; + len -= 1; + } + /* Default type for floating-point literals is double. */ + else + { + putithere->typed_val_float.type + = parse_type (par_state)->builtin_double; } - if (! parse_c_float (parse_gdbarch (par_state), p, len, - &putithere->typed_val_float.dval, - &putithere->typed_val_float.type)) - return ERROR; + if (!parse_float (p, len, + putithere->typed_val_float.type, + putithere->typed_val_float.val)) + return ERROR; return FLOAT; } @@ -1957,9 +2024,9 @@ c_parse_escape (const char **ptr, struct obstack *output) if (output) obstack_grow_str (output, "\\x"); ++tokptr; - if (!isxdigit (*tokptr)) + if (!ISXDIGIT (*tokptr)) error (_("\\x escape without a following hex digit")); - while (isxdigit (*tokptr)) + while (ISXDIGIT (*tokptr)) { if (output) obstack_1grow (output, *tokptr); @@ -1982,7 +2049,7 @@ c_parse_escape (const char **ptr, struct obstack *output) if (output) obstack_grow_str (output, "\\"); for (i = 0; - i < 3 && isdigit (*tokptr) && *tokptr != '8' && *tokptr != '9'; + i < 3 && ISDIGIT (*tokptr) && *tokptr != '8' && *tokptr != '9'; ++i) { if (output) @@ -2007,9 +2074,9 @@ c_parse_escape (const char **ptr, struct obstack *output) obstack_1grow (output, *tokptr); } ++tokptr; - if (!isxdigit (*tokptr)) + if (!ISXDIGIT (*tokptr)) error (_("\\%c escape without a following hex digit"), c); - for (i = 0; i < len && isxdigit (*tokptr); ++i) + for (i = 0; i < len && ISXDIGIT (*tokptr); ++i) { if (output) obstack_1grow (output, *tokptr); @@ -2267,6 +2334,8 @@ static const struct token ident_tokens[] = {"struct", STRUCT, OP_NULL, 0}, {"signed", SIGNED_KEYWORD, OP_NULL, 0}, {"sizeof", SIZEOF, OP_NULL, 0}, + {"_Alignof", ALIGNOF, OP_NULL, 0}, + {"alignof", ALIGNOF, OP_NULL, FLAG_CXX}, {"double", DOUBLE_KEYWORD, OP_NULL, 0}, {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX}, {"class", CLASS, OP_NULL, FLAG_CXX}, @@ -2400,24 +2469,23 @@ static struct macro_scope *expression_macro_scope; static int saw_name_at_eof; /* This is set if the previously-returned token was a structure - operator -- either '.' or ARROW. This is used only when parsing to - do field name completion. */ -static int last_was_structop; + operator -- either '.' or ARROW. */ +static bool last_was_structop; /* Read one token, getting characters through lexptr. */ static int -lex_one_token (struct parser_state *par_state, int *is_quoted_name) +lex_one_token (struct parser_state *par_state, bool *is_quoted_name) { int c; int namelen; unsigned int i; const char *tokstart; - int saw_structop = last_was_structop; + bool saw_structop = last_was_structop; char *copy; - last_was_structop = 0; - *is_quoted_name = 0; + last_was_structop = false; + *is_quoted_name = false; retry: @@ -2458,7 +2526,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) lexptr += 2; yylval.opcode = tokentab2[i].opcode; - if (parse_completion && tokentab2[i].token == ARROW) + if (tokentab2[i].token == ARROW) last_was_structop = 1; return tokentab2[i].token; } @@ -2482,7 +2550,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) saw_name_at_eof = 0; return COMPLETE; } - else if (saw_structop) + else if (parse_completion && saw_structop) return COMPLETE; else return 0; @@ -2522,11 +2590,10 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) /* Might be a floating point number. */ if (lexptr[1] < '0' || lexptr[1] > '9') { - if (parse_completion) - last_was_structop = 1; + last_was_structop = true; goto symbol; /* Nope, must be a symbol. */ } - /* FALL THRU into number case. */ + /* FALL THRU. */ case '0': case '1': @@ -2602,7 +2669,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) size_t len = strlen ("selector"); if (strncmp (p, "selector", len) == 0 - && (p[len] == '\0' || isspace (p[len]))) + && (p[len] == '\0' || ISSPACE (p[len]))) { lexptr = p + len; return SELECTOR; @@ -2611,9 +2678,9 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) goto parse_string; } - while (isspace (*p)) + while (ISSPACE (*p)) p++; - if (strncmp (p, "entry", len) == 0 && !isalnum (p[len]) + if (strncmp (p, "entry", len) == 0 && !c_ident_is_alnum (p[len]) && p[len] != '_') { lexptr = &p[len]; @@ -2664,7 +2731,7 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) { ++tokstart; namelen = lexptr - tokstart - 1; - *is_quoted_name = 1; + *is_quoted_name = true; goto tryname; } @@ -2675,16 +2742,14 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) } } - if (!(c == '_' || c == '$' - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) + if (!(c == '_' || c == '$' || c_ident_is_alpha (c))) /* We must have come across a bad character (e.g. ';'). */ error (_("Invalid character '%c' in expression."), c); /* It's a name. See how long it is. */ namelen = 0; for (c = tokstart[namelen]; - (c == '_' || c == '$' || (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');) + (c == '_' || c == '$' || c_ident_is_alnum (c) || c == '<');) { /* Template parameter lists are part of the name. FIXME: This mishandles `print $a<4&&$a>3'. */ @@ -2789,34 +2854,33 @@ lex_one_token (struct parser_state *par_state, int *is_quoted_name) } /* An object of this type is pushed on a FIFO by the "outer" lexer. */ -typedef struct +struct token_and_value { int token; YYSTYPE value; -} token_and_value; - -DEF_VEC_O (token_and_value); +}; /* A FIFO of tokens that have been read but not yet returned to the parser. */ -static VEC (token_and_value) *token_fifo; +static std::vector token_fifo; /* Non-zero if the lexer should return tokens from the FIFO. */ 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 in which lookups start; this can be NULL to mean the global scope. IS_QUOTED_NAME is non-zero if the name token was originally quoted - in single quotes. */ + in single quotes. IS_AFTER_STRUCTOP is true if this name follows + a structure operator -- either '.' or ARROW */ static int classify_name (struct parser_state *par_state, const struct block *block, - int is_quoted_name) + bool is_quoted_name, bool is_after_structop) { struct block_symbol bsym; char *copy; @@ -2860,11 +2924,13 @@ classify_name (struct parser_state *par_state, const struct block *block, } } - /* If we found a field, then we want to prefer it over a + /* If we found a field on the "this" object, or we are looking + up a field on a struct, then we want to prefer it over a filename. However, if the name was quoted, then it is better to check for a filename or a block, since this is the only way the user has of requiring the extension to be used. */ - if (is_a_field_of_this.type == NULL || is_quoted_name) + if ((is_a_field_of_this.type == NULL && !is_after_structop) + || is_quoted_name) { /* See if it's a file name. */ struct symtab *symtab; @@ -2945,7 +3011,7 @@ classify_inner_name (struct parser_state *par_state, char *copy; if (context == NULL) - return classify_name (par_state, block, 0); + return classify_name (par_state, block, false, false); type = check_typedef (context); if (!type_aggregate_p (type)) @@ -3019,19 +3085,21 @@ yylex (void) struct type *context_type = NULL; int last_to_examine, next_to_examine, checkpoint; const struct block *search_block; - int is_quoted_name; + bool is_quoted_name, last_lex_was_structop; - if (popping && !VEC_empty (token_and_value, token_fifo)) + if (popping && !token_fifo.empty ()) goto do_pop; popping = 0; + last_lex_was_structop = last_was_structop; + /* 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 (pstate, &is_quoted_name); if (current.token == NAME) current.token = classify_name (pstate, expression_context_block, - is_quoted_name); + is_quoted_name, last_lex_was_structop); if (parse_language (pstate)->la_language != language_cplus || (current.token != TYPENAME && current.token != COLONCOLON && current.token != FILENAME)) @@ -3040,17 +3108,17 @@ yylex (void) /* Read any sequence of alternating "::" and name-like tokens into the token FIFO. */ current.value = yylval; - VEC_safe_push (token_and_value, token_fifo, ¤t); + token_fifo.push_back (current); last_was_coloncolon = current.token == COLONCOLON; while (1) { - int ignore; + bool ignore; /* We ignore quoted names other than the very first one. Subsequent ones do not have any special meaning. */ current.token = lex_one_token (pstate, &ignore); current.value = yylval; - VEC_safe_push (token_and_value, token_fifo, ¤t); + token_fifo.push_back (current); if ((last_was_coloncolon && current.token != NAME) || (!last_was_coloncolon && current.token != COLONCOLON)) @@ -3061,13 +3129,13 @@ yylex (void) /* 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; + last_to_examine = token_fifo.size () - 2; next_to_examine = 0; - current = *VEC_index (token_and_value, token_fifo, next_to_examine); + current = 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; @@ -3088,16 +3156,16 @@ yylex (void) while (next_to_examine <= last_to_examine) { - token_and_value *next; + token_and_value next; - next = VEC_index (token_and_value, token_fifo, next_to_examine); + next = token_fifo[next_to_examine]; ++next_to_examine; - if (next->token == NAME && last_was_coloncolon) + if (next.token == NAME && last_was_coloncolon) { int classification; - yylval = next->value; + yylval = next.value; classification = classify_inner_name (pstate, search_block, context_type); /* We keep going until we either run out of names, or until @@ -3114,8 +3182,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 = (const char *) obstack_base (&name_obstack); yylval.sval.length = obstack_object_size (&name_obstack); @@ -3129,7 +3197,7 @@ 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 { @@ -3147,14 +3215,15 @@ yylex (void) current.value.sval.ptr, current.value.sval.length); - VEC_replace (token_and_value, token_fifo, 0, ¤t); + token_fifo[0] = current; if (checkpoint > 1) - VEC_block_remove (token_and_value, token_fifo, 1, checkpoint - 1); + token_fifo.erase (token_fifo.begin () + 1, + token_fifo.begin () + checkpoint); } do_pop: - current = *VEC_index (token_and_value, token_fifo, 0); - VEC_ordered_remove (token_and_value, token_fifo, 0); + current = token_fifo[0]; + token_fifo.erase (token_fifo.begin ()); yylval = current.value; return current.token; } @@ -3166,39 +3235,39 @@ c_parse (struct parser_state *par_state) struct cleanup *back_to; /* Setting up the parser state. */ + scoped_restore pstate_restore = make_scoped_restore (&pstate); gdb_assert (par_state != NULL); pstate = par_state; - back_to = make_cleanup (free_current_contents, &expression_macro_scope); - make_cleanup_clear_parser_state (&pstate); - - /* Set up the scope for macro expansion. */ - expression_macro_scope = NULL; + gdb::unique_xmalloc_ptr macro_scope; if (expression_context_block) - expression_macro_scope - = sal_macro_scope (find_pc_line (expression_context_pc, 0)); + macro_scope = sal_macro_scope (find_pc_line (expression_context_pc, 0)); else - expression_macro_scope = default_macro_scope (); - if (! expression_macro_scope) - expression_macro_scope = user_macro_scope (); + macro_scope = default_macro_scope (); + if (! macro_scope) + macro_scope = user_macro_scope (); + + scoped_restore restore_macro_scope + = make_scoped_restore (&expression_macro_scope, macro_scope.get ()); /* Initialize macro expansion code. */ obstack_init (&expansion_obstack); gdb_assert (! macro_original_text); - make_cleanup (scan_macro_cleanup, 0); + /* Note that parsing (within yyparse) freely installs cleanups + assuming they'll be run here (below). */ + back_to = make_cleanup (scan_macro_cleanup, 0); scoped_restore restore_yydebug = make_scoped_restore (&yydebug, parser_debug); /* Initialize some state used by the lexer. */ - last_was_structop = 0; + last_was_structop = false; saw_name_at_eof = 0; - VEC_free (token_and_value, token_fifo); + token_fifo.clear (); popping = 0; - obstack_init (&name_obstack); - make_cleanup_obstack_free (&name_obstack); + name_obstack.clear (); result = yyparse (); do_cleanups (back_to); @@ -3264,11 +3333,11 @@ c_print_token (FILE *file, int type, YYSTYPE value) #endif -void +static void yyerror (const char *msg) { if (prev_lexptr) lexptr = prev_lexptr; - error (_("A %s in expression, near `%s'."), (msg ? msg : "error"), lexptr); + error (_("A %s in expression, near `%s'."), msg, lexptr); }