From patchwork Wed Aug 15 17:26:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 957987 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-483724-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="P6nz1Dh8"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41rGbf25fFz9sCR for ; Thu, 16 Aug 2018 03:26:36 +1000 (AEST) Received: (qmail 2073 invoked by alias); 15 Aug 2018 17:26:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 632 invoked by uid 89); 15 Aug 2018 17:26:28 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=PCH, pch, pixel, top-level X-HELO: mail-yw1-f44.google.com Received: from mail-yw1-f44.google.com (HELO mail-yw1-f44.google.com) (209.85.161.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 15 Aug 2018 17:26:23 +0000 Received: by mail-yw1-f44.google.com with SMTP id z143-v6so1376088ywa.7 for ; Wed, 15 Aug 2018 10:26:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:cc:from:subject:message-id:date:user-agent:mime-version :content-language; bh=pmUGyvtNiOaOYologm/mlTaJjod9MBLlDs/hlZStC5o=; b=P6nz1Dh8ufJ4tPhMZ7c4nnkcqgfmsAJlY2uH2MFfxHtxHWuDy370s3FYLCDSQ1qpN3 sLpbSxgqJFjwGDVmU6CU6RI6uBCXTOucApQEGHOYJGO+RFE/L6qau+BW7QKLHuJzi0l8 Yq14Bk6BPIR1NaYLjyPW51Z8dKGEW9Zw6H5jTlH1mENFp0mfFWo5OsTfGvvhoqx/A6/P jCxxeopLVzZzTKjGaJQFMDO878phKuRFuGlAQZdnk2a2EV8x5haPt1ZqFW051p0q1X27 gTLfwWQJ+O4cfxe2mdf0OSEiTsPJinErFYCT5PR1JnBP0YtcwI1fIm0c4lIBPVU+MfXk vXiQ== Received: from ?IPv6:2620:10d:c0a1:1102:495f:7267:5ff:a250? ([2620:10d:c091:180::1:7f62]) by smtp.googlemail.com with ESMTPSA id c18-v6sm10469625ywb.62.2018.08.15.10.26.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Aug 2018 10:26:21 -0700 (PDT) Sender: Nathan Sidwell To: GCC Patches Cc: David Edelsohn From: Nathan Sidwell Subject: [PATCH] CPP Macro predicates Message-ID: <91e24b8c-9b93-dcf4-5834-822b896488c9@acm.org> Date: Wed, 15 Aug 2018 13:26:19 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 I've been working on a cleanup of the preprocessor's macro machinery, this is the first patch of that series. 1) Introduce a set of inline predicates for detecting if an identifier is a macro of some kind. The implementation of those predicates will change, but the users will not need further changes. 2) We have a bunch of places in the preprocessor to call the macro use hook. Broken out into a single worker function and call it there. booted & tested on x86_64-linux, and built and tested on powerpc64le-linux, as that uses the conditional macro machinery for its vector keyword extension. I'll commit in a day or so, as the non-preprocessor changes are obvious. nathan 2018-08-15 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. 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. Index: gcc/c-family/c-ada-spec.c =================================================================== --- gcc/c-family/c-ada-spec.c (revision 263558) +++ gcc/c-family/c-ada-spec.c (working copy) @@ -171,13 +171,12 @@ static int count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED) { - const cpp_macro *macro = node->value.macro; - - if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN) - && macro->count - && *NODE_NAME (node) != '_' - && LOCATION_FILE (macro->line) == macro_source_file) - max_ada_macros++; + if (cpp_user_macro_p (node) && *NODE_NAME (node) != '_') + { + const cpp_macro *macro = node->value.macro; + if (macro->count && LOCATION_FILE (macro->line) == macro_source_file) + max_ada_macros++; + } return 1; } @@ -190,15 +189,13 @@ static int store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node, void *macros) { - const cpp_macro *macro = node->value.macro; - - if (node->type == NT_MACRO - && !(node->flags & NODE_BUILTIN) - && macro->count - && *NODE_NAME (node) != '_' - && LOCATION_FILE (macro->line) == macro_source_file) - ((cpp_hashnode **) macros)[store_ada_macro_index++] = node; - + if (cpp_user_macro_p (node) && *NODE_NAME (node) != '_') + { + const cpp_macro *macro = node->value.macro; + if (macro->count + && LOCATION_FILE (macro->line) == macro_source_file) + ((cpp_hashnode **) macros)[store_ada_macro_index++] = node; + } return 1; } Index: gcc/c-family/c-ppoutput.c =================================================================== --- gcc/c-family/c-ppoutput.c (revision 263558) +++ gcc/c-family/c-ppoutput.c (working copy) @@ -532,13 +532,14 @@ static void cb_used_define (cpp_reader *pfile, source_location line ATTRIBUTE_UNUSED, cpp_hashnode *node) { - macro_queue *q; - if (node->flags & NODE_BUILTIN) - return; - q = XNEW (macro_queue); - q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node)); - q->next = define_queue; - define_queue = q; + if (cpp_user_macro_p (node)) + { + macro_queue *q; + q = XNEW (macro_queue); + q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node)); + q->next = define_queue; + define_queue = q; + } } static void @@ -688,7 +689,7 @@ cb_def_pragma (cpp_reader *pfile, source static int dump_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)) { fputs ("#define ", print.outf); fputs ((const char *) cpp_macro_definition (pfile, node), Index: gcc/c-family/c-spellcheck.cc =================================================================== --- gcc/c-family/c-spellcheck.cc (revision 263558) +++ gcc/c-family/c-spellcheck.cc (working copy) @@ -45,13 +45,13 @@ name_reserved_for_implementation_p (cons static bool should_suggest_as_macro_p (cpp_hashnode *hashnode) { - if (hashnode->type != NT_MACRO) + if (!cpp_macro_p (hashnode)) return false; - /* Don't suggest names reserved for the implementation, but do suggest the builtin - macros such as __FILE__, __LINE__ etc. */ - if (name_reserved_for_implementation_p ((const char *)hashnode->ident.str) - && !(hashnode->flags & NODE_BUILTIN)) + /* Don't suggest names reserved for the implementation, but do + suggest the builtin macros such as __FILE__, __LINE__ etc. */ + if (cpp_user_macro_p (hashnode) + && name_reserved_for_implementation_p ((const char *)hashnode->ident.str)) return false; return true; Index: gcc/config/powerpcspe/powerpcspe-c.c =================================================================== --- gcc/config/powerpcspe/powerpcspe-c.c (revision 263558) +++ gcc/config/powerpcspe/powerpcspe-c.c (working copy) @@ -220,21 +220,22 @@ rs6000_macro_to_expand (cpp_reader *pfil else if (ident && (ident != C_CPP_HASHNODE (__vector_keyword))) { enum rid rid_code = (enum rid)(ident->rid_code); - enum node_type itype = ident->type; + bool is_macro = cpp_macro_p (ident); + /* If there is a function-like macro, check if it is going to be invoked with or without arguments. Without following ( treat it like non-macro, otherwise the following cpp_get_token eats what should be preserved. */ - if (itype == NT_MACRO && cpp_fun_like_macro_p (ident)) + if (is_macro && cpp_fun_like_macro_p (ident)) { int idx2 = idx; do tok = cpp_peek_token (pfile, idx2++); while (tok->type == CPP_PADDING); if (tok->type != CPP_OPEN_PAREN) - itype = NT_VOID; + is_macro = false; } - if (itype == NT_MACRO) + if (is_macro) { do (void) cpp_get_token (pfile); Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (revision 263558) +++ gcc/config/rs6000/rs6000-c.c (working copy) @@ -220,21 +220,23 @@ rs6000_macro_to_expand (cpp_reader *pfil else if (ident && (ident != C_CPP_HASHNODE (__vector_keyword))) { enum rid rid_code = (enum rid)(ident->rid_code); - enum node_type itype = ident->type; + bool is_macro = cpp_macro_p (ident); + /* If there is a function-like macro, check if it is going to be invoked with or without arguments. Without following ( treat it like non-macro, otherwise the following cpp_get_token eats what should be preserved. */ - if (itype == NT_MACRO && cpp_fun_like_macro_p (ident)) + if (is_macro && cpp_fun_like_macro_p (ident)) { int idx2 = idx; do tok = cpp_peek_token (pfile, idx2++); while (tok->type == CPP_PADDING); if (tok->type != CPP_OPEN_PAREN) - itype = NT_VOID; + is_macro = false; } - if (itype == NT_MACRO) + + if (is_macro) { do (void) cpp_get_token (pfile); Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 263558) +++ gcc/cp/name-lookup.c (working copy) @@ -5954,10 +5954,10 @@ lookup_name_fuzzy (tree name, enum looku /* If we have an exact match for a macro name, then either the macro was used with the wrong argument count, or the macro has been used before it was defined. */ - cpp_hashnode *macro = bmm.blithely_get_best_candidate (); - if (macro && (macro->flags & NODE_BUILTIN) == 0) - return name_hint (NULL, - macro_use_before_def::maybe_make (loc, macro)); + if (cpp_hashnode *macro = bmm.blithely_get_best_candidate ()) + if (cpp_user_macro_p (macro)) + return name_hint (NULL, + macro_use_before_def::maybe_make (loc, macro)); } /* Try the "starts_decl_specifier_p" keywords to detect Index: gcc/fortran/cpp.c =================================================================== --- gcc/fortran/cpp.c (revision 263558) +++ gcc/fortran/cpp.c (working copy) @@ -990,7 +990,7 @@ cb_include (cpp_reader *pfile ATTRIBUTE_ static int dump_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)) { fputs ("#define ", print.outf); fputs ((const char *) cpp_macro_definition (pfile, node), Index: libcpp/directives.c =================================================================== --- libcpp/directives.c (revision 263558) +++ libcpp/directives.c (working copy) @@ -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, s 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, s 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) { Index: libcpp/expr.c =================================================================== --- libcpp/expr.c (revision 263558) +++ libcpp/expr.c (working copy) @@ -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; } Index: libcpp/files.c =================================================================== --- libcpp/files.c (revision 263558) +++ libcpp/files.c (working copy) @@ -805,7 +805,7 @@ should_stack_file (cpp_reader *pfile, _c /* 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. */ Index: libcpp/identifiers.c =================================================================== --- libcpp/identifiers.c (revision 263558) +++ libcpp/identifiers.c (working copy) @@ -104,8 +104,8 @@ cpp_defined (cpp_reader *pfile, const un 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 Index: libcpp/include/cpplib.h =================================================================== --- libcpp/include/cpplib.h (revision 263558) +++ libcpp/include/cpplib.h (working copy) @@ -890,7 +890,21 @@ extern int cpp_avoid_paste (cpp_reader * 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 *); Index: libcpp/internal.h =================================================================== --- libcpp/internal.h (revision 263558) +++ libcpp/internal.h (working copy) @@ -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 *); Index: libcpp/lex.c =================================================================== --- libcpp/lex.c (revision 263558) +++ libcpp/lex.c (working copy) @@ -1627,7 +1627,7 @@ is_macro(cpp_reader *pfile, const uchar 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 Index: libcpp/macro.c =================================================================== --- libcpp/macro.c (revision 263558) +++ libcpp/macro.c (working copy) @@ -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, 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, 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 *pfil 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 *pfil 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 Index: libcpp/traditional.c =================================================================== --- libcpp/traditional.c (revision 263558) +++ libcpp/traditional.c (working copy) @@ -325,7 +325,7 @@ _cpp_read_logical_line_trad (cpp_reader 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, 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 * 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 * 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 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);