From patchwork Fri Aug 17 16:06:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 958989 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-483864-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="Hv71LuAT"; 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 41sSkT1zJ1z9s0n for ; Sat, 18 Aug 2018 02:06:40 +1000 (AEST) Received: (qmail 45667 invoked by alias); 17 Aug 2018 16:06:32 -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 45642 invoked by uid 89); 17 Aug 2018 16:06:31 -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=spare, sans, letters X-HELO: mail-yb0-f194.google.com Received: from mail-yb0-f194.google.com (HELO mail-yb0-f194.google.com) (209.85.213.194) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 17 Aug 2018 16:06:28 +0000 Received: by mail-yb0-f194.google.com with SMTP id y130-v6so2118014yby.9 for ; Fri, 17 Aug 2018 09:06:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=ivDgH0x7ZXtHlLD+Ka96rNaD7oSgag9A/YfkHCKcclg=; b=Hv71LuAToP+MfXlLa7jCICYGmSKA1ZUodhP4HK4zUH+NAFJBJO/9xLuh6LhsvHZuHu Ca13ouGehDw6jIWQMfujy7OtjQ6Lr5NY3fUC9ffWuxYc+g98S4SP08LR2kQw3IqUKywi 4riIzEWd8LivZ5IzIrarzH2S4zODFU8NOPFtDaUBewIuw2BZxgpPwQRrvzPorgGKZcZY jD9lUUD9CdcCt/4ZnrlOazKGfyoAeZFv9rEsrMzZ77L2kbwsctUXtu7fk+7pBWLlrJnx fWFzzuq8xTVSqLniPamRWEOy4Nf4kvfE3Iu0vzL1coMpR1dp1+DA2fl1+PC1sW95JaOd G3Nw== Received: from ?IPv6:2620:10d:c0a1:1102:495f:7267:5ff:a250? ([2620:10d:c091:180::1:995c]) by smtp.googlemail.com with ESMTPSA id f5-v6sm1294691ywa.39.2018.08.17.09.06.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Aug 2018 09:06:25 -0700 (PDT) Sender: Nathan Sidwell To: GCC Patches From: Nathan Sidwell Subject: [PATCH] Macro body is trailing array Message-ID: <72e99339-b460-d18e-997c-0395d95afa99@acm.org> Date: Fri, 17 Aug 2018 12:06:23 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 This patch changes the representation of a macro body, rather than be a pointer to an array of tokens, it is a trailing array of tokens. That's only for iso macros, traditional ones are still a pointer to a [segmented] char array. I introduce two helpers to deal with allocation (cpp uses an obstack-like mechanism). We now have to allocate the macro object after parsing the parms, so the macro definition functions get reordered a bit. the new two-value enumeration 'macro_kind' and its storage in a 2-bit bitfield is a bit of foreshadowing :) A couple of uses needed constifying, as we now inherit the qualification of the containing cpp_macro object when looking at its tokens. booted & tested on x86_64-linux. nathan 2018-08-17 Nathan Sidwell libcpp/ * include/cpplib.h (enum cpp_macro_kind): New. (struct cpp_macro): Make body trailing array. Add kind field, delete traditional flag. * internal.h (_cpp_new_macro): Declare. (_cpp_reserve_room): New inline. (_cpp_commit_buf): Declare. (_cpp_create_trad_definition): Return new macro. * lex.c (_cpp_commit_buff): New. * macro.c (macro_real_token_count): Count backwards. (replace_args): Pointer equality not orderedness. (_cpp_save_parameter): Use _cpp_reserve_room. (alloc_expansion_token): Delete. (lex_expansion_token): Return macro pointer. Use _cpp_reserve_room. (create_iso_definition): Allocate macro itself. Adjust for different allocation ordering. (_cpp_new_macro): New. (_cpp_create_definition): Adjust for API changes. * traditional.c (push_replacement_text): Don't set traditional flag. (save_replacement_text): Likewise. (_cpp_create_trad_definition): Allocate macro itself, Adjust for different allocation ordering. gcc/c-family/ * c-ada-spec.c (macro_length, dump_ada_macros): Constify. Index: gcc/c-family/c-ada-spec.c =================================================================== --- gcc/c-family/c-ada-spec.c (revision 263618) +++ gcc/c-family/c-ada-spec.c (working copy) @@ -88,7 +88,7 @@ macro_length (const cpp_macro *macro, in for (j = 0; j < macro->count; j++) { - cpp_token *token = ¯o->exp.tokens[j]; + const cpp_token *token = ¯o->exp.tokens[j]; if (token->flags & PREV_WHITE) (*buffer_len)++; @@ -274,7 +274,7 @@ dump_ada_macros (pretty_printer *pp, con for (i = 0; supported && i < macro->count; i++) { - cpp_token *token = ¯o->exp.tokens[i]; + const cpp_token *token = ¯o->exp.tokens[i]; int is_one = 0; if (token->flags & PREV_WHITE) Index: libcpp/include/cpplib.h =================================================================== --- libcpp/include/cpplib.h (revision 263618) +++ libcpp/include/cpplib.h (working copy) @@ -671,6 +671,12 @@ struct cpp_dir dev_t dev; }; +/* The kind of the cpp_macro. */ +enum cpp_macro_kind { + cmk_macro, /* An ISO macro (token expansion). */ + cmk_traditional, /* A traditional macro (text expansion). */ +}; + /* Each macro definition is recorded in a cpp_macro structure. Variadic macros cannot occur with traditional cpp. */ struct GTY(()) cpp_macro { @@ -683,15 +689,6 @@ struct GTY(()) cpp_macro { length ("%h.paramc"))) params; - /* Replacement tokens (ISO) or replacement text (traditional). See - comment at top of cpptrad.c for how traditional function-like - macros are encoded. */ - union cpp_macro_u - { - cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens; - const unsigned char * GTY ((tag ("1"))) text; - } GTY ((desc ("%1.traditional"))) exp; - /* Definition line number. */ source_location line; @@ -701,6 +698,9 @@ struct GTY(()) cpp_macro { /* Number of parameters. */ unsigned short paramc; + /* The kind of this macro (ISO, trad or assert) */ + unsigned kind : 2; + /* If a function-like macro. */ unsigned int fun_like : 1; @@ -713,13 +713,23 @@ struct GTY(()) cpp_macro { /* Nonzero if it has been expanded or had its existence tested. */ unsigned int used : 1; - /* Indicate which field of 'exp' is in use. */ - unsigned int traditional : 1; - /* Indicate whether the tokens include extra CPP_PASTE tokens at the end to track invalid redefinitions with consecutive CPP_PASTE tokens. */ unsigned int extra_tokens : 1; + + /* 1 bits spare (32-bit). 33 on 64-bit target. */ + + union cpp_exp_u + { + /* Trailing array of replacement tokens (ISO), or assertion body value. */ + cpp_token GTY ((tag ("false"), length ("%1.count"))) tokens[1]; + + /* Pointer to replacement text (traditional). See comment at top + of cpptrad.c for how traditional function-like macros are + encoded. */ + const unsigned char *GTY ((tag ("true"))) text; + } GTY ((desc ("%1.kind == cmk_traditional"))) exp; }; /* The structure of a node in the hash table. The hash table has Index: libcpp/internal.h =================================================================== --- libcpp/internal.h (revision 263618) +++ libcpp/internal.h (working copy) @@ -633,6 +633,7 @@ inline void _cpp_maybe_notify_macro_use if (!(node->flags & NODE_USED)) _cpp_notify_macro_use (pfile, node); } +extern cpp_macro *_cpp_new_macro (cpp_reader *, cpp_macro_kind, void *); extern void _cpp_free_definition (cpp_hashnode *); extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *); extern void _cpp_pop_context (cpp_reader *); @@ -697,6 +698,14 @@ extern void _cpp_init_tokenrun (tokenrun extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *); extern int _cpp_remaining_tokens_num_in_context (cpp_context *); extern void _cpp_init_lexer (void); +static inline void *_cpp_reserve_room (cpp_reader *pfile, size_t have, + size_t extra) +{ + if (BUFF_ROOM (pfile->a_buff) < (have + extra)) + _cpp_extend_buff (pfile, &pfile->a_buff, extra); + return BUFF_FRONT (pfile->a_buff); +} +extern void *_cpp_commit_buff (cpp_reader *pfile, size_t size); /* In init.c. */ extern void _cpp_maybe_push_include_file (cpp_reader *); @@ -733,7 +742,7 @@ extern bool _cpp_read_logical_line_trad extern void _cpp_overlay_buffer (cpp_reader *pfile, const unsigned char *, size_t); extern void _cpp_remove_overlay (cpp_reader *); -extern bool _cpp_create_trad_definition (cpp_reader *, cpp_macro *); +extern cpp_macro *_cpp_create_trad_definition (cpp_reader *); extern bool _cpp_expansions_different_trad (const cpp_macro *, const cpp_macro *); extern unsigned char *_cpp_copy_replacement_text (const cpp_macro *, Index: libcpp/lex.c =================================================================== --- libcpp/lex.c (revision 263618) +++ libcpp/lex.c (working copy) @@ -3725,6 +3725,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, s return result; } +/* Commit or allocate storage from a buffer. */ + +void * +_cpp_commit_buff (cpp_reader *pfile, size_t size) +{ + void *ptr = BUFF_FRONT (pfile->a_buff); + + if (pfile->hash_table->alloc_subobject) + { + void *copy = pfile->hash_table->alloc_subobject (size); + memcpy (copy, ptr, size); + ptr = copy; + } + else + BUFF_FRONT (pfile->a_buff) += size; + + return ptr; +} + /* Say which field of TOK is in use. */ enum cpp_token_fld_kind Index: libcpp/macro.c =================================================================== --- libcpp/macro.c (revision 263618) +++ libcpp/macro.c (working copy) @@ -308,12 +308,11 @@ static void replace_args (cpp_reader *, macro_arg *, source_location); static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *, _cpp_buff **, unsigned *); -static bool create_iso_definition (cpp_reader *, cpp_macro *); +static cpp_macro *create_iso_definition (cpp_reader *); /* #define directive parsing and handling. */ -static cpp_token *alloc_expansion_token (cpp_reader *, cpp_macro *); -static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *); +static cpp_macro *lex_expansion_token (cpp_reader *, cpp_macro *); static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *, const cpp_macro *); static bool parse_params (cpp_reader *, unsigned *, bool *); @@ -1235,13 +1234,14 @@ funlike_invocation_p (cpp_reader *pfile, static inline unsigned int macro_real_token_count (const cpp_macro *macro) { - unsigned int i; if (__builtin_expect (!macro->extra_tokens, true)) return macro->count; - for (i = 0; i < macro->count; i++) - if (macro->exp.tokens[i].type == CPP_PASTE) - return i; - abort (); + + for (unsigned i = macro->count; i--;) + if (macro->exp.tokens[i].type != CPP_PASTE) + return i + 1; + + return 0; } /* Push the context of a macro with hash entry NODE onto the context @@ -1773,7 +1773,7 @@ replace_args (cpp_reader *pfile, cpp_has arg->stringified = stringify_arg (pfile, arg); } else if ((src->flags & PASTE_LEFT) - || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) + || (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))) total += arg->count - 1; else { @@ -3078,10 +3078,9 @@ _cpp_save_parameter (cpp_reader *pfile, saved[n].canonical_node = node; saved[n].value = node->value; - if (BUFF_ROOM (pfile->a_buff) < (n + 1) * sizeof (cpp_hashnode *)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); - - ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[n] = spelling; + 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; @@ -3226,26 +3225,18 @@ parse_params (cpp_reader *pfile, unsigne return ok; } -/* Allocate room for a token from a macro's replacement list. */ -static cpp_token * -alloc_expansion_token (cpp_reader *pfile, cpp_macro *macro) -{ - if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token)); - - return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++]; -} - /* Lex a token from the expansion of MACRO, but mark parameters as we find them and warn of traditional stringification. */ -static cpp_token * +static cpp_macro * lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) { - cpp_token *token, *saved_cur_token; - - saved_cur_token = pfile->cur_token; - pfile->cur_token = alloc_expansion_token (pfile, macro); - token = _cpp_lex_direct (pfile); + macro = (cpp_macro *)_cpp_reserve_room (pfile, + sizeof (cpp_macro) - sizeof (cpp_token) + + macro->count * sizeof (cpp_token), + sizeof (cpp_token)); + cpp_token *saved_cur_token = pfile->cur_token; + pfile->cur_token = ¯o->exp.tokens[macro->count]; + cpp_token *token = _cpp_lex_direct (pfile); pfile->cur_token = saved_cur_token; /* Is this a parameter? */ @@ -3261,52 +3252,45 @@ lex_expansion_token (cpp_reader *pfile, && (token->type == CPP_STRING || token->type == CPP_CHAR)) check_trad_stringification (pfile, macro, &token->val.str); - return token; + return macro; } -static bool -create_iso_definition (cpp_reader *pfile, cpp_macro *macro) +static cpp_macro * +create_iso_definition (cpp_reader *pfile) { - cpp_token *token; - const cpp_token *ctoken; bool following_paste_op = false; const char *paste_op_error_msg = N_("'##' cannot appear at either end of a macro expansion"); unsigned int num_extra_tokens = 0; unsigned nparms = 0; + cpp_hashnode **params = NULL; bool varadic = false; bool ok = false; + cpp_macro *macro = NULL; - /* Get the first token of the expansion (or the '(' of a - function-like macro). */ - ctoken = _cpp_lex_token (pfile); + /* Look at the first token, to see if this is a function-like + macro. */ + cpp_token first; + cpp_token *saved_cur_token = pfile->cur_token; + pfile->cur_token = &first; + cpp_token *token = _cpp_lex_direct (pfile); + pfile->cur_token = saved_cur_token; - if (ctoken->flags & PREV_WHITE) + if (token->flags & PREV_WHITE) /* Preceeded by space, must be part of expansion. */; - else if (ctoken->type == CPP_OPEN_PAREN) + else if (token->type == CPP_OPEN_PAREN) { /* An open-paren, get a parameter list. */ if (!parse_params (pfile, &nparms, &varadic)) goto out; - macro->variadic = varadic; - macro->paramc = nparms; - macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); - /* Success. Commit or allocate the parameter array. */ - if (pfile->hash_table->alloc_subobject) - { - cpp_hashnode **params = - (cpp_hashnode **) pfile->hash_table->alloc_subobject - (sizeof (cpp_hashnode *) * macro->paramc); - memcpy (params, macro->params, - sizeof (cpp_hashnode *) * macro->paramc); - macro->params = params; - } - else - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; - macro->fun_like = 1; - } - else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE)) + params = (cpp_hashnode **)_cpp_commit_buff + (pfile, sizeof (cpp_hashnode *) * nparms); + token = NULL; + } + else if (token->type != CPP_EOF + && !(token->type == CPP_COMMENT + && ! CPP_OPTION (pfile, discard_comments_in_macro_exp))) { /* While ISO C99 requires whitespace before replacement text in a macro definition, ISO C90 with TC1 allows characters @@ -3319,7 +3303,7 @@ create_iso_definition (cpp_reader *pfile else { int warntype = CPP_DL_WARNING; - switch (ctoken->type) + switch (token->type) { case CPP_ATSIGN: case CPP_AT_NAME: @@ -3330,7 +3314,7 @@ create_iso_definition (cpp_reader *pfile case CPP_OTHER: /* Basic character set sans letters, digits and _. */ if (strchr ("!\"#%&'()*+,-./:;<=>?[\\]^{|}~", - ctoken->val.str.text[0]) == NULL) + token->val.str.text[0]) == NULL) warntype = CPP_DL_PEDWARN; break; default: @@ -3343,16 +3327,32 @@ create_iso_definition (cpp_reader *pfile } } - if (macro->fun_like) - token = lex_expansion_token (pfile, macro); + macro = _cpp_new_macro (pfile, cmk_macro, + _cpp_reserve_room (pfile, 0, sizeof (cpp_macro))); + + if (!token) + { + macro->variadic = varadic; + macro->paramc = nparms; + macro->params = params; + macro->fun_like = true; + } else { - token = alloc_expansion_token (pfile, macro); - *token = *ctoken; + /* Preserve the token we peeked, there is already a single slot for it. */ + macro->exp.tokens[0] = *token; + token = ¯o->exp.tokens[0]; + macro->count = 1; } - for ( vaopt_state vaopt_tracker (pfile, macro->variadic, true);;) + for (vaopt_state vaopt_tracker (pfile, macro->variadic, true);; token = NULL) { + if (!token) + { + macro = lex_expansion_token (pfile, macro); + token = ¯o->exp.tokens[macro->count++]; + } + /* Check the stringifying # constraint 6.10.3.2.1 of function-like macros when lexing the subsequent token. */ if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like) @@ -3404,14 +3404,16 @@ create_iso_definition (cpp_reader *pfile goto out; } - if (token[-1].flags & PASTE_LEFT) + if (following_paste_op) { - macro->extra_tokens = 1; + /* Consecutive paste operators. This one will be moved + to the end. */ num_extra_tokens++; token->val.token_no = macro->count - 1; } else { + /* Drop the paste operator. */ --macro->count; token[-1].flags |= PASTE_LEFT; if (token->flags & DIGRAPH) @@ -3419,79 +3421,64 @@ create_iso_definition (cpp_reader *pfile if (token->flags & PREV_WHITE) token[-1].flags |= SP_PREV_WHITE; } + following_paste_op = true; } + else + following_paste_op = false; if (vaopt_tracker.update (token) == vaopt_state::ERROR) goto out; - - following_paste_op = (token->type == CPP_PASTE); - token = lex_expansion_token (pfile, macro); } /* We're committed to winning now. */ ok = true; - macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); - macro->traditional = 0; - /* Don't count the CPP_EOF. */ macro->count--; + macro = (cpp_macro *)_cpp_commit_buff + (pfile, sizeof (cpp_macro) - sizeof (cpp_token) + + sizeof (cpp_token) * macro->count); + /* Clear whitespace on first token for warn_of_redefinition(). */ if (macro->count) macro->exp.tokens[0].flags &= ~PREV_WHITE; - /* Commit or allocate the memory. */ - if (pfile->hash_table->alloc_subobject) + if (num_extra_tokens) { - cpp_token *tokns = - (cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token) - * macro->count); - if (num_extra_tokens) - { - /* Place second and subsequent ## or %:%: tokens in - sequences of consecutive such tokens at the end of the - list to preserve information about where they appear, how - they are spelt and whether they are preceded by - whitespace without otherwise interfering with macro - expansion. */ - cpp_token *normal_dest = tokns; - cpp_token *extra_dest = tokns + macro->count - num_extra_tokens; - unsigned int i; - for (i = 0; i < macro->count; i++) - { - if (macro->exp.tokens[i].type == CPP_PASTE) - *extra_dest++ = macro->exp.tokens[i]; - else - *normal_dest++ = macro->exp.tokens[i]; - } - } - else - memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count); - macro->exp.tokens = tokns; + /* Place second and subsequent ## or %:%: tokens in sequences of + consecutive such tokens at the end of the list to preserve + information about where they appear, how they are spelt and + whether they are preceded by whitespace without otherwise + interfering with macro expansion. Remember, this is + extremely rare, so efficiency is not a priority. */ + cpp_token *temp = (cpp_token *)_cpp_reserve_room + (pfile, 0, num_extra_tokens * sizeof (cpp_token)); + unsigned extra_ix = 0, norm_ix = 0; + cpp_token *exp = macro->exp.tokens; + for (unsigned ix = 0; ix != macro->count; ix++) + if (exp[ix].type == CPP_PASTE) + temp[extra_ix++] = exp[ix]; + else + exp[norm_ix++] = exp[ix]; + memcpy (&exp[norm_ix], temp, num_extra_tokens * sizeof (cpp_token)); + + /* Record there are extra tokens. */ + macro->extra_tokens = 1; } - else - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count]; out: pfile->state.va_args_ok = 0; _cpp_unsave_parameters (pfile, nparms); - return ok; + return ok ? macro : NULL; } -/* Parse a macro and save its expansion. Returns nonzero on success. */ -bool -_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) +cpp_macro * +_cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement) { - cpp_macro *macro; - bool ok; + cpp_macro *macro = (cpp_macro *) placement; - if (pfile->hash_table->alloc_subobject) - macro = (cpp_macro *) pfile->hash_table->alloc_subobject - (sizeof (cpp_macro)); - else - macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro)); macro->line = pfile->directive_line; macro->params = 0; macro->paramc = 0; @@ -3503,15 +3490,26 @@ _cpp_create_definition (cpp_reader *pfil /* To suppress some diagnostics. */ macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; + macro->kind = kind; + + return macro; +} + +/* Parse a macro and save its expansion. Returns nonzero on success. */ +bool +_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) +{ + cpp_macro *macro; + if (CPP_OPTION (pfile, traditional)) - ok = _cpp_create_trad_definition (pfile, macro); + macro = _cpp_create_trad_definition (pfile); else - ok = create_iso_definition (pfile, macro); + macro = create_iso_definition (pfile); - if (!ok) - return ok; + if (!macro) + return false; - if (node->type == NT_MACRO) + if (cpp_macro_p (node)) { if (CPP_OPTION (pfile, warn_unused_macros)) _cpp_warn_if_unused_macro (pfile, node, NULL); @@ -3552,7 +3550,7 @@ _cpp_create_definition (cpp_reader *pfil conditional flag */ node->flags &= ~NODE_CONDITIONAL; - return ok; + return true; } /* Notify the use of NODE in a macro-aware context (i.e. expanding it, @@ -3678,7 +3676,7 @@ cpp_macro_definition (cpp_reader *pfile, unsigned int count = macro_real_token_count (macro); for (i = 0; i < count; i++) { - cpp_token *token = ¯o->exp.tokens[i]; + const cpp_token *token = ¯o->exp.tokens[i]; if (token->type == CPP_MACRO_ARG) len += NODE_LEN (token->val.macro_arg.spelling); @@ -3742,7 +3740,7 @@ cpp_macro_definition (cpp_reader *pfile, unsigned int count = macro_real_token_count (macro); for (i = 0; i < count; i++) { - cpp_token *token = ¯o->exp.tokens[i]; + const cpp_token *token = ¯o->exp.tokens[i]; if (token->flags & PREV_WHITE) *buffer++ = ' '; Index: libcpp/traditional.c =================================================================== --- libcpp/traditional.c (revision 263618) +++ libcpp/traditional.c (working copy) @@ -853,7 +853,6 @@ push_replacement_text (cpp_reader *pfile cpp_macro *macro = node->value.macro; macro->used = 1; text = macro->exp.text; - macro->traditional = 1; len = macro->count; } @@ -1143,7 +1142,6 @@ save_replacement_text (cpp_reader *pfile memcpy (exp, pfile->out.base, len); exp[len] = '\n'; macro->exp.text = exp; - macro->traditional = 1; macro->count = len; } else @@ -1159,7 +1157,6 @@ save_replacement_text (cpp_reader *pfile exp = BUFF_FRONT (pfile->a_buff); block = (struct block *) (exp + macro->count); macro->exp.text = exp; - macro->traditional = 1; /* Write out the block information. */ block->text_len = len; @@ -1179,13 +1176,15 @@ save_replacement_text (cpp_reader *pfile /* Analyze and save the replacement text of a macro. Returns true on success. */ -bool -_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) +cpp_macro * +_cpp_create_trad_definition (cpp_reader *pfile) { const uchar *cur; uchar *limit; cpp_context *context = pfile->context; unsigned nparms = 0; + int fun_like = 0; + cpp_hashnode **params = NULL; /* The context has not been set up for command line defines, and CUR has not been updated for the macro name for in-file defines. */ @@ -1197,21 +1196,23 @@ _cpp_create_trad_definition (cpp_reader /* Is this a function-like macro? */ if (* CUR (context) == '(') { - bool ok = scan_parameters (pfile, &nparms); - macro->paramc = nparms; + fun_like = +1; + if (scan_parameters (pfile, &nparms)) + params = (cpp_hashnode **)_cpp_commit_buff + (pfile, sizeof (cpp_hashnode *) * nparms); + else + fun_like = -1; + } - /* Remember the params so we can clear NODE_MACRO_ARG flags. */ - macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); + cpp_macro *macro = NULL; - /* Setting macro to NULL indicates an error occurred, and - prevents unnecessary work in _cpp_scan_out_logical_line. */ - if (!ok) - macro = NULL; - else - { - BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc]; - macro->fun_like = 1; - } + if (fun_like >= 0) + { + macro = _cpp_new_macro (pfile, cmk_traditional, + _cpp_aligned_alloc (pfile, sizeof (cpp_macro))); + macro->params = params; + macro->paramc = nparms; + macro->fun_like = fun_like != 0; } /* Skip leading whitespace in the replacement text. */ @@ -1225,18 +1226,18 @@ _cpp_create_trad_definition (cpp_reader _cpp_unsave_parameters (pfile, nparms); - if (!macro) - return false; - - /* Skip trailing white space. */ - cur = pfile->out.base; - limit = pfile->out.cur; - while (limit > cur && is_space (limit[-1])) - limit--; - pfile->out.cur = limit; - save_replacement_text (pfile, macro, 0); + if (macro) + { + /* Skip trailing white space. */ + cur = pfile->out.base; + limit = pfile->out.cur; + while (limit > cur && is_space (limit[-1])) + limit--; + pfile->out.cur = limit; + save_replacement_text (pfile, macro, 0); + } - return true; + return macro; } /* Copy SRC of length LEN to DEST, but convert all contiguous