source_location);
static bool parse_answer (cpp_reader *, int, source_location, cpp_macro **);
static cpp_hashnode *parse_assertion (cpp_reader *, int, cpp_macro **);
-static cpp_macro **find_answer (cpp_hashnode *, const cpp_macro *);
+static cpp_macro **find_assert (cpp_hashnode *, const cpp_macro *);
static void handle_assertion (cpp_reader *, const char *, int);
static void do_pragma_push_macro (cpp_reader *);
static void do_pragma_pop_macro (cpp_reader *);
Macros and assertions no longer have anything to free. */
h->type = NT_VOID;
h->flags &= ~(NODE_POISONED|NODE_DISABLED|NODE_USED);
- h->value.macro = NULL;
+ h->value.assert = NULL;
return 1;
}
/* Returns a pointer to the pointer to CANDIDATE in the answer chain,
or a pointer to NULL if the answer is not in the chain. */
static cpp_macro **
-find_answer (cpp_hashnode *node, const cpp_macro *candidate)
+find_assert (cpp_hashnode *node, const cpp_macro *candidate)
{
unsigned int i;
cpp_macro **result = NULL;
- for (result = &node->value.macro; *result; result = &(*result)->parm.next)
+ for (result = &node->value.assert; *result; result = &(*result)->parm.next)
{
cpp_macro *answer = *result;
if (node)
{
- if (node->value.macro)
- *value = !answer || *find_answer (node, answer);
+ if (node->value.assert)
+ *value = !answer || *find_assert (node, answer);
}
else if (pfile->cur_token[-1].type == CPP_EOF)
_cpp_backup_tokens (pfile, 1);
{
/* Place the new answer in the answer list. First check there
is not a duplicate. */
- if (*find_answer (node, answer))
+ if (*find_assert (node, answer))
{
cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted",
NODE_NAME (node) + 1);
(pfile, sizeof (cpp_macro) - sizeof (cpp_token)
+ sizeof (cpp_token) * answer->count);
- answer->parm.next = node->value.macro;
+ answer->parm.next = node->value.assert;
- node->type = NT_USER_MACRO;
- node->value.macro = answer;
+ node->value.assert = answer;
check_eol (pfile, false);
}
{
if (answer)
{
- cpp_macro **p = find_answer (node, answer), *temp;
+ cpp_macro **p = find_assert (node, answer);
- /* Remove the answer from the list. */
- temp = *p;
- if (temp)
+ /* Remove the assert from the list. */
+ if (cpp_macro *temp = *p)
*p = temp->parm.next;
- /* Did we free the last answer? */
- if (node->value.macro == 0)
- node->type = NT_VOID;
-
check_eol (pfile, false);
}
else
} GTY ((desc ("%1.kind == cmk_traditional"))) exp;
};
-/* The structure of a node in the hash table. The hash table has
- entries for all identifiers: either macros defined by #define
- commands (type NT_MACRO), assertions created with #assert
- (NT_MACRO), or neither of the above (NT_VOID). Builtin macros
- like __LINE__ are flagged NODE_BUILTIN. Poisoned identifiers are
- flagged NODE_POISONED. NODE_OPERATOR (C++ only) indicates an
- identifier that behaves like an operator such as "xor".
- NODE_DIAGNOSTIC is for speed in lex_token: it indicates a
- diagnostic may be required for this node. Currently this only
- applies to __VA_ARGS__, poisoned identifiers, and -Wc++-compat
- warnings about NODE_OPERATOR. */
-
/* Hash node flags. */
#define NODE_OPERATOR (1 << 0) /* C++ named operator. */
#define NODE_POISONED (1 << 1) /* Poisoned identifier. */
-
-#define NODE_DIAGNOSTIC (1 << 3) /* Possible diagnostic when lexed. */
-#define NODE_WARN (1 << 4) /* Warn if redefined or undefined. */
-#define NODE_DISABLED (1 << 5) /* A disabled macro. */
-
-#define NODE_USED (1 << 7) /* Dumped with -dU. */
-#define NODE_CONDITIONAL (1 << 8) /* Conditional macro */
-#define NODE_WARN_OPERATOR (1 << 9) /* Warn about C++ named operator. */
+#define NODE_DIAGNOSTIC (1 << 2) /* Possible diagnostic when lexed. */
+#define NODE_WARN (1 << 3) /* Warn if redefined or undefined. */
+#define NODE_DISABLED (1 << 4) /* A disabled macro. */
+#define NODE_USED (1 << 5) /* Dumped with -dU. */
+#define NODE_CONDITIONAL (1 << 6) /* Conditional macro */
+#define NODE_WARN_OPERATOR (1 << 7) /* Warn about C++ named operator. */
/* Different flavors of hash node. */
enum node_type
{
- NT_VOID = 0, /* No definition yet. */
+ NT_VOID = 0, /* Maybe an assert? */
NT_MACRO_ARG, /* A macro arg. */
- NT_USER_MACRO, /* A user macro or assert (#node). */
+ NT_USER_MACRO, /* A user macro. */
NT_BUILTIN_MACRO /* A builtin macro. */
};
identifiers in the grammatical sense. */
union GTY(()) _cpp_hashnode_value {
- /* Macro or assert */
+ /* Assert (maybe NULL) */
+ cpp_macro * GTY((tag ("NT_VOID"))) assert;
+ /* Macro (never NULL) */
cpp_macro * GTY((tag ("NT_USER_MACRO"))) macro;
/* Code for a builtin macro. */
enum cpp_builtin_type GTY ((tag ("NT_BUILTIN_MACRO"))) builtin;
then index into directive table.
Otherwise, a NODE_OPERATOR. */
unsigned char rid_code; /* Rid code - for front ends. */
- ENUM_BITFIELD(node_type) type : 6; /* CPP node type. */
- unsigned int flags : 10; /* CPP flags. */
+ ENUM_BITFIELD(node_type) type : 2; /* CPP node type. */
+ unsigned int flags : 14; /* CPP flags. */
+
+ /* 32-bits of padding on 64-bit arch. We could shrink this by
+ making ht_identifier hold an offset to a trailing string value.
+ That would require FE's expose their IDENTIFIER_NODE size to
+ us. */
union _cpp_hashnode_value GTY ((desc ("%1.type"))) value;
};
source_location *);
inline bool cpp_user_macro_p (const cpp_hashnode *node)
{
- return node->type == NT_USER_MACRO && node->value.macro->kind != cmk_assert;
+ return node->type == NT_USER_MACRO;
}
inline bool cpp_builtin_macro_p (const cpp_hashnode *node)
{
return node->type == NT_BUILTIN_MACRO;
}
-/* Although a macro may actually turn out to be an assert, they are
- separated by namespace, in that the latter have special
- '#'-starting names, that macros cannot have. We don't have to
- check that here. */
inline bool cpp_macro_p (const cpp_hashnode *node)
{
return node->type & NT_USER_MACRO;