From 3f6677f418564e634e3b77b0fc385891d1fdf1da Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 16 Aug 2018 13:51:38 +0000 Subject: [PATCH] CPP Macro predicates https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00897.html libcpp/ * include/cpplib.h (cpp_user_macro_p, cpp_builtin_macro_p) (cpp_macro_p): New inlines. * directives.c (do_pragma_poison): Use cpp_macro_p. (do_ifdef, do_ifndef): Likewise. Use _cpp_maybe_notify_macro_use. (cpp_pop_definition): Use cpp_macro_p. Move _cpp_free_definition earlier. Don't zap node directly. * expr.c (parse_defined): Use _cpp_maybe_notify_macro_use & cpp_macro_p. * files.c (should_stack_file): Use cpp_macro_p. * identifiers.c (cpp_defined): Likewise. * internal.h (_cpp_mark_macro): Use cpp_user_macro_p. (_cpp_notify_macro_use): Declare. (_cpp_maybe_notify_macro_use): New inline. * lex.c (is_macro): Use cpp_macro_p. * macro.c (_cpp_warn_if_unused_macro): Use cpp_user_macro_p. (enter_macro_context): Likewise. (_cpp_create_definition): Use cpp_builtin_macro_p, cpp_user_macro_p. Move _cpp_free_definition earlier. (_cpp_notify_macro_use): New, broken out of multiple call sites. * traditional.c (fun_like_macro_p): Use cpp_builtin_macro_p. (maybe_start_funlike, _cpp_scan_out_logical_line) (push_replacement_text): Likewise. gcc/c-family/ * c-ada-spec.c (count_ada_macro): Use cpp_user_macro_p. (store_ada_macro): Likewise. * c-ppoutput.c (cb_used_define, dump_macro): Likewise. * c-spellcheck.cc (should-suggest_as_macro_p): Likewise, gcc/ * config/rs6000/rs6000-c.c (rs6000_macro_to_expend): Use cpp_macro_p. * config/powerpcspc/powerpcspe-c.c (rs6000_macro_to_expend): Likewise. gcc/cp/ * name-lookup.c (lookup_name_fuzzy): Likewise. gcc/fortran/ * cpp.c (dump_macro): Use cpp_user_macro_p. From-SVN: r263587 --- libcpp/ChangeLog | 26 ++++++++++++++++++++++++ libcpp/directives.c | 53 +++++++++---------------------------------------- libcpp/expr.c | 22 +++----------------- libcpp/files.c | 2 +- libcpp/identifiers.c | 4 ++-- libcpp/include/cpplib.h | 16 ++++++++++++++- libcpp/internal.h | 11 +++++++--- libcpp/lex.c | 2 +- libcpp/macro.c | 51 ++++++++++++++++++++++++++++++++++------------- libcpp/traditional.c | 10 +++++----- 10 files changed, 107 insertions(+), 90 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index a39144c..2bab8a7 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,29 @@ +2018-08-16 Nathan Sidwell + + libcpp/ + * include/cpplib.h (cpp_user_macro_p, cpp_builtin_macro_p) + (cpp_macro_p): New inlines. + * directives.c (do_pragma_poison): Use cpp_macro_p. + (do_ifdef, do_ifndef): Likewise. Use _cpp_maybe_notify_macro_use. + (cpp_pop_definition): Use cpp_macro_p. Move _cpp_free_definition + earlier. Don't zap node directly. + * expr.c (parse_defined): Use _cpp_maybe_notify_macro_use & + cpp_macro_p. + * files.c (should_stack_file): Use cpp_macro_p. + * identifiers.c (cpp_defined): Likewise. + * internal.h (_cpp_mark_macro): Use cpp_user_macro_p. + (_cpp_notify_macro_use): Declare. + (_cpp_maybe_notify_macro_use): New inline. + * lex.c (is_macro): Use cpp_macro_p. + * macro.c (_cpp_warn_if_unused_macro): Use cpp_user_macro_p. + (enter_macro_context): Likewise. + (_cpp_create_definition): Use cpp_builtin_macro_p, + cpp_user_macro_p. Move _cpp_free_definition earlier. + (_cpp_notify_macro_use): New, broken out of multiple call sites. + * traditional.c (fun_like_macro_p): Use cpp_builtin_macro_p. + (maybe_start_funlike, _cpp_scan_out_logical_line) + (push_replacement_text): Likewise. + 2018-08-15 David Malcolm * include/line-map.h (struct location_range): Add "m_label" field. diff --git a/libcpp/directives.c b/libcpp/directives.c index 352c591..6ddfce6 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -1666,7 +1666,7 @@ do_pragma_poison (cpp_reader *pfile) if (hp->flags & NODE_POISONED) continue; - if (hp->type == NT_MACRO) + if (cpp_macro_p (hp)) cpp_error (pfile, CPP_DL_WARNING, "poisoning existing macro \"%s\"", NODE_NAME (hp)); _cpp_free_definition (hp); @@ -1960,26 +1960,9 @@ do_ifdef (cpp_reader *pfile) the powerpc and spu ports using conditional macros for 'vector', 'bool', and 'pixel' to act as conditional keywords. This messes up tests like #ifndef bool. */ - skip = (node->type != NT_MACRO - || ((node->flags & NODE_CONDITIONAL) != 0)); + skip = !cpp_macro_p (node) || (node->flags & NODE_CONDITIONAL); _cpp_mark_macro_used (node); - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (node->type == NT_MACRO) - { - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - else - { - if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); - } - } + _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, pfile->directive_line, node); check_eol (pfile, false); @@ -2006,26 +1989,10 @@ do_ifndef (cpp_reader *pfile) the powerpc and spu ports using conditional macros for 'vector', 'bool', and 'pixel' to act as conditional keywords. This messes up tests like #ifndef bool. */ - skip = (node->type == NT_MACRO - && ((node->flags & NODE_CONDITIONAL) == 0)); + skip = (cpp_macro_p (node) + && !(node->flags & NODE_CONDITIONAL)); _cpp_mark_macro_used (node); - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (node->type == NT_MACRO) - { - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - else - { - if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); - } - } + _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, pfile->directive_line, node); check_eol (pfile, false); @@ -2508,18 +2475,18 @@ cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c) if (pfile->cb.before_define) pfile->cb.before_define (pfile); - if (node->type == NT_MACRO) + if (cpp_macro_p (node)) { if (pfile->cb.undef) pfile->cb.undef (pfile, pfile->directive_line, node); if (CPP_OPTION (pfile, warn_unused_macros)) _cpp_warn_if_unused_macro (pfile, node, NULL); + _cpp_free_definition (node); } - if (node->type != NT_VOID) - _cpp_free_definition (node); if (c->is_undef) return; + { size_t namelen; const uchar *dn; @@ -2530,8 +2497,6 @@ cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c) h = cpp_lookup (pfile, c->definition, namelen); dn = c->definition + namelen; - h->type = NT_VOID; - h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED); nbuf = cpp_push_buffer (pfile, dn, ustrchr (dn, '\n') - dn, true); if (nbuf != NULL) { diff --git a/libcpp/expr.c b/libcpp/expr.c index 36c3fc4..201a619 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -1065,23 +1065,7 @@ parse_defined (cpp_reader *pfile) "this use of \"defined\" may not be portable"); _cpp_mark_macro_used (node); - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (node->type == NT_MACRO) - { - if ((node->flags & NODE_BUILTIN) - && pfile->cb.user_builtin_macro) - pfile->cb.user_builtin_macro (pfile, node); - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - else - { - if (pfile->cb.used_undef) - pfile->cb.used_undef (pfile, pfile->directive_line, node); - } - } + _cpp_maybe_notify_macro_use (pfile, node); /* A possible controlling macro of the form #if !defined (). _cpp_parse_expr checks there was no other junk on the line. */ @@ -1097,8 +1081,8 @@ parse_defined (cpp_reader *pfile) result.unsignedp = false; result.high = 0; result.overflow = false; - result.low = (node && node->type == NT_MACRO - && (node->flags & NODE_CONDITIONAL) == 0); + result.low = (node && cpp_macro_p (node) + && !(node->flags & NODE_CONDITIONAL)); return result; } diff --git a/libcpp/files.c b/libcpp/files.c index e8d21b2..08b7c64 100644 --- a/libcpp/files.c +++ b/libcpp/files.c @@ -805,7 +805,7 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import, /* Skip if the file had a header guard and the macro is defined. PCH relies on this appearing before the PCH handler below. */ - if (file->cmacro && file->cmacro->type == NT_MACRO) + if (file->cmacro && cpp_macro_p (file->cmacro)) return false; /* Handle PCH files immediately; don't stack them. */ diff --git a/libcpp/identifiers.c b/libcpp/identifiers.c index 16584a6..3d42d1a 100644 --- a/libcpp/identifiers.c +++ b/libcpp/identifiers.c @@ -104,8 +104,8 @@ cpp_defined (cpp_reader *pfile, const unsigned char *str, int len) node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT)); - /* If it's of type NT_MACRO, it cannot be poisoned. */ - return node && node->type == NT_MACRO; + /* If it's a macro, it cannot have been poisoned. */ + return node && cpp_macro_p (node); } /* We don't need a proxy since the hash table's identifier comes first diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 3ad52d5..99992a2 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -890,7 +890,21 @@ extern int cpp_avoid_paste (cpp_reader *, const cpp_token *, extern const cpp_token *cpp_get_token (cpp_reader *); extern const cpp_token *cpp_get_token_with_location (cpp_reader *, source_location *); -extern bool cpp_fun_like_macro_p (cpp_hashnode *); +inline bool cpp_user_macro_p (const cpp_hashnode *node) +{ + return node->type == NT_MACRO && !(node->flags & NODE_BUILTIN); +} +inline bool cpp_builtin_macro_p (const cpp_hashnode *node) +{ + return node->flags & NODE_BUILTIN; +} +inline bool cpp_macro_p (const cpp_hashnode *node) +{ + return node->type == NT_MACRO; +} +/* Returns true if NODE is a function-like user macro. */ +extern bool cpp_fun_like_macro_p (cpp_hashnode *node); + extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); extern source_location cpp_macro_definition_location (cpp_hashnode *); diff --git a/libcpp/internal.h b/libcpp/internal.h index 782d8e6..dd145ab 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -93,9 +93,8 @@ struct dummy #define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1)) #define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT) -#define _cpp_mark_macro_used(NODE) do { \ - if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN)) \ - (NODE)->value.macro->used = 1; } while (0) +#define _cpp_mark_macro_used(NODE) \ + (cpp_user_macro_p (NODE) ? (NODE)->value.macro->used = 1 : 0) /* A generic memory buffer, and operations on it. */ typedef struct _cpp_buff _cpp_buff; @@ -622,6 +621,12 @@ cpp_in_primary_file (cpp_reader *pfile) } /* In macro.c */ +extern void _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node); +inline void _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) +{ + if (!(node->flags & NODE_USED)) + _cpp_notify_macro_use (pfile, node); +} extern void _cpp_free_definition (cpp_hashnode *); extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *); extern void _cpp_pop_context (cpp_reader *); diff --git a/libcpp/lex.c b/libcpp/lex.c index a2592e0..fa465be 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1627,7 +1627,7 @@ is_macro(cpp_reader *pfile, const uchar *base) cpp_hashnode *result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table, base, cur - base, hash, HT_NO_INSERT)); - return !result ? false : (result->type == NT_MACRO); + return result && cpp_macro_p (result); } /* Returns true if a literal suffix does not have the expected form diff --git a/libcpp/macro.c b/libcpp/macro.c index 683f918..5d4cd78 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -342,7 +342,7 @@ int _cpp_warn_if_unused_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED) { - if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + if (cpp_user_macro_p (node)) { cpp_macro *macro = node->value.macro; @@ -1282,8 +1282,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, pfile->cb.used_define (pfile, pfile->directive_line, node); } - /* Handle standard macros. */ - if (! (node->flags & NODE_BUILTIN)) + if (cpp_user_macro_p (node)) { cpp_macro *macro = node->value.macro; _cpp_buff *pragma_buff = NULL; @@ -1413,10 +1412,8 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, source_location expand_loc; if (/* The top-level macro invocation that triggered the expansion - we are looking at is with a standard macro ... */ - !(pfile->top_most_macro_node->flags & NODE_BUILTIN) - /* ... and it's a function-like macro invocation, */ - && pfile->top_most_macro_node->value.macro->fun_like + we are looking at is with a function-like user macro ... */ + cpp_fun_like_macro_p (pfile->top_most_macro_node) /* ... and we are tracking the macro expansion. */ && CPP_OPTION (pfile, track_macro_expansion)) /* Then the location of the end of the macro invocation is the @@ -3505,25 +3502,23 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) if (warn_of_redefinition (pfile, node, macro)) { - const int reason = ((node->flags & NODE_BUILTIN) - && !(node->flags & NODE_WARN)) - ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE; + const int reason + = (cpp_builtin_macro_p (node) && !(node->flags & NODE_WARN)) + ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE; bool warned = cpp_pedwarning_with_line (pfile, reason, pfile->directive_line, 0, "\"%s\" redefined", NODE_NAME (node)); - if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + if (warned && cpp_user_macro_p (node)) cpp_error_with_line (pfile, CPP_DL_NOTE, node->value.macro->line, 0, "this is the location of the previous definition"); } + _cpp_free_definition (node); } - if (node->type != NT_VOID) - _cpp_free_definition (node); - /* Enter definition in hash table. */ node->type = NT_MACRO; node->value.macro = macro; @@ -3544,6 +3539,34 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) return ok; } +/* Notify the use of NODE in a macro-aware context (i.e. expanding it, + or testing its existance). Also applies any lazy definition. */ + +extern void +_cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node) +{ + node->flags |= NODE_USED; + switch (node->type) + { + case NT_MACRO: + if ((node->flags & NODE_BUILTIN) + && pfile->cb.user_builtin_macro) + pfile->cb.user_builtin_macro (pfile, node); + + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + break; + + case NT_VOID: + if (pfile->cb.used_undef) + pfile->cb.used_undef (pfile, pfile->directive_line, node); + break; + + default: + abort (); + } +} + /* Warn if a token in STRING matches one of a function-like MACRO's parameters. */ static void diff --git a/libcpp/traditional.c b/libcpp/traditional.c index b25d522..aa38ea4 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -325,7 +325,7 @@ _cpp_read_logical_line_trad (cpp_reader *pfile) static inline bool fun_like_macro (cpp_hashnode *node) { - if (node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (node)) return node->value.builtin == BT_HAS_ATTRIBUTE; else return node->value.macro->fun_like; @@ -338,7 +338,7 @@ maybe_start_funlike (cpp_reader *pfile, cpp_hashnode *node, const uchar *start, struct fun_macro *macro) { unsigned int n; - if (node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (node)) n = 1; else n = node->value.macro->paramc; @@ -521,7 +521,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro, out = pfile->out.cur; cur = CUR (context); - if (node->type == NT_MACRO + if (cpp_macro_p (node) /* Should we expand for ls_answer? */ && (lex_state == ls_none || lex_state == ls_fun_open) && !pfile->state.prevent_expansion) @@ -610,7 +610,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro, paren_depth--; if (lex_state == ls_fun_close && paren_depth == 0) { - if (fmacro.node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (fmacro.node)) { /* Handle builtin function-like macros like __has_attribute. The already parsed arguments @@ -839,7 +839,7 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node) const uchar *text; uchar *buf; - if (node->flags & NODE_BUILTIN) + if (cpp_builtin_macro_p (node)) { text = _cpp_builtin_macro_text (pfile, node); len = ustrlen (text); -- cgit v1.1