aboutsummaryrefslogtreecommitdiff
path: root/gdb/c-exp.y
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/c-exp.y')
-rw-r--r--gdb/c-exp.y472
1 files changed, 288 insertions, 184 deletions
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index f53a138..11f0d88 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -35,7 +35,6 @@
%{
-#include <ctype.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
@@ -106,8 +105,35 @@ struct c_parse_state
/* The type stack. */
struct type_stack type_stack;
+
+ /* When set, a name token is not looked up. This can be useful when
+ the search domain is known by context. TYPE_CODE_UNDEF is used
+ to mean "unset" here -- typically only types with tags (enum,
+ struct, class, union) use this feature, but TYPE_CODE_VOID is
+ also used to avoid the lookup for field names. */
+ type_code assume_classification = TYPE_CODE_UNDEF;
+};
+
+/* Used for field names, which skip name lookup. */
+struct qualified_name_token
+{
+ /* The prefix, if any. This can be nullptr. */
+ const char *prefix;
+ /* The field name itself. */
+ const char *name;
+ /* True if the COMPLETE token was seen. */
+ bool complete;
};
+/* A convenient overload of copy_name. */
+static std::string
+copy_name (qualified_name_token token)
+{
+ if (token.prefix == nullptr)
+ return token.name;
+ return std::string (token.prefix) + "::" + token.name;
+}
+
/* This is set and cleared in c_parse. */
static struct c_parse_state *cpstate;
@@ -120,6 +146,8 @@ static void yyerror (const char *);
static int type_aggregate_p (struct type *);
+static void handle_qualified_field_name (qualified_name_token token);
+
using namespace expr;
%}
@@ -140,6 +168,7 @@ using namespace expr;
} typed_val_float;
struct type *tval;
struct stoken sval;
+ qualified_name_token qval;
struct typed_stoken tsval;
struct ttype tsym;
struct symtoken ssym;
@@ -160,7 +189,7 @@ using namespace expr;
static int parse_number (struct parser_state *par_state,
const char *, int, int, YYSTYPE *);
static struct stoken operator_stoken (const char *);
-static struct stoken typename_stoken (const char *);
+static qualified_name_token typename_stoken (const char *);
static void check_parameter_typelist (std::vector<struct type *> *);
#if defined(YYBISON) && YYBISON < 30800
@@ -171,7 +200,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly function_method
%type <lval> rcurly
-%type <tval> type typebase scalar_type
+%type <tval> type typebase scalar_type tag_name_or_complete
%type <tvec> nonempty_typelist func_mod parameter_typelist
/* %type <bval> block */
@@ -202,7 +231,9 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
%token <voidval> COMPLETE
%token <tsym> TYPENAME
%token <theclass> CLASSNAME /* ObjC Class name */
-%type <sval> name field_name
+%type <sval> name
+%type <qval> qual_field_name field_name field_name_or_complete
+%type <qval> field_or_destructor
%type <svec> string_exp
%type <ssym> name_not_typename
%type <tsym> type_name
@@ -364,117 +395,73 @@ exp : ALIGNOF '(' type_exp ')' %prec UNARY
{ pstate->wrap<unop_alignof_operation> (); }
;
-exp : exp ARROW field_name
+exp : exp ARROW
{
- pstate->push_new<structop_ptr_operation>
- (pstate->pop (), copy_name ($3));
+ cpstate->assume_classification = TYPE_CODE_VOID;
}
- ;
-
-exp : exp ARROW field_name COMPLETE
+ field_name_or_complete
{
- structop_base_operation *op
- = new structop_ptr_operation (pstate->pop (),
- copy_name ($3));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
- }
- ;
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
-exp : exp ARROW COMPLETE
- {
- structop_base_operation *op
- = new structop_ptr_operation (pstate->pop (), "");
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
- }
- ;
-
-exp : exp ARROW '~' name
- {
- pstate->push_new<structop_ptr_operation>
- (pstate->pop (), "~" + copy_name ($4));
- }
- ;
-
-exp : exp ARROW '~' name COMPLETE
- {
- structop_base_operation *op
- = new structop_ptr_operation (pstate->pop (),
- "~" + copy_name ($4));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
+ if ($4.prefix != nullptr)
+ {
+ handle_qualified_field_name ($4);
+ /* exp->type::name becomes exp->*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ pstate->wrap<unop_addr_operation> ();
+ pstate->wrap2<structop_mptr_operation> ();
+ }
+ else
+ {
+ structop_base_operation *op
+ = new structop_ptr_operation (pstate->pop (),
+ copy_name ($4));
+ if ($4.complete)
+ pstate->mark_struct_expression (op);
+ pstate->push (operation_up (op));
+ }
}
;
-exp : exp ARROW qualified_name
- { /* exp->type::name becomes exp->*(&type::name) */
- /* Note: this doesn't work if name is a
- static member! FIXME */
- pstate->wrap<unop_addr_operation> ();
- pstate->wrap2<structop_mptr_operation> (); }
- ;
-
exp : exp ARROW_STAR exp
{ pstate->wrap2<structop_mptr_operation> (); }
;
-exp : exp '.' field_name
- {
- if (pstate->language ()->la_language
- == language_opencl)
- pstate->push_new<opencl_structop_operation>
- (pstate->pop (), copy_name ($3));
- else
- pstate->push_new<structop_operation>
- (pstate->pop (), copy_name ($3));
- }
- ;
-
-exp : exp '.' field_name COMPLETE
- {
- structop_base_operation *op
- = new structop_operation (pstate->pop (),
- copy_name ($3));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
- }
- ;
-
-exp : exp '.' COMPLETE
+exp : exp '.'
{
- structop_base_operation *op
- = new structop_operation (pstate->pop (), "");
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
+ cpstate->assume_classification = TYPE_CODE_VOID;
}
- ;
-
-exp : exp '.' '~' name
+ field_name_or_complete
{
- pstate->push_new<structop_operation>
- (pstate->pop (), "~" + copy_name ($4));
- }
- ;
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
-exp : exp '.' '~' name COMPLETE
- {
- structop_base_operation *op
- = new structop_operation (pstate->pop (),
- "~" + copy_name ($4));
- pstate->mark_struct_expression (op);
- pstate->push (operation_up (op));
+ if ($4.prefix != nullptr)
+ {
+ handle_qualified_field_name ($4);
+ /* exp.type::name becomes exp.*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ pstate->wrap<unop_addr_operation> ();
+ pstate->wrap2<structop_member_operation> ();
+ }
+ else if (pstate->language ()->la_language
+ == language_opencl
+ && !$4.complete)
+ pstate->push_new<opencl_structop_operation>
+ (pstate->pop (), copy_name ($4));
+ else
+ {
+ structop_base_operation *op
+ = new structop_operation (pstate->pop (),
+ copy_name ($4));
+ if ($4.complete)
+ pstate->mark_struct_expression (op);
+ pstate->push (operation_up (op));
+ }
}
;
-exp : exp '.' qualified_name
- { /* exp.type::name becomes exp.*(&type::name) */
- /* Note: this doesn't work if name is a
- static member! FIXME */
- pstate->wrap<unop_addr_operation> ();
- pstate->wrap2<structop_member_operation> (); }
- ;
-
exp : exp DOT_STAR exp
{ pstate->wrap2<structop_member_operation> (); }
;
@@ -1261,12 +1248,12 @@ single_qualifier:
{ cpstate->type_stack.insert (tp_restrict); }
| '@' NAME
{
- cpstate->type_stack.insert (pstate,
+ cpstate->type_stack.insert (pstate->gdbarch (),
copy_name ($2.stoken).c_str ());
}
| '@' UNKNOWN_CPP_NAME
{
- cpstate->type_stack.insert (pstate,
+ cpstate->type_stack.insert (pstate->gdbarch (),
copy_name ($2.stoken).c_str ());
}
;
@@ -1316,15 +1303,13 @@ direct_abs_decl: '(' abs_decl ')'
| direct_abs_decl array_mod
{
cpstate->type_stack.push ($1);
- cpstate->type_stack.push ($2);
- cpstate->type_stack.push (tp_array);
+ cpstate->type_stack.push (tp_array, $2);
$$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$);
}
| array_mod
{
- cpstate->type_stack.push ($1);
- cpstate->type_stack.push (tp_array);
+ cpstate->type_stack.push (tp_array, $1);
$$ = cpstate->type_stack.create ();
cpstate->type_stacks.emplace_back ($$);
}
@@ -1504,71 +1489,37 @@ typebase
{
$$ = init_complex_type (nullptr, $2);
}
- | STRUCT name
- { $$
- = lookup_struct (copy_name ($2).c_str (),
- pstate->expression_context_block);
- }
- | STRUCT COMPLETE
+ | STRUCT
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_STRUCT;
}
- | STRUCT name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- $2.ptr, $2.length);
- $$ = NULL;
+ $$ = $3;
}
- | CLASS name
- { $$ = lookup_struct
- (copy_name ($2).c_str (),
- pstate->expression_context_block);
- }
- | CLASS COMPLETE
+ | CLASS
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_STRUCT;
}
- | CLASS name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_STRUCT,
- $2.ptr, $2.length);
- $$ = NULL;
- }
- | UNION name
- { $$
- = lookup_union (copy_name ($2).c_str (),
- pstate->expression_context_block);
+ $$ = $3;
}
- | UNION COMPLETE
+ | ENUM
{
- pstate->mark_completion_tag (TYPE_CODE_UNION,
- "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_ENUM;
}
- | UNION name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_UNION,
- $2.ptr, $2.length);
- $$ = NULL;
+ $$ = $3;
}
- | ENUM name
- { $$ = lookup_enum (copy_name ($2).c_str (),
- pstate->expression_context_block);
- }
- | ENUM COMPLETE
+ | UNION
{
- pstate->mark_completion_tag (TYPE_CODE_ENUM, "", 0);
- $$ = NULL;
+ cpstate->assume_classification = TYPE_CODE_UNION;
}
- | ENUM name COMPLETE
+ tag_name_or_complete
{
- pstate->mark_completion_tag (TYPE_CODE_ENUM, $2.ptr,
- $2.length);
- $$ = NULL;
+ $$ = $3;
}
/* It appears that this rule for templates is never
reduced; template recognition happens by lookahead
@@ -1793,13 +1744,66 @@ oper: OPERATOR NEW
}
;
+qual_field_name:
+ qual_field_name COLONCOLON name
+ {
+ $$.complete = false;
+ if ($1.prefix == nullptr)
+ $$.prefix = $1.name;
+ else
+ $$.prefix = obconcat (&cpstate->expansion_obstack,
+ $1.prefix, "::", $1.name, nullptr);
+ $$.name = obstack_strndup (&cpstate->expansion_obstack,
+ $3.ptr, $3.length);
+ }
+ | name
+ {
+ $$.complete = false;
+ $$.prefix = nullptr;
+ $$.name = obstack_strndup (&cpstate->expansion_obstack,
+ $1.ptr, $1.length);
+ }
+ ;
+
+field_or_destructor:
+ qual_field_name
+ | qual_field_name COLONCOLON '~' name
+ {
+ $$.complete = false;
+ if ($1.prefix == nullptr)
+ $$.prefix = $1.name;
+ else
+ $$.prefix = obconcat (&cpstate->expansion_obstack,
+ $1.prefix, "::", $1.name, nullptr);
+ char *name
+ = (char *) obstack_alloc (&cpstate->expansion_obstack,
+ $4.length + 2);
+ name[0] = '~';
+ memcpy (&name[1], $4.ptr, $4.length);
+ name[$4.length + 1] = '\0';
+ $$.name = name;
+ }
+ | '~' name
+ {
+ $$.complete = false;
+ $$.prefix = nullptr;
+ char *name
+ = (char *) obstack_alloc (&cpstate->expansion_obstack,
+ $2.length + 2);
+ name[0] = '~';
+ memcpy (&name[1], $2.ptr, $2.length);
+ name[$2.length + 1] = '\0';
+ $$.name = name;
+ }
+ ;
+
/* This rule exists in order to allow some tokens that would not normally
match the 'name' rule to appear as fields within a struct. The example
that initially motivated this was the RISC-V target which models the
floating point registers as a union with fields called 'float' and
'double'. */
field_name
- : name
+ : field_or_destructor
| DOUBLE_KEYWORD { $$ = typename_stoken ("double"); }
| FLOAT_KEYWORD { $$ = typename_stoken ("float"); }
| INT_KEYWORD { $$ = typename_stoken ("int"); }
@@ -1809,6 +1813,61 @@ field_name
| UNSIGNED { $$ = typename_stoken ("unsigned"); }
;
+field_name_or_complete
+ : field_name
+ | field_name COMPLETE
+ {
+ $$ = $1;
+ $$.complete = true;
+ }
+ | COMPLETE
+ {
+ $$ = typename_stoken ("");
+ $$.complete = true;
+ }
+ ;
+
+/* This rule is used when the preceding token is a keyword that takes
+ a tag name (e.g., "struct"). The "caller" should disable name
+ lookup, see c_parse_state::assume_classification. */
+tag_name_or_complete
+ : NAME
+ {
+ switch (cpstate->assume_classification)
+ {
+ case TYPE_CODE_STRUCT:
+ $$ = lookup_struct (copy_name ($1.stoken).c_str (),
+ pstate->expression_context_block);
+ break;
+ case TYPE_CODE_ENUM:
+ $$ = lookup_enum (copy_name ($1.stoken).c_str (),
+ pstate->expression_context_block);
+ break;
+ case TYPE_CODE_UNION:
+ $$ = lookup_union (copy_name ($1.stoken).c_str (),
+ pstate->expression_context_block);
+ break;
+ default:
+ gdb_assert_not_reached ();
+ }
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
+ }
+ | COMPLETE
+ {
+ pstate->mark_completion_tag (cpstate->assume_classification,
+ "", 0);
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
+ $$ = nullptr;
+ }
+ | NAME COMPLETE
+ {
+ pstate->mark_completion_tag (cpstate->assume_classification,
+ $1.stoken.ptr, $1.stoken.length);
+ cpstate->assume_classification = TYPE_CODE_UNDEF;
+ $$ = nullptr;
+ }
+ ;
+
name : NAME { $$ = $1.stoken; }
| BLOCKNAME { $$ = $1.stoken; }
| TYPENAME { $$ = $1.stoken; }
@@ -1866,12 +1925,10 @@ operator_stoken (const char *op)
/* Returns a stoken of the type named TYPE. */
-static struct stoken
+static qualified_name_token
typename_stoken (const char *type)
{
- struct stoken st = { type, 0 };
- st.length = strlen (type);
- return st;
+ return qualified_name_token { nullptr, type, false };
};
/* Return true if the type is aggregate-like. */
@@ -1969,13 +2026,13 @@ parse_number (struct parser_state *par_state,
len -= 2;
}
/* Handle suffixes: 'f' for float, 'l' for long double. */
- else if (len >= 1 && TOLOWER (buf[len - 1]) == 'f')
+ else if (len >= 1 && c_tolower (buf[len - 1]) == 'f')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_float;
len -= 1;
}
- else if (len >= 1 && TOLOWER (buf[len - 1]) == 'l')
+ else if (len >= 1 && c_tolower (buf[len - 1]) == 'l')
{
putithere->typed_val_float.type
= parse_type (par_state)->builtin_long_double;
@@ -2181,9 +2238,9 @@ c_parse_escape (const char **ptr, struct obstack *output)
if (output)
obstack_grow_str (output, "\\x");
++tokptr;
- if (!ISXDIGIT (*tokptr))
+ if (!c_isxdigit (*tokptr))
error (_("\\x escape without a following hex digit"));
- while (ISXDIGIT (*tokptr))
+ while (c_isxdigit (*tokptr))
{
if (output)
obstack_1grow (output, *tokptr);
@@ -2206,7 +2263,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 && c_isdigit (*tokptr) && *tokptr != '8' && *tokptr != '9';
++i)
{
if (output)
@@ -2231,9 +2288,9 @@ c_parse_escape (const char **ptr, struct obstack *output)
obstack_1grow (output, *tokptr);
}
++tokptr;
- if (!ISXDIGIT (*tokptr))
+ if (!c_isxdigit (*tokptr))
error (_("\\%c escape without a following hex digit"), c);
- for (i = 0; i < len && ISXDIGIT (*tokptr); ++i)
+ for (i = 0; i < len && c_isxdigit (*tokptr); ++i)
{
if (output)
obstack_1grow (output, *tokptr);
@@ -2818,7 +2875,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
size_t len = strlen ("selector");
if (strncmp (p, "selector", len) == 0
- && (p[len] == '\0' || ISSPACE (p[len])))
+ && (p[len] == '\0' || c_isspace (p[len])))
{
pstate->lexptr = p + len;
return SELECTOR;
@@ -2827,7 +2884,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
goto parse_string;
}
- while (ISSPACE (*p))
+ while (c_isspace (*p))
p++;
size_t len = strlen ("entry");
if (strncmp (p, "entry", len) == 0 && !c_ident_is_alnum (p[len])
@@ -3042,15 +3099,11 @@ classify_name (struct parser_state *par_state, const struct block *block,
std::string copy = copy_name (yylval.sval);
- /* Initialize this in case we *don't* use it in this call; that way
- we can refer to it unconditionally below. */
- memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this));
-
bsym = lookup_symbol (copy.c_str (), block, SEARCH_VFT,
par_state->language ()->name_of_this ()
? &is_a_field_of_this : NULL);
- if (bsym.symbol && bsym.symbol->aclass () == LOC_BLOCK)
+ if (bsym.symbol && bsym.symbol->loc_class () == LOC_BLOCK)
{
yylval.ssym.sym = bsym;
yylval.ssym.is_a_field_of_this = is_a_field_of_this.type != NULL;
@@ -3098,7 +3151,7 @@ classify_name (struct parser_state *par_state, const struct block *block,
}
}
- if (bsym.symbol && bsym.symbol->aclass () == LOC_TYPEDEF)
+ if (bsym.symbol && bsym.symbol->loc_class () == LOC_TYPEDEF)
{
yylval.tsym.type = bsym.symbol->type ();
return TYPENAME;
@@ -3193,7 +3246,7 @@ classify_inner_name (struct parser_state *par_state,
return ERROR;
}
- switch (yylval.ssym.sym.symbol->aclass ())
+ switch (yylval.ssym.sym.symbol->loc_class ())
{
case LOC_BLOCK:
case LOC_LABEL:
@@ -3222,6 +3275,48 @@ classify_inner_name (struct parser_state *par_state,
internal_error (_("not reached"));
}
+/* A helper function for the specific case of a qualified field name,
+ like "obj->type1::type2::field". This takes the type prefix
+ ("type1::type2" in the example) and finds the corresponding type.
+ It will either throw an exception, or push a scope_operation on the
+ operation stack. */
+static void
+handle_qualified_field_name (qualified_name_token token)
+{
+ struct type *type = nullptr;
+ std::string accum;
+ for (const auto name : split_name (token.prefix, split_style::CXX))
+ {
+ std::string current (name);
+
+ if (accum.empty ())
+ accum = name;
+ else
+ accum = accum + "::" + current;
+
+ yylval.ssym.stoken.ptr = current.c_str ();
+ yylval.ssym.stoken.length = current.size ();
+ yylval.ssym.sym = {};
+ yylval.ssym.is_a_field_of_this = 0;
+
+ int kind = classify_inner_name (pstate,
+ pstate->expression_context_block,
+ type);
+ if (kind != TYPENAME)
+ error (_("could not find type '%s'"), accum.c_str ());
+
+ type = yylval.tsym.type;
+ }
+
+ type = check_typedef (type);
+ if (!type_aggregate_p (type))
+ error (_("`%s' is not defined as an aggregate type."),
+ TYPE_SAFE_NAME (type));
+ if (token.name[0] == '~')
+ destructor_name_p (token.name, type);
+ pstate->push_new<scope_operation> (type, token.name);
+}
+
/* The outer level of a two-level lexer. This calls the inner lexer
to return tokens. It then either returns these tokens, or
aggregates them into a larger token. This lets us work around a
@@ -3254,12 +3349,16 @@ yylex (void)
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)
+ if (cpstate->assume_classification == TYPE_CODE_UNDEF
+ && current.token == NAME)
current.token = classify_name (pstate, pstate->expression_context_block,
is_quoted_name, last_lex_was_structop);
if (pstate->language ()->la_language != language_cplus
|| (current.token != TYPENAME && current.token != COLONCOLON
- && current.token != FILENAME))
+ && current.token != FILENAME
+ && (cpstate->assume_classification == TYPE_CODE_UNDEF
+ || current.token != NAME))
+ || cpstate->assume_classification == TYPE_CODE_VOID)
return current.token;
/* Read any sequence of alternating "::" and name-like tokens into
@@ -3300,7 +3399,8 @@ yylex (void)
search_block = NULL;
else
{
- gdb_assert (current.token == TYPENAME);
+ gdb_assert (current.token == TYPENAME
+ || cpstate->assume_classification != TYPE_CODE_UNDEF);
search_block = pstate->expression_context_block;
obstack_grow (&name_obstack, current.value.sval.ptr,
current.value.sval.length);
@@ -3323,8 +3423,11 @@ yylex (void)
int classification;
yylval = next.value;
- classification = classify_inner_name (pstate, search_block,
- context_type);
+ if (cpstate->assume_classification != TYPE_CODE_UNDEF)
+ classification = NAME;
+ else
+ classification = classify_inner_name (pstate, 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)
@@ -3334,7 +3437,7 @@ yylex (void)
checkpoint = next_to_examine;
/* Update the partial name we are constructing. */
- if (context_type != NULL)
+ if (next_to_examine > 1)
{
/* We don't want to put a leading "::" into the name. */
obstack_grow_str (&name_obstack, "::");
@@ -3349,7 +3452,8 @@ yylex (void)
last_was_coloncolon = 0;
- if (classification == NAME)
+ if (cpstate->assume_classification == TYPE_CODE_UNDEF
+ && classification == NAME)
break;
context_type = yylval.tsym.type;
@@ -3396,18 +3500,18 @@ c_parse (struct parser_state *par_state)
c_parse_state cstate;
scoped_restore cstate_restore = make_scoped_restore (&cpstate, &cstate);
- gdb::unique_xmalloc_ptr<struct macro_scope> macro_scope;
+ macro_scope macro_scope;
if (par_state->expression_context_block)
macro_scope
= sal_macro_scope (find_pc_line (par_state->expression_context_pc, 0));
else
macro_scope = default_macro_scope ();
- if (! macro_scope)
+ if (!macro_scope.is_valid ())
macro_scope = user_macro_scope ();
scoped_restore restore_macro_scope
- = make_scoped_restore (&expression_macro_scope, macro_scope.get ());
+ = make_scoped_restore (&expression_macro_scope, &macro_scope);
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
par_state->debug);