Make type_stack pushing a bit safer

This changes type_stack to make pushing elements a bit safer: if an
element requires an argument, these are now always pushed at the same
time, rather than separately.

This patch also adds a few comments to help document a bit better.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
Tom Tromey
2025-08-23 11:39:35 -06:00
parent 1faabbe632
commit 8ea36fc9f3
4 changed files with 74 additions and 45 deletions

View File

@@ -1303,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 ($$);
}

View File

@@ -613,11 +613,9 @@ BasicType2:
| '*' BasicType2
{ type_stack->push (tp_pointer); }
| '[' INTEGER_LITERAL ']'
{ type_stack->push ($2.val);
type_stack->push (tp_array); }
{ type_stack->push (tp_array, $2.val); }
| '[' INTEGER_LITERAL ']' BasicType2
{ type_stack->push ($2.val);
type_stack->push (tp_array); }
{ type_stack->push (tp_array, $2.val); }
;
BasicType:

View File

@@ -1159,8 +1159,7 @@ push_kind_type (LONGEST val, struct type *type)
ival = static_cast <int> (val);
}
type_stack->push (ival);
type_stack->push (tp_kind);
type_stack->push (tp_kind, ival);
}
/* Helper function for convert_to_kind_type. */

View File

@@ -26,34 +26,49 @@
struct type;
struct expr_builder;
/* For parsing of complicated types.
An array should be preceded in the list by the size of the array. */
/* The kind of element on the stack of types and qualifiers, used for
parsing complicated types. */
enum type_pieces
{
tp_end = -1,
tp_pointer,
tp_reference,
tp_rvalue_reference,
tp_array,
tp_function,
tp_function_with_arguments,
tp_const,
tp_volatile,
tp_space_identifier,
tp_atomic,
tp_restrict,
tp_type_stack,
tp_kind
};
{
/* This is returned by pop() to indicate that the stack is empty.
Note that it may not be pushed by the user. */
tp_end = -1,
tp_pointer,
tp_reference,
tp_rvalue_reference,
/* An array type, where the dimension is pushed on the stack as
well. */
tp_array,
tp_function,
/* A function with argument types; the types are also pushed on the
stack. */
tp_function_with_arguments,
tp_const,
tp_volatile,
/* An address space identifier. The address space is also pushed on
the stack. */
tp_space_identifier,
tp_atomic,
tp_restrict,
/* A separate type stack, which is also pushed onto this type
stack. */
tp_type_stack,
/* Fortran-specific, specifies the kind. */
tp_kind,
};
/* The stack can contain either an enum type_pieces or an int. */
/* Items on the type stack. */
union type_stack_elt
{
enum type_pieces piece;
int int_val;
struct type_stack *stack_val;
std::vector<struct type *> *typelist_val;
};
{
/* An ordinary type qualifier. */
enum type_pieces piece;
/* An integer value. Currently only used for address spaces. */
int int_val;
/* Another type stack. */
struct type_stack *stack_val;
/* A list of types. */
std::vector<struct type *> *typelist_val;
};
/* The type stack is an instance of this structure. */
@@ -80,18 +95,31 @@ public:
void insert (enum type_pieces tp);
/* Push an ordinary element on the type stack. This can be used for
any element that doesn't require any extra data. */
void push (enum type_pieces tp)
{
/* tp_end can only be returned by this class, not pushed. The
others require a payload on the stack and so can only be pushed
by the appropriate method. */
gdb_assert (tp != tp_end);
gdb_assert (!requires_payload (tp));
type_stack_elt elt;
elt.piece = tp;
m_elements.push_back (elt);
}
void push (int n)
/* Push an element and an integer value onto the stack. The integer
value is pushed first, followed by TP. Only piece kinds that
accept an integer argument are allowed. */
void push (enum type_pieces tp, int n)
{
gdb_assert (tp == tp_array || tp == tp_space_identifier || tp == tp_kind);
type_stack_elt elt;
elt.int_val = n;
m_elements.push_back (elt);
elt.piece = tp;
m_elements.push_back (elt);
}
/* Push the type stack STACK as an element on this type stack. */
@@ -101,11 +129,12 @@ public:
type_stack_elt elt;
elt.stack_val = stack;
m_elements.push_back (elt);
push (tp_type_stack);
elt.piece = tp_type_stack;
m_elements.push_back (elt);
}
/* Push a function type with arguments onto the global type stack.
LIST holds the argument types. If the final item in LIST is NULL,
/* Push a function type with arguments onto this type stack. LIST
holds the argument types. If the final item in LIST is NULL,
then the function will be varargs. */
void push (std::vector<struct type *> *list)
@@ -113,7 +142,8 @@ public:
type_stack_elt elt;
elt.typelist_val = list;
m_elements.push_back (elt);
push (tp_function_with_arguments);
elt.piece = tp_function_with_arguments;
m_elements.push_back (elt);
}
enum type_pieces pop ()
@@ -127,11 +157,7 @@ public:
int pop_int ()
{
if (m_elements.empty ())
{
/* "Can't happen". */
return 0;
}
gdb_assert (!m_elements.empty ());
type_stack_elt elt = m_elements.back ();
m_elements.pop_back ();
return elt.int_val;
@@ -198,6 +224,14 @@ private:
m_elements.insert (m_elements.begin () + slot, element);
}
/* Return true if TP requires some payload element. */
bool requires_payload (type_pieces tp) const
{
return (tp == tp_array || tp == tp_kind || tp == tp_type_stack
|| tp == tp_function_with_arguments
|| tp == tp_space_identifier);
}
/* Elements on the stack. */
std::vector<union type_stack_elt> m_elements;