2018-08-20 Nathan Sidwell <nathan@acm.org>
+ * include/cpplib.h (NODE_BUILTIN, NODE_MACRO_ARG): Delete.
+ Renumber others.
+ (enum node_type): Replace NT_MACRO with NT_USER_MACRO,
+ NT_BUILTIN_MACRO, NT_MACRO_ARG. Delete NT_ASSERTION.
+ (NTV_MACRO, NTV_ANSWER, NTV_BUILTIN, NTV_ARGUMENT, NTV_NONE):
+ Delete.
+ (CPP_HASHNODE_VALUE_IDX): Delete.
+ (union _cpp_hashnode_value): GTY tag from enum node_type directly.
+ (struct cpp_hashnode): Adjust GTY desc for value field.
+ (cpp_user_macro_p, cpp_builtin_macro_p, cpp_macro_p): Adjust.
+ * directives.c (undefine_macros): Clear value.anwers, adjust flag
+ clearing.
+ (_cpp_test_assertion): No need to check NT_ASSERTION.
+ (do_assert, do_unassert): Likewise.
+ * init.c (cpp_init_special_builtins): Set type not flags.
+ * macro.c (struct macro_arg_saved_data): Add type field.
+ (cpp_get_token_1): Check type not NT_VOID.
+ (_cpp_free_definition): Adjust flag clearing. Nullify
+ value.answers.
+ (_cpp_save_parameter, _cpp_unsave_parameters): Save and restore
+ type.
+ (lex_expansion_token): Check type not flags.
+ (_cpp_create_definition): Set type to NT_USER_MACRO.
+ (_cpp_notify_macro_use): Adjust type checking.
+ * pch.c (write_macdef, count_defs, write_defs, cpp_valid_state)
+ (save_macros): Adjust node type/flag handling.
+ * traditional.c (_cpp_scan_out_logical_line): Check type not flags.
+
* directives.c (do_undef): Use cpp_macro_p & cpp_builtin_macro_p.
* include/cpplib.h (enum cpp_macro_kind): Remove trailing comma.
(cpp_fun_like_macro_p): Make inline, define.
/* Body of _cpp_free_definition inlined here for speed.
Macros and assertions no longer have anything to free. */
h->type = NT_VOID;
- h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED);
+ h->value.answers = NULL;
+ h->flags &= ~(NODE_POISONED|NODE_DISABLED|NODE_USED);
return 1;
}
}
/* Parses an assertion directive of type TYPE, returning a pointer to
- the hash node of the predicate, or 0 on error. If an answer was
- supplied, it is placed in EXP_PTR & EXP_COUNT, which is otherwise
- set to 0. */
+ the hash node of the predicate, or 0 on error. The node is
+ guaranteed to be disjoint from the macro namespace, so can only
+ have type 'NT_VOID'. If an answer was supplied, it is placed in
+ *ANSWER_PTR, which is otherwise set to 0. */
static cpp_hashnode *
parse_assertion (cpp_reader *pfile, int type, cpp_macro **answer_ptr)
{
if (node)
{
- if (node->type == NT_ASSERTION)
+ if (node->value.answers)
*value = !answer || *find_answer (node, answer);
}
else if (pfile->cur_token[-1].type == CPP_EOF)
{
/* Place the new answer in the answer list. First check there
is not a duplicate. */
- if (node->type == NT_ASSERTION && *find_answer (node, answer))
+ if (*find_answer (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);
- if (node->type == NT_ASSERTION)
- answer->parm.next = node->value.answers;
-
- node->type = NT_ASSERTION;
+ /* Chain into the list. */
+ answer->parm.next = node->value.answers;
node->value.answers = answer;
check_eol (pfile, false);
cpp_hashnode *node = parse_assertion (pfile, T_UNASSERT, &answer);
/* It isn't an error to #unassert something that isn't asserted. */
- if (node && node->type == NT_ASSERTION)
+ if (node)
{
if (answer)
{
/* Remove the assert from the list. */
if (cpp_macro *temp = *p)
- {
- *p = temp->parm.next;
- /* Did we free the last answer? */
- if (!*p)
- node->type = NT_VOID;
- }
+ *p = temp->parm.next;
check_eol (pfile, false);
}
} 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_ASSERTION), 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
+/* 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_BUILTIN (1 << 2) /* Builtin macro. */
-#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_MACRO_ARG (1 << 6) /* Used during #define processing. */
-#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_MACRO, /* A macro of some form. */
- NT_ASSERTION /* Predicate for #assert. */
+ NT_VOID = 0, /* Maybe an assert? */
+ NT_MACRO_ARG, /* A macro arg. */
+ NT_USER_MACRO, /* A user macro. */
+ NT_BUILTIN_MACRO, /* A builtin macro. */
+ NT_MACRO_MASK = NT_USER_MACRO /* Mask for either macro kind. */
};
/* Different flavors of builtin macro. _Pragma is an operator, but we
#define NODE_LEN(NODE) HT_LEN (&(NODE)->ident)
#define NODE_NAME(NODE) HT_STR (&(NODE)->ident)
-/* Specify which field, if any, of the union is used. */
-
-enum {
- NTV_MACRO,
- NTV_ANSWER,
- NTV_BUILTIN,
- NTV_ARGUMENT,
- NTV_NONE
-};
-
-#define CPP_HASHNODE_VALUE_IDX(HNODE) \
- ((HNODE.flags & NODE_MACRO_ARG) ? NTV_ARGUMENT \
- : HNODE.type == NT_MACRO ? ((HNODE.flags & NODE_BUILTIN) \
- ? NTV_BUILTIN : NTV_MACRO) \
- : HNODE.type == NT_ASSERTION ? NTV_ANSWER \
- : NTV_NONE)
-
/* The common part of an identifier node shared amongst all 3 C front
ends. Also used to store CPP identifiers, which are a superset of
identifiers in the grammatical sense. */
union GTY(()) _cpp_hashnode_value {
- /* If a macro. */
- cpp_macro * GTY((tag ("NTV_MACRO"))) macro;
- /* Answers to an assertion. */
- cpp_macro * GTY ((tag ("NTV_ANSWER"))) answers;
+ /* Assert (maybe NULL) */
+ cpp_macro * GTY((tag ("NT_VOID"))) answers;
+ /* Macro (never NULL) */
+ cpp_macro * GTY((tag ("NT_USER_MACRO"))) macro;
/* Code for a builtin macro. */
- enum cpp_builtin_type GTY ((tag ("NTV_BUILTIN"))) builtin;
+ enum cpp_builtin_type GTY ((tag ("NT_BUILTIN_MACRO"))) builtin;
/* Macro argument index. */
- unsigned short GTY ((tag ("NTV_ARGUMENT"))) arg_index;
+ unsigned short GTY ((tag ("NT_MACRO_ARG"))) arg_index;
};
struct GTY(()) cpp_hashnode {
ENUM_BITFIELD(node_type) type : 6; /* CPP node type. */
unsigned int flags : 10; /* CPP flags. */
- union _cpp_hashnode_value GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value;
+ union _cpp_hashnode_value GTY ((desc ("%1.type"))) value;
};
/* A class for iterating through the source locations within a
source_location *);
inline bool cpp_user_macro_p (const cpp_hashnode *node)
{
- return node->type == NT_MACRO && !(node->flags & NODE_BUILTIN);
+ return node->type == NT_USER_MACRO;
+
}
inline bool cpp_builtin_macro_p (const cpp_hashnode *node)
{
- return node->flags & NODE_BUILTIN;
+ return node->type == NT_BUILTIN_MACRO;
}
inline bool cpp_macro_p (const cpp_hashnode *node)
{
- return node->type == NT_MACRO;
+ return node->type & NT_MACRO_MASK;
}
/* Returns true if NODE is a function-like user macro. */
inline bool cpp_fun_like_macro_p (cpp_hashnode *node)
|| pfile->cb.has_attribute == NULL))
continue;
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->type = NT_MACRO;
- hp->flags |= NODE_BUILTIN;
+ hp->type = NT_BUILTIN_MACRO;
if (b->always_warn_if_redefined)
hp->flags |= NODE_WARN;
hp->value.builtin = (enum cpp_builtin_type) b->value;
struct macro_arg_saved_data {
/* The canonical (UTF-8) spelling of this identifier. */
cpp_hashnode *canonical_node;
- /* The previous value of this identifier. */
+ /* The previous value & type of this identifier. */
union _cpp_hashnode_value value;
+ node_type type;
};
static const char *vaopt_paste_error =
node = result->val.node.node;
- if (node->type != NT_MACRO || (result->flags & NO_EXPAND))
+ if (node->type == NT_VOID || (result->flags & NO_EXPAND))
break;
if (!(node->flags & NODE_DISABLED))
{
/* Macros and assertions no longer have anything to free. */
h->type = NT_VOID;
- /* Clear builtin flag in case of redefinition. */
- h->flags &= ~(NODE_BUILTIN | NODE_DISABLED | NODE_USED);
+ h->value.answers = NULL;
+ h->flags &= ~(NODE_DISABLED | NODE_USED);
}
/* Save parameter NODE (spelling SPELLING) to the parameter list of
cpp_hashnode *spelling)
{
/* Constraint 6.10.3.6 - duplicate parameter names. */
- if (node->flags & NODE_MACRO_ARG)
+ if (node->type == NT_MACRO_ARG)
{
cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"",
NODE_NAME (node));
macro_arg_saved_data *saved = (macro_arg_saved_data *)pfile->macro_buffer;
saved[n].canonical_node = node;
saved[n].value = node->value;
+ saved[n].type = node->type;
void *base = _cpp_reserve_room (pfile, n * sizeof (cpp_hashnode *),
sizeof (cpp_hashnode *));
((cpp_hashnode **)base)[n] = spelling;
/* Morph into a macro arg. */
- node->flags |= NODE_MACRO_ARG;
+ node->type = NT_MACRO_ARG;
/* Index is 1 based. */
node->value.arg_index = n + 1;
&((struct macro_arg_saved_data *) pfile->macro_buffer)[n];
struct cpp_hashnode *node = save->canonical_node;
+ node->type = save->type;
node->value = save->value;
- node->flags &= ~NODE_MACRO_ARG;
}
}
| name '...'
| '...'
*/
+
static bool
parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr)
{
pfile->cur_token = saved_cur_token;
/* Is this a parameter? */
- if (token->type == CPP_NAME
- && (token->val.node.node->flags & NODE_MACRO_ARG) != 0)
+ if (token->type == CPP_NAME && token->val.node.node->type == NT_MACRO_ARG)
{
+ /* Morph into a parameter reference. */
cpp_hashnode *spelling = token->val.node.spelling;
token->type = CPP_MACRO_ARG;
token->val.macro_arg.arg_no = token->val.node.node->value.arg_index;
}
/* Enter definition in hash table. */
- node->type = NT_MACRO;
+ node->type = NT_USER_MACRO;
node->value.macro = macro;
if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))
&& ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_FORMAT_MACROS")
node->flags |= NODE_USED;
switch (node->type)
{
- case NT_MACRO:
- if (!(node->flags & NODE_BUILTIN))
- {
- cpp_macro *macro = node->value.macro;
- if (macro->lazy)
- {
- pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1);
- macro->lazy = 0;
- }
- }
+ case NT_USER_MACRO:
+ {
+ cpp_macro *macro = node->value.macro;
+ if (macro->lazy)
+ {
+ pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1);
+ macro->lazy = 0;
+ }
+ }
+ /* FALLTHROUGH. */
+ case NT_BUILTIN_MACRO:
if (pfile->cb.used_define)
pfile->cb.used_define (pfile, pfile->directive_line, node);
break;
write_macdef (cpp_reader *pfile, cpp_hashnode *hn, void *file_p)
{
FILE *f = (FILE *) file_p;
+ bool is_void = false;
switch (hn->type)
{
case NT_VOID:
if (! (hn->flags & NODE_POISONED))
return 1;
- /* XXX Really fallthru? */
- /* FALLTHRU */
+ is_void = true;
+ goto poisoned;
- case NT_MACRO:
- if (hn->flags & NODE_BUILTIN)
- return 1;
-
- {
- struct macrodef_struct s;
- const unsigned char *defn;
+ case NT_BUILTIN_MACRO:
+ return 1;
- s.name_length = NODE_LEN (hn);
- s.flags = hn->flags & NODE_POISONED;
+ case NT_USER_MACRO:
+ if (hn->value.macro->kind != cmk_assert)
+ {
+ poisoned:
+ struct macrodef_struct s;
+ const unsigned char *defn;
- if (hn->type == NT_MACRO)
- {
- defn = cpp_macro_definition (pfile, hn);
- s.definition_length = ustrlen (defn);
- }
- else
- {
- defn = NODE_NAME (hn);
- s.definition_length = s.name_length;
- }
+ s.name_length = NODE_LEN (hn);
+ s.flags = hn->flags & NODE_POISONED;
- if (fwrite (&s, sizeof (s), 1, f) != 1
- || fwrite (defn, 1, s.definition_length, f) != s.definition_length)
- {
- cpp_errno (pfile, CPP_DL_ERROR,
- "while writing precompiled header");
- return 0;
- }
- }
- return 1;
+ if (is_void)
+ {
+ defn = NODE_NAME (hn);
+ s.definition_length = s.name_length;
+ }
+ else
+ {
+ defn = cpp_macro_definition (pfile, hn);
+ s.definition_length = ustrlen (defn);
+ }
- case NT_ASSERTION:
- /* Not currently implemented. */
+ if (fwrite (&s, sizeof (s), 1, f) != 1
+ || fwrite (defn, 1, s.definition_length, f) != s.definition_length)
+ {
+ cpp_errno (pfile, CPP_DL_ERROR,
+ "while writing precompiled header");
+ return 0;
+ }
+ }
return 1;
default:
switch (hn->type)
{
- case NT_MACRO:
- if (hn->flags & NODE_BUILTIN)
+ case NT_BUILTIN_MACRO:
+ return 1;
+
+ case NT_USER_MACRO:
+ if (hn->value.macro->kind == cmk_assert)
return 1;
/* fall through. */
}
return 1;
- case NT_ASSERTION:
- /* Not currently implemented. */
- return 1;
-
default:
abort ();
}
switch (hn->type)
{
- case NT_MACRO:
- if (hn->flags & NODE_BUILTIN)
+ case NT_BUILTIN_MACRO:
+ return 1;
+
+ case NT_USER_MACRO:
+ if (hn->value.macro->kind == cmk_assert)
return 1;
/* fall through. */
}
return 1;
- case NT_ASSERTION:
- /* Not currently implemented. */
- return 1;
-
default:
abort ();
}
goto fail;
}
- if (h->type != NT_MACRO)
+ if (h->type == NT_VOID)
{
/* It's ok if __GCC_HAVE_DWARF2_CFI_ASM becomes undefined,
as in, when the PCH file is created with -g and we're
{
struct save_macro_data *data = (struct save_macro_data *)data_p;
- if (h->type != NT_VOID
- && (h->flags & NODE_BUILTIN) == 0)
+ if (cpp_user_macro_p (h))
{
if (data->count == data->array_size)
{
data->defns = XRESIZEVEC (uchar *, data->defns, (data->array_size));
}
- switch (h->type)
- {
- case NT_ASSERTION:
- /* Not currently implemented. */
- return 1;
-
- case NT_MACRO:
- {
- const uchar * defn = cpp_macro_definition (r, h);
- size_t defnlen = ustrlen (defn);
+ const uchar * defn = cpp_macro_definition (r, h);
+ size_t defnlen = ustrlen (defn);
- data->defns[data->count] = (uchar *) xmemdup (defn, defnlen,
- defnlen + 2);
- data->defns[data->count][defnlen] = '\n';
- }
- break;
-
- default:
- abort ();
- }
+ data->defns[data->count] = (uchar *) xmemdup (defn, defnlen, defnlen + 2);
+ data->defns[data->count][defnlen] = '\n';
data->count++;
}
+
return 1;
}
goto new_context;
}
}
- else if (macro && (node->flags & NODE_MACRO_ARG) != 0)
+ else if (macro && node->type == NT_MACRO_ARG)
{
/* Found a parameter in the replacement text of a
#define. Remove its name from the output. */