diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-09-25 01:02:42 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-09-25 01:02:42 +0000 |
commit | 5055f108385c076346b3b279788dc0129549b11f (patch) | |
tree | 91456c9f0ec368308f734e6d649b046d57a19114 /libcpp | |
parent | 414925ab0cb8d0aea39cb3383b18f72f3ce887a0 (diff) | |
parent | 44eb8fa73bb53afa17e4d72b1c073d0e08a76866 (diff) | |
download | gcc-5055f108385c076346b3b279788dc0129549b11f.zip gcc-5055f108385c076346b3b279788dc0129549b11f.tar.gz gcc-5055f108385c076346b3b279788dc0129549b11f.tar.bz2 |
Merge from trunk revision 264547.
From-SVN: r264554
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/ChangeLog | 221 | ||||
-rw-r--r-- | libcpp/Makefile.in | 5 | ||||
-rw-r--r-- | libcpp/directives.c | 236 | ||||
-rw-r--r-- | libcpp/expr.c | 22 | ||||
-rw-r--r-- | libcpp/files.c | 2 | ||||
-rw-r--r-- | libcpp/identifiers.c | 4 | ||||
-rw-r--r-- | libcpp/include/cpp-id-data.h | 82 | ||||
-rw-r--r-- | libcpp/include/cpplib.h | 174 | ||||
-rw-r--r-- | libcpp/include/line-map.h | 218 | ||||
-rw-r--r-- | libcpp/init.c | 3 | ||||
-rw-r--r-- | libcpp/internal.h | 33 | ||||
-rw-r--r-- | libcpp/lex.c | 21 | ||||
-rw-r--r-- | libcpp/line-map.c | 180 | ||||
-rw-r--r-- | libcpp/macro.c | 648 | ||||
-rw-r--r-- | libcpp/pch.c | 121 | ||||
-rw-r--r-- | libcpp/traditional.c | 87 |
16 files changed, 1146 insertions, 911 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index c72804f..ef96824 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,216 @@ +2018-09-17 David Malcolm <dmalcolm@redhat.com> + + * include/line-map.h (range_label::get_text): Add param + "range_idx". + +2018-08-30 Nathan Sidwell <nathan@acm.org> + + * include/line-map.h (enum lc_reason): Comment each member + separately. + (struct line_maps): Fix reallocator comment. + +2018-08-27 David Malcolm <dmalcolm@redhat.com> + + PR 87091 + * include/line-map.h (enum range_display_kind): New enum. + (struct location_range): Replace field "m_show_caret_p" with + "m_range_display_kind", converting from bool to the new enum. + (class rich_location): Add example of line insertion fix-it hint. + (rich_location::add_range): Convert param "show_caret_p" from bool + to enum range_display_kind and rename to "range_display_kind", + giving it a default of SHOW_RANGE_WITHOUT_CARET. + (rich_location::set_range): Likewise, albeit without a default. + * line-map.c (rich_location::rich_location): Update for conversion + of show_caret_p to tri-state enum. + (rich_location::add_range): Likewise. + (rich_location::set_range): Likewise. + +2018-08-24 H.J. Lu <hongjiu.lu@intel.com> + + PR bootstrap/86872 + * line-map.c (pure_location_p): Return true if linemap_lookup + returns NULL. + (linemap_add): Set start_location to 0 if we run out of line map + space. + +2018-08-20 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h: Fixup some whitespace. + (cpp_hashnode): Reduce type to 2 bit & flags to 8. + + * 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. + * macro.c (cpp_define_lazily): Use UCHAR_MAX. + (cpp_fun_like_macro_p): Delete. + + * Makefile.in (TAGS_SOURCES): Remove cpp-id-data.h. + * include/cpp-id-data.h: Delete. + * internal.h: Include cpplib.h not cpp-id-data.h. + + * include/cpp-id-data.h (struct answer): Delete. + * include/cpplib.h (struct answer): Don't forward-declare. + (enum cpp_macro_kind): Add cmk_assert. + (struct cpp_macro): Union parms and next assert chain. + (union _cpp_hashnode_value): 'answer' field is cpp_macro. + * directives.c (parse_answer): Convert to use cpp_macro. Return + true on success. + (parse_assertion, find_answer, _cpp_test_assertion, cpp_do_assert) + (cpp_do_unassert): Convert to use cpp_macro. + * macro.c (warn_of_redefinition, _cpp_new_macro) + (check_trad_stringification, cpp_macro_definition): Adjust macro + parm access. + * traditional.c (_cpp_replacement_text_len) + (_cpp_copy_replacement_text, _cpp_create_trad_definition): Likewise. + +2018-08-17 Nathan Sidwell <nathan@acm.org> + + * include/cpplib.h (struct cpp_callbacks): Replace + user_builtin_macro with user_lazy_macro. + (struct cpp_macro): add lazy field. + (enum cpp_builtin_type): Remove BT_FIRST_USER, BT_LAST_USER. + (cpp_define_lazily): Declare. + * macro.c (enter_macro_context) Use _cpp_maybe_notify_macro_use. + (warn_of_redefinition): Use cpp_builtin_macro_p, directly call + user_lazy_macro hook. + (_cpp_new_macro): Clear lazy field. + (cpp_define_lazily): Define. + (_cpp_notify_macro_use): Adjust lazy definition code. + (cpp_macro_definition): No need to do lazy definition here. + * pch.c (write_macdef, save_macros): Likewise. + + * 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. + + * cpp-id-data.h (uchar, UC): Move to internal.h + (struct cpp_macro): Move to cpplib.h. + * internal.h (uchar, UC): From cpp-id-data.h. + * include/cpplib.h (struct cpp_macro): From cpp-id-data.h. + +2018-08-16 Nathan Sidwell <nathan@acm.org> + + * internal.h (_cpp_save_parameter): Take parmno, not macro. + (_cpp_unsave_parameters): Declare. + * macro.c (_cpp_save_parameter): Take parm number, not macro. + Return true on success. + (_cpp_unsave_parameters): New. + (parse_params): Take parm_no and variadic pointers, not macro. + Reimplement parsing logic. + (create_iso_definition): Adjust parse_params changes. Call + _cpp_unsave_parameters here. + (_cpp_create_definition): Don't unsave params here. + * traditional.c (scan_parameters): Take n_param pointer, adjust. + (_cpp_create_trad_definition): Ajust scan_parameters change. Call + _cpp_unsave_parameters. + + * 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 <dmalcolm@redhat.com> + + * include/line-map.h (struct location_range): Add "m_label" field. + (class rich_location): Add description of labels to leading + comment. + (rich_location::rich_location): Add "label" param, defaulting to + NULL. + (rich_location::add_range): Likewise. + (struct label_text): New struct. + (class range_label): New abstract base class. + * line-map.c (rich_location::rich_location): Add "label" param; + use it. + (rich_location::add_range): Likewise. + +2018-08-08 Nathan Sidwell <nathan@acm.org> + + Make linemap::included_from a location + libcpp/ + * include/line-map.h (struct line_map_ordinary): Replace + included_from map index with included_at source_location. + (ORDINARY_MAP_INCLUDER_FILE_INDEX): Delete. + (LAST_SOURCE_LINE_LOCATION): Delete. + (LAST_SOURCE_LINE, LAST_SOURCE_COLUMN): Delete. + (linemap_included_from): New. + (linemap_included_from_linemap): Declare. + (MAIN_FILE_P): Adjust. + * line-map.c (linemap_included_from_linemap): New. + (lonemap_check_files_exited): Use linemap_included_at. + (linemap_add): Adjust inclusion setting. + (linemap_dump, linemap_dump_location): Adjust. + * directives.c (do_linemarker): Use linemap_included_at. + +2018-08-07 Nathan Sidwell <nathan@acm.org> + + * line-map.c: (linemap_init): Set default allocator here. + (new_linemap): Rather than here. Refactor allocation logic. + 2018-07-20 David Malcolm <dmalcolm@redhat.com> * include/line-map.h (rich_location::set_range): Remove redundant @@ -94,10 +307,10 @@ 2018-01-18 Boris Kolpackov <boris@codesynthesis.com> - PR other/70268 - * include/cpplib.h (cpp_callbacks::remap_filename): New callback. - * macro.c (_cpp_builtin_macro_text): Call remap_filename for - __FILE__ and __BASE_FILE__. + PR other/70268 + * include/cpplib.h (cpp_callbacks::remap_filename): New callback. + * macro.c (_cpp_builtin_macro_text): Call remap_filename for + __FILE__ and __BASE_FILE__. 2018-01-10 Kelvin Nilsen <kelvin@gcc.gnu.org> diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in index bfd6069..835c835 100644 --- a/libcpp/Makefile.in +++ b/libcpp/Makefile.in @@ -261,9 +261,8 @@ po/$(PACKAGE).pot: $(libcpp_a_SOURCES) sed 's:$(srcdir)/::g' <po/$(PACKAGE).pot.tmp >po/$(PACKAGE).pot rm po/$(PACKAGE).pot.tmp -TAGS_SOURCES = $(libcpp_a_SOURCES) internal.h ucnid.h \ - include/line-map.h include/symtab.h include/cpp-id-data.h \ - include/cpplib.h include/mkdeps.h system.h +TAGS_SOURCES = $(libcpp_a_SOURCES) internal.h system.h ucnid.h \ + include/cpplib.h include/line-map.h include/mkdeps.h include/symtab.h TAGS: $(TAGS_SOURCES) cd $(srcdir) && etags $(TAGS_SOURCES) diff --git a/libcpp/directives.c b/libcpp/directives.c index bf13ada..f7c460d 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -124,9 +124,9 @@ static const cpp_token *get_token_no_padding (cpp_reader *); static const cpp_token *get__Pragma_string (cpp_reader *); static void destringize_and_run (cpp_reader *, const cpp_string *, source_location); -static int parse_answer (cpp_reader *, struct answer **, int, source_location); -static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int); -static struct answer ** find_answer (cpp_hashnode *, const struct answer *); +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 void handle_assertion (cpp_reader *, const char *, int); static void do_pragma_push_macro (cpp_reader *); static void do_pragma_pop_macro (cpp_reader *); @@ -665,12 +665,12 @@ do_undef (cpp_reader *pfile) /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier is not currently defined as a macro name. */ - if (node->type == NT_MACRO) + if (cpp_macro_p (node)) { if (node->flags & NODE_WARN) cpp_error (pfile, CPP_DL_WARNING, "undefining \"%s\"", NODE_NAME (node)); - else if ((node->flags & NODE_BUILTIN) + else if (cpp_builtin_macro_p (node) && CPP_OPTION (pfile, warn_builtin_macro_redefined)) cpp_warning_with_line (pfile, CPP_W_BUILTIN_MACRO_REDEFINED, pfile->directive_line, 0, @@ -695,7 +695,8 @@ undefine_macros (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *h, /* 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; } @@ -1088,10 +1089,10 @@ do_linemarker (cpp_reader *pfile) /* Reread map since cpp_get_token can invalidate it with a reallocation. */ map = LINEMAPS_LAST_ORDINARY_MAP (line_table); - const line_map_ordinary *from; + const line_map_ordinary *from + = linemap_included_from_linemap (line_table, map); if (MAIN_FILE_P (map) - || (new_file - && (from = INCLUDED_FROM (pfile->line_table, map)) != NULL + || (from && filename_cmp (ORDINARY_MAP_FILE_NAME (from), new_file) != 0)) { cpp_warning (pfile, CPP_W_NONE, @@ -1666,7 +1667,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 +1961,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 +1990,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); @@ -2182,17 +2150,13 @@ push_conditional (cpp_reader *pfile, int skip, int type, storage, i.e. the #assert case. Returns 0 on success, and sets ANSWERP to point to the answer. PRED_LOC is the location of the predicate. */ -static int -parse_answer (cpp_reader *pfile, struct answer **answerp, int type, - source_location pred_loc) +static bool +parse_answer (cpp_reader *pfile, int type, source_location pred_loc, + cpp_macro **answer_ptr) { - const cpp_token *paren; - struct answer *answer; - unsigned int acount; - /* In a conditional, it is legal to not have an open paren. We should save the following token in this case. */ - paren = cpp_get_token (pfile); + const cpp_token *paren = cpp_get_token (pfile); /* If not a paren, see if we're OK. */ if (paren->type != CPP_OPEN_PAREN) @@ -2202,23 +2166,26 @@ parse_answer (cpp_reader *pfile, struct answer **answerp, int type, if (type == T_IF) { _cpp_backup_tokens (pfile, 1); - return 0; + return true; } /* #unassert with no answer is valid - it removes all answers. */ if (type == T_UNASSERT && paren->type == CPP_EOF) - return 0; + return true; cpp_error_with_line (pfile, CPP_DL_ERROR, pred_loc, 0, "missing '(' after predicate"); - return 1; + return false; } - for (acount = 0;; acount++) + cpp_macro *answer = _cpp_new_macro (pfile, cmk_assert, + _cpp_reserve_room (pfile, 0, + sizeof (cpp_macro))); + answer->parm.next = NULL; + unsigned count = 0; + for (;;) { - size_t room_needed; const cpp_token *token = cpp_get_token (pfile); - cpp_token *dest; if (token->type == CPP_CLOSE_PAREN) break; @@ -2226,57 +2193,52 @@ parse_answer (cpp_reader *pfile, struct answer **answerp, int type, if (token->type == CPP_EOF) { cpp_error (pfile, CPP_DL_ERROR, "missing ')' to complete answer"); - return 1; + return false; } - /* struct answer includes the space for one token. */ - room_needed = (sizeof (struct answer) + acount * sizeof (cpp_token)); - - if (BUFF_ROOM (pfile->a_buff) < room_needed) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (struct answer)); - - dest = &((struct answer *) BUFF_FRONT (pfile->a_buff))->first[acount]; - *dest = *token; - - /* Drop whitespace at start, for answer equivalence purposes. */ - if (acount == 0) - dest->flags &= ~PREV_WHITE; + answer = (cpp_macro *)_cpp_reserve_room + (pfile, sizeof (cpp_macro) + count * sizeof (cpp_token), + sizeof (cpp_token)); + answer->exp.tokens[count++] = *token; } - if (acount == 0) + if (!count) { cpp_error (pfile, CPP_DL_ERROR, "predicate's answer is empty"); - return 1; + return false; } - answer = (struct answer *) BUFF_FRONT (pfile->a_buff); - answer->count = acount; - answer->next = NULL; - *answerp = answer; + /* Drop whitespace at start, for answer equivalence purposes. */ + answer->exp.tokens[0].flags &= ~PREV_WHITE; - return 0; + answer->count = count; + *answer_ptr = answer; + + return true; } /* 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 ANSWERP, otherwise it is 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, struct answer **answerp, int type) +parse_assertion (cpp_reader *pfile, int type, cpp_macro **answer_ptr) { cpp_hashnode *result = 0; - const cpp_token *predicate; /* We don't expand predicates or answers. */ pfile->state.prevent_expansion++; - *answerp = 0; - predicate = cpp_get_token (pfile); + *answer_ptr = NULL; + + const cpp_token *predicate = cpp_get_token (pfile); if (predicate->type == CPP_EOF) cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate"); else if (predicate->type != CPP_NAME) cpp_error_with_line (pfile, CPP_DL_ERROR, predicate->src_loc, 0, "predicate must be an identifier"); - else if (parse_answer (pfile, answerp, type, predicate->src_loc) == 0) + else if (parse_answer (pfile, type, predicate->src_loc, answer_ptr)) { unsigned int len = NODE_LEN (predicate->val.node.node); unsigned char *sym = (unsigned char *) alloca (len + 1); @@ -2288,25 +2250,27 @@ parse_assertion (cpp_reader *pfile, struct answer **answerp, int type) } pfile->state.prevent_expansion--; + return result; } /* 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 struct answer ** -find_answer (cpp_hashnode *node, const struct answer *candidate) +static cpp_macro ** +find_answer (cpp_hashnode *node, const cpp_macro *candidate) { unsigned int i; - struct answer **result; + cpp_macro **result = NULL; - for (result = &node->value.answers; *result; result = &(*result)->next) + for (result = &node->value.answers; *result; result = &(*result)->parm.next) { - struct answer *answer = *result; + cpp_macro *answer = *result; if (answer->count == candidate->count) { for (i = 0; i < answer->count; i++) - if (! _cpp_equiv_tokens (&answer->first[i], &candidate->first[i])) + if (!_cpp_equiv_tokens (&answer->exp.tokens[i], + &candidate->exp.tokens[i])) break; if (i == answer->count) @@ -2323,18 +2287,18 @@ find_answer (cpp_hashnode *node, const struct answer *candidate) int _cpp_test_assertion (cpp_reader *pfile, unsigned int *value) { - struct answer *answer; - cpp_hashnode *node; - - node = parse_assertion (pfile, &answer, T_IF); + cpp_macro *answer; + cpp_hashnode *node = parse_assertion (pfile, T_IF, &answer); /* For recovery, an erroneous assertion expression is handled as a failing assertion. */ *value = 0; if (node) - *value = (node->type == NT_ASSERTION && - (answer == 0 || *find_answer (node, answer) != 0)); + { + if (node->value.answers) + *value = !answer || *find_answer (node, answer); + } else if (pfile->cur_token[-1].type == CPP_EOF) _cpp_backup_tokens (pfile, 1); @@ -2346,43 +2310,29 @@ _cpp_test_assertion (cpp_reader *pfile, unsigned int *value) static void do_assert (cpp_reader *pfile) { - struct answer *new_answer; - cpp_hashnode *node; + cpp_macro *answer; + cpp_hashnode *node = parse_assertion (pfile, T_ASSERT, &answer); - node = parse_assertion (pfile, &new_answer, T_ASSERT); if (node) { - size_t answer_size; - /* Place the new answer in the answer list. First check there is not a duplicate. */ - new_answer->next = 0; - if (node->type == NT_ASSERTION) + if (*find_answer (node, answer)) { - if (*find_answer (node, new_answer)) - { - cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted", - NODE_NAME (node) + 1); - return; - } - new_answer->next = node->value.answers; + cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted", + NODE_NAME (node) + 1); + return; } - answer_size = sizeof (struct answer) + ((new_answer->count - 1) - * sizeof (cpp_token)); - /* Commit or allocate storage for the object. */ - if (pfile->hash_table->alloc_subobject) - { - struct answer *temp_answer = new_answer; - new_answer = (struct answer *) pfile->hash_table->alloc_subobject - (answer_size); - memcpy (new_answer, temp_answer, answer_size); - } - else - BUFF_FRONT (pfile->a_buff) += answer_size; + /* Commit or allocate storage for the answer. */ + answer = (cpp_macro *)_cpp_commit_buff + (pfile, sizeof (cpp_macro) - sizeof (cpp_token) + + sizeof (cpp_token) * answer->count); + + /* Chain into the list. */ + answer->parm.next = node->value.answers; + node->value.answers = answer; - node->type = NT_ASSERTION; - node->value.answers = new_answer; check_eol (pfile, false); } } @@ -2391,25 +2341,19 @@ do_assert (cpp_reader *pfile) static void do_unassert (cpp_reader *pfile) { - cpp_hashnode *node; - struct answer *answer; + cpp_macro *answer; + cpp_hashnode *node = parse_assertion (pfile, T_UNASSERT, &answer); - node = parse_assertion (pfile, &answer, T_UNASSERT); /* It isn't an error to #unassert something that isn't asserted. */ - if (node && node->type == NT_ASSERTION) + if (node) { if (answer) { - struct answer **p = find_answer (node, answer), *temp; + cpp_macro **p = find_answer (node, answer); - /* Remove the answer from the list. */ - temp = *p; - if (temp) - *p = temp->next; - - /* Did we free the last answer? */ - if (node->value.answers == 0) - node->type = NT_VOID; + /* Remove the assert from the list. */ + if (cpp_macro *temp = *p) + *p = temp->parm.next; check_eol (pfile, false); } @@ -2508,18 +2452,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 +2474,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/cpp-id-data.h b/libcpp/include/cpp-id-data.h deleted file mode 100644 index 0299984..0000000 --- a/libcpp/include/cpp-id-data.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Structures that hang off cpp_identifier, for PCH. - Copyright (C) 1986-2018 Free Software Foundation, Inc. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "cpplib.h" - -#if !defined (HAVE_UCHAR) && !defined (IN_GCC) -typedef unsigned char uchar; -#endif - -#define UC (const unsigned char *) /* Intended use: UC"string" */ - -/* Chained list of answers to an assertion. */ -struct GTY(()) answer { - struct answer *next; - unsigned int count; - cpp_token GTY ((length ("%h.count"))) first[1]; -}; - -/* Each macro definition is recorded in a cpp_macro structure. - Variadic macros cannot occur with traditional cpp. */ -struct GTY(()) cpp_macro { - /* Parameters, if any. If parameter names use extended identifiers, - the original spelling of those identifiers, not the canonical - UTF-8 spelling, goes here. */ - cpp_hashnode ** GTY ((nested_ptr (union tree_node, - "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL", - "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"), - 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; - - /* Number of tokens in expansion, or bytes for traditional macros. */ - unsigned int count; - - /* Number of parameters. */ - unsigned short paramc; - - /* If a function-like macro. */ - unsigned int fun_like : 1; - - /* If a variadic macro. */ - unsigned int variadic : 1; - - /* If macro defined in system header. */ - unsigned int syshdr : 1; - - /* 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; -}; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 3ad52d5..85aa09f 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -36,7 +36,6 @@ typedef struct cpp_macro cpp_macro; typedef struct cpp_callbacks cpp_callbacks; typedef struct cpp_dir cpp_dir; -struct answer; struct _cpp_file; /* The first three groups, apart from '=', can appear in preprocessor @@ -605,8 +604,8 @@ struct cpp_callbacks /* Callback to identify whether an attribute exists. */ int (*has_attribute) (cpp_reader *); - /* Callback that can change a user builtin into normal macro. */ - bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *); + /* Callback that can change a user lazy into normal macro. */ + void (*user_lazy_macro) (cpp_reader *, cpp_macro *, unsigned); /* Callback to parse SOURCE_DATE_EPOCH from environment. */ time_t (*get_source_date_epoch) (cpp_reader *); @@ -671,14 +670,81 @@ struct cpp_dir dev_t dev; }; -/* 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 +/* The kind of the cpp_macro. */ +enum cpp_macro_kind { + cmk_macro, /* An ISO macro (token expansion). */ + cmk_assert, /* An assertion. */ + 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 { + union cpp_parm_u + { + /* Parameters, if any. If parameter names use extended identifiers, + the original spelling of those identifiers, not the canonical + UTF-8 spelling, goes here. */ + cpp_hashnode ** GTY ((tag ("false"), + nested_ptr (union tree_node, + "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL", + "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"), + length ("%1.paramc"))) params; + + /* If this is an assertion, the next one in the chain. */ + cpp_macro *GTY ((tag ("true"))) next; + } GTY ((desc ("%1.kind == cmk_assert"))) parm; + + /* Definition line number. */ + source_location line; + + /* Number of tokens in body, or bytes for traditional macros. */ + /* Do we really need 2^32-1 range here? */ + unsigned int count; + + /* Number of parameters. */ + unsigned short paramc; + + /* Non-zero if this is a user-lazy macro, value provided by user. */ + unsigned char lazy; + + /* The kind of this macro (ISO, trad or assert) */ + unsigned kind : 2; + + /* If a function-like macro. */ + unsigned int fun_like : 1; + + /* If a variadic macro. */ + unsigned int variadic : 1; + + /* If macro defined in system header. */ + unsigned int syshdr : 1; + + /* Nonzero if it has been expanded or had its existence tested. */ + unsigned int used : 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; +}; + +/* 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. */ @@ -686,21 +752,21 @@ struct cpp_dir /* 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 @@ -717,9 +783,7 @@ enum cpp_builtin_type BT_PRAGMA, /* `_Pragma' operator */ BT_TIMESTAMP, /* `__TIMESTAMP__' */ BT_COUNTER, /* `__COUNTER__' */ - BT_HAS_ATTRIBUTE, /* `__has_attribute__(x)' */ - BT_FIRST_USER, /* User defined builtin macros. */ - BT_LAST_USER = BT_FIRST_USER + 63 + BT_HAS_ATTRIBUTE /* `__has_attribute__(x)' */ }; #define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE)) @@ -727,36 +791,19 @@ enum cpp_builtin_type #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. */ - struct answer * 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 { @@ -766,10 +813,12 @@ struct GTY(()) cpp_hashnode { 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 : 8; /* CPP flags. */ - union _cpp_hashnode_value GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) value; + /* 6 bits spare (plus another 32 on 64-bit hosts). */ + + union _cpp_hashnode_value GTY ((desc ("%1.type"))) value; }; /* A class for iterating through the source locations within a @@ -890,7 +939,25 @@ 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_USER_MACRO; +} +inline bool cpp_builtin_macro_p (const cpp_hashnode *node) +{ + return node->type == NT_BUILTIN_MACRO; +} +inline bool cpp_macro_p (const cpp_hashnode *node) +{ + 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) +{ + return cpp_user_macro_p (node) && node->value.macro->fun_like; +} + extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); extern source_location cpp_macro_definition_location (cpp_hashnode *); @@ -926,6 +993,9 @@ extern void cpp_assert (cpp_reader *, const char *); extern void cpp_undef (cpp_reader *, const char *); extern void cpp_unassert (cpp_reader *, const char *); +/* Mark a node as a lazily defined macro. */ +extern void cpp_define_lazily (cpp_reader *, cpp_hashnode *node, unsigned N); + /* Undefine all macros and assertions. */ extern void cpp_undef_all (cpp_reader *); diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index a4baa49..c479dfa 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -61,20 +61,14 @@ inline int compare (linenum_type lhs, linenum_type rhs) return 0; } -/* Reason for creating a new line map with linemap_add. LC_ENTER is - when including a new file, e.g. a #include directive in C. - LC_LEAVE is when reaching a file's end. LC_RENAME is when a file - name or line number changes for neither of the above reasons - (e.g. a #line directive in C); LC_RENAME_VERBATIM is like LC_RENAME - but a filename of "" is not specially interpreted as standard - input. LC_ENTER_MACRO is when a macro expansion is about to start. */ +/* Reason for creating a new line map with linemap_add. */ enum lc_reason { - LC_ENTER = 0, - LC_LEAVE, - LC_RENAME, - LC_RENAME_VERBATIM, - LC_ENTER_MACRO, + LC_ENTER = 0, /* Begin #include. */ + LC_LEAVE, /* Return to including file. */ + LC_RENAME, /* Other reason for name change. */ + LC_RENAME_VERBATIM, /* Likewise, but "" != stdin. */ + LC_ENTER_MACRO, /* Begin macro expansion. */ /* FIXME: add support for stringize and paste. */ LC_HWM /* High Water Mark. */ }; @@ -440,10 +434,10 @@ struct GTY((tag ("1"))) line_map_ordinary : public line_map { const char *to_file; linenum_type to_line; - /* An index into the set that gives the line mapping at whose end - the current one was included. File(s) at the bottom of the - include stack have this set to -1. */ - int included_from; + /* Location from whence this line map was included. For regular + #includes, this location will be the last location of a map. For + outermost file, this is 0. */ + source_location included_from; /* Size is 20 or 24 bytes, no padding */ }; @@ -634,17 +628,6 @@ ORDINARY_MAP_STARTING_LINE_NUMBER (const line_map_ordinary *ord_map) return ord_map->to_line; } -/* Get the index of the ordinary map at whose end - ordinary map MAP was included. - - File(s) at the bottom of the include stack have this set. */ - -inline int -ORDINARY_MAP_INCLUDER_FILE_INDEX (const line_map_ordinary *ord_map) -{ - return ord_map->included_from; -} - /* Return a positive value if map encodes locations from a system header, 0 otherwise. Returns 1 if ordinary map MAP encodes locations in a system header and 2 if it encodes locations in a C system header @@ -788,8 +771,7 @@ struct GTY(()) line_maps { may require allocating a new line_map. */ unsigned int max_column_hint; - /* If non-null, the allocator to use when resizing 'maps'. If null, - xrealloc is used. */ + /* The allocator to use when resizing 'maps', defaults to xrealloc. */ line_map_realloc reallocator; /* The allocators' function used to know the actual size it @@ -1192,51 +1174,23 @@ SOURCE_COLUMN (const line_map_ordinary *ord_map, source_location loc) & ((1 << ord_map->m_column_and_range_bits) - 1)) >> ord_map->m_range_bits; } -/* Return the location of the last source line within an ordinary - map. */ -inline source_location -LAST_SOURCE_LINE_LOCATION (const line_map_ordinary *map) -{ - return (((map[1].start_location - 1 - - map->start_location) - & ~((1 << map->m_column_and_range_bits) - 1)) - + map->start_location); -} -/* Returns the last source line number within an ordinary map. This - is the (last) line of the #include, or other directive, that caused - a map change. */ -inline linenum_type -LAST_SOURCE_LINE (const line_map_ordinary *map) -{ - return SOURCE_LINE (map, LAST_SOURCE_LINE_LOCATION (map)); -} - -/* Return the last column number within an ordinary map. */ - -inline linenum_type -LAST_SOURCE_COLUMN (const line_map_ordinary *map) +inline source_location +linemap_included_from (const line_map_ordinary *ord_map) { - return SOURCE_COLUMN (map, LAST_SOURCE_LINE_LOCATION (map)); + return ord_map->included_from; } -/* Returns the map a given map was included from, or NULL if the map - belongs to the main file, i.e, a file that wasn't included by - another one. */ -inline line_map_ordinary * -INCLUDED_FROM (struct line_maps *set, const line_map_ordinary *ord_map) -{ - return ((ord_map->included_from == -1) - ? NULL - : LINEMAPS_ORDINARY_MAP_AT (set, ord_map->included_from)); -} +/* The linemap containing the included-from location of MAP. */ +const line_map_ordinary *linemap_included_from_linemap + (line_maps *set, const line_map_ordinary *map); /* True if the map is at the bottom of the include stack. */ inline bool MAIN_FILE_P (const line_map_ordinary *ord_map) { - return ord_map->included_from < 0; + return ord_map->included_from == 0; } /* Encode and return a source_location from a column number. The @@ -1320,23 +1274,50 @@ typedef struct bool sysp; } expanded_location; -/* A location within a rich_location: a caret&range, with - the caret potentially flagged for display. */ +class range_label; -struct location_range -{ - source_location m_loc; +/* A hint to diagnostic_show_locus on how to print a source range within a + rich_location. - /* Should a caret be drawn for this range? Typically this is - true for the 0th range, and false for subsequent ranges, - but the Fortran frontend overrides this for rendering things like: + Typically this is SHOW_RANGE_WITH_CARET for the 0th range, and + SHOW_RANGE_WITHOUT_CARET for subsequent ranges, + but the Fortran frontend uses SHOW_RANGE_WITH_CARET repeatedly for + printing things like: x = x + y 1 2 Error: Shapes for operands at (1) and (2) are not conformable - where "1" and "2" are notionally carets. */ - bool m_show_caret_p; + where "1" and "2" are notionally carets. */ + +enum range_display_kind +{ + /* Show the pertinent source line(s), the caret, and underline(s). */ + SHOW_RANGE_WITH_CARET, + + /* Show the pertinent source line(s) and underline(s), but don't + show the caret (just an underline). */ + SHOW_RANGE_WITHOUT_CARET, + + /* Just show the source lines; don't show the range itself. + This is for use when displaying some line-insertion fix-it hints (for + showing the user context on the change, for when it doesn't make sense + to highlight the first column on the next line). */ + SHOW_LINES_WITHOUT_RANGE +}; + +/* A location within a rich_location: a caret&range, with + the caret potentially flagged for display, and an optional + label. */ + +struct location_range +{ + source_location m_loc; + + enum range_display_kind m_range_display_kind; + + /* If non-NULL, the label for this range. */ + const range_label *m_label; }; /* A partially-embedded vec for use within rich_location for storing @@ -1478,6 +1459,8 @@ class fixit_hint; Additional ranges may be added to help the user identify other pertinent clauses in a diagnostic. + Ranges can (optionally) be given labels via class range_label. + rich_location instances are intended to be allocated on the stack when generating diagnostics, and to be short-lived. @@ -1523,18 +1506,22 @@ class fixit_hint; equal to their caret point. The frontend overrides the diagnostic context's default caret character for these ranges. - Example E - ********* + Example E (range labels) + ************************ printf ("arg0: %i arg1: %s arg2: %i", ^~ + | + const char * 100, 101, 102); ~~~ + | + int This rich location has two ranges: - range 0 is at the "%s" with start = caret = "%" and finish at - the "s". + the "s". It has a range_label ("const char *"). - range 1 has start/finish covering the "101" and is not flagged for - caret printing; it is perhaps at the start of "101". - + caret printing. The caret is at the start of "101", where its + range_label is printed ("int"). Fix-it hints ------------ @@ -1594,6 +1581,18 @@ class fixit_hint; added via richloc.add_fixit_replace ("color"); + Example J: fix-it hint: line insertion + ************************************** + + 3 | #include <stddef.h> + + |+#include <stdio.h> + 4 | int the_next_line; + + This rich location has a single range at line 4 column 1, marked + with SHOW_LINES_WITHOUT_RANGE (to avoid printing a meaningless caret + on the "i" of int). It has a insertion fix-it hint of the string + "#include <stdio.h>\n". + Adding a fix-it hint can fail: for example, attempts to insert content at the transition between two line maps may fail due to there being no source_location (aka location_t) value to express the new location. @@ -1626,7 +1625,8 @@ class rich_location /* Constructors. */ /* Constructing from a location. */ - rich_location (line_maps *set, source_location loc); + rich_location (line_maps *set, source_location loc, + const range_label *label = NULL); /* Destructor. */ ~rich_location (); @@ -1636,10 +1636,14 @@ class rich_location source_location get_loc (unsigned int idx) const; void - add_range (source_location loc, bool show_caret_p); + add_range (source_location loc, + enum range_display_kind range_display_kind + = SHOW_RANGE_WITHOUT_CARET, + const range_label *label = NULL); void - set_range (unsigned int idx, source_location loc, bool show_caret_p); + set_range (unsigned int idx, source_location loc, + enum range_display_kind range_display_kind); unsigned int get_num_locations () const { return m_ranges.count (); } @@ -1760,6 +1764,56 @@ protected: bool m_fixits_cannot_be_auto_applied; }; +/* A struct for the result of range_label::get_text: a NUL-terminated buffer + of localized text, and a flag to determine if the caller should "free" the + buffer. */ + +struct label_text +{ + label_text () + : m_buffer (NULL), m_caller_owned (false) + {} + + label_text (char *buffer, bool caller_owned) + : m_buffer (buffer), m_caller_owned (caller_owned) + {} + + void maybe_free () + { + if (m_caller_owned) + free (m_buffer); + } + + char *m_buffer; + bool m_caller_owned; +}; + +/* Abstract base class for labelling a range within a rich_location + (e.g. for labelling expressions with their type). + + Generating the text could require non-trivial work, so this work + is delayed (via the "get_text" virtual function) until the diagnostic + printing code "knows" it needs it, thus avoiding doing it e.g. for + warnings that are filtered by command-line flags. This virtual + function also isolates libcpp and the diagnostics subsystem from + the front-end and middle-end-specific code for generating the text + for the labels. + + Like the rich_location instances they annotate, range_label instances + are intended to be allocated on the stack when generating diagnostics, + and to be short-lived. */ + +class range_label +{ + public: + virtual ~range_label () {} + + /* Get localized text for the label. + The RANGE_IDX is provided, allowing for range_label instances to be + shared by multiple ranges if need be (the "flyweight" design pattern). */ + virtual label_text get_text (unsigned range_idx) const = 0; +}; + /* A fix-it hint: a suggested insertion, replacement, or deletion of text. We handle these three types of edit with one class, by representing them as replacement of a half-open range: diff --git a/libcpp/init.c b/libcpp/init.c index d1697fd..32a5956 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -480,8 +480,7 @@ cpp_init_special_builtins (cpp_reader *pfile) || 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; diff --git a/libcpp/internal.h b/libcpp/internal.h index 782d8e6..59f830c 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -23,7 +23,7 @@ along with this program; see the file COPYING3. If not see #define LIBCPP_INTERNAL_H #include "symtab.h" -#include "cpp-id-data.h" +#include "cpplib.h" #if HAVE_ICONV #include <iconv.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; @@ -603,6 +602,12 @@ extern const unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; #endif +#if !defined (HAVE_UCHAR) && !defined (IN_GCC) +typedef unsigned char uchar; +#endif + +#define UC (const uchar *) /* Intended use: UC"string" */ + /* Macros. */ static inline int cpp_in_system_header (cpp_reader *); @@ -622,13 +627,21 @@ 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 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 *); extern void _cpp_push_text_context (cpp_reader *, cpp_hashnode *, const unsigned char *, size_t); -extern bool _cpp_save_parameter (cpp_reader *, cpp_macro *, cpp_hashnode *, +extern bool _cpp_save_parameter (cpp_reader *, unsigned, cpp_hashnode *, cpp_hashnode *); +extern void _cpp_unsave_parameters (cpp_reader *, unsigned); extern bool _cpp_arguments_ok (cpp_reader *, cpp_macro *, const cpp_hashnode *, unsigned int); extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *, @@ -685,6 +698,14 @@ extern void _cpp_init_tokenrun (tokenrun *, unsigned int); 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 *); @@ -721,7 +742,7 @@ extern bool _cpp_read_logical_line_trad (cpp_reader *); 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 *, diff --git a/libcpp/lex.c b/libcpp/lex.c index a2592e0..892cfc4 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 @@ -3725,6 +3725,25 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len) 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 diff --git a/libcpp/line-map.c b/libcpp/line-map.c index a1a765f..73d9444 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -304,6 +304,8 @@ pure_location_p (line_maps *set, source_location loc) return false; const line_map *map = linemap_lookup (set, loc); + if (map == NULL) + return true; const line_map_ordinary *ordmap = linemap_check_ordinary (map); if (loc & ((1U << ordmap->m_range_bits) - 1)) @@ -346,6 +348,8 @@ linemap_init (struct line_maps *set, #else new (set) line_maps(); #endif + /* Set default reallocator (used for initial alloc too). */ + set->reallocator = xrealloc; set->highest_location = RESERVED_LOCATION_COUNT - 1; set->highest_line = RESERVED_LOCATION_COUNT - 1; set->location_adhoc_data_map.htab = @@ -353,17 +357,25 @@ linemap_init (struct line_maps *set, set->builtin_location = builtin_location; } +/* Return the ordinary line map from whence MAP was included. Returns + NULL if MAP was not an include. */ + +const line_map_ordinary * +linemap_included_from_linemap (line_maps *set, const line_map_ordinary *map) +{ + return linemap_ordinary_map_lookup (set, linemap_included_from (map)); +} + /* Check for and warn about line_maps entered but not exited. */ void linemap_check_files_exited (struct line_maps *set) { - const line_map_ordinary *map; /* Depending upon whether we are handling preprocessed input or not, this can be a user error or an ICE. */ - for (map = LINEMAPS_LAST_ORDINARY_MAP (set); + for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set); ! MAIN_FILE_P (map); - map = INCLUDED_FROM (set, map)) + map = linemap_included_from_linemap (set, map)) fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n", ORDINARY_MAP_FILE_NAME (map)); } @@ -376,81 +388,59 @@ linemap_check_files_exited (struct line_maps *set) static struct line_map * new_linemap (struct line_maps *set, source_location start_location) { - struct line_map *result; - bool macro_map_p = start_location >= LINE_MAP_MAX_LOCATION; + bool macro_p = start_location >= LINE_MAP_MAX_LOCATION; + unsigned num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p); + unsigned num_maps_used = LINEMAPS_USED (set, macro_p); - if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p)) + if (num_maps_used == num_maps_allocated) { - /* We ran out of allocated line maps. Let's allocate more. */ - size_t alloc_size; - - /* Cast away extern "C" from the type of xrealloc. */ - line_map_realloc reallocator = (set->reallocator - ? set->reallocator - : (line_map_realloc) xrealloc); - line_map_round_alloc_size_func round_alloc_size = - set->round_alloc_size; - - size_t map_size = (macro_map_p - ? sizeof (line_map_macro) - : sizeof (line_map_ordinary)); + /* We need more space! */ + if (!num_maps_allocated) + num_maps_allocated = 128; + num_maps_allocated *= 2; + + size_t size_of_a_map; + void *buffer; + if (macro_p) + { + size_of_a_map = sizeof (line_map_macro); + buffer = set->info_macro.maps; + } + else + { + size_of_a_map = sizeof (line_map_ordinary); + buffer = set->info_ordinary.maps; + } /* We are going to execute some dance to try to reduce the overhead of the memory allocator, in case we are using the ggc-page.c one. The actual size of memory we are going to get back from the - allocator is the smallest power of 2 that is greater than the - size we requested. So let's consider that size then. */ - - alloc_size = - (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256) - * map_size; - - /* Get the actual size of memory that is going to be allocated - by the allocator. */ - alloc_size = round_alloc_size (alloc_size); + allocator may well be larger than what we ask for. Use this + hook to find what that size is. */ + size_t alloc_size + = set->round_alloc_size (num_maps_allocated * size_of_a_map); /* Now alloc_size contains the exact memory size we would get if we have asked for the initial alloc_size amount of memory. - Let's get back to the number of macro map that amounts - to. */ - LINEMAPS_ALLOCATED (set, macro_map_p) = - alloc_size / map_size; - - /* And now let's really do the re-allocation. */ - if (macro_map_p) - { - set->info_macro.maps - = (line_map_macro *) (*reallocator) (set->info_macro.maps, - (LINEMAPS_ALLOCATED (set, macro_map_p) - * map_size)); - result = &set->info_macro.maps[LINEMAPS_USED (set, macro_map_p)]; - } - else - { - set->info_ordinary.maps = - (line_map_ordinary *) (*reallocator) (set->info_ordinary.maps, - (LINEMAPS_ALLOCATED (set, macro_map_p) - * map_size)); - result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)]; - } - memset (result, 0, - ((LINEMAPS_ALLOCATED (set, macro_map_p) - - LINEMAPS_USED (set, macro_map_p)) - * map_size)); - } - else - { - if (macro_map_p) - result = &set->info_macro.maps[LINEMAPS_USED (set, macro_map_p)]; + Let's get back to the number of map that amounts to. */ + unsigned num_maps = alloc_size / size_of_a_map; + buffer = set->reallocator (buffer, num_maps * size_of_a_map); + memset ((char *)buffer + num_maps_used * size_of_a_map, 0, + (num_maps - num_maps_used) * size_of_a_map); + if (macro_p) + set->info_macro.maps = (line_map_macro *)buffer; else - result = &set->info_ordinary.maps[LINEMAPS_USED (set, macro_map_p)]; + set->info_ordinary.maps = (line_map_ordinary *)buffer; + LINEMAPS_ALLOCATED (set, macro_p) = num_maps; } - result->start_location = start_location; + line_map *result = (macro_p ? (line_map *)&set->info_macro.maps[num_maps_used] + : (line_map *)&set->info_ordinary.maps[num_maps_used]); + LINEMAPS_USED (set, macro_p)++; - LINEMAPS_USED (set, macro_map_p)++; + result->start_location = start_location; return result; } @@ -504,6 +494,11 @@ linemap_add (struct line_maps *set, enum lc_reason reason, } linemap_assert (reason != LC_ENTER_MACRO); + + if (start_location >= LINE_MAP_MAX_LOCATION) + /* We ran out of line map space. */ + start_location = 0; + line_map_ordinary *map = linemap_check_ordinary (new_linemap (set, start_location)); map->reason = reason; @@ -514,19 +509,19 @@ linemap_add (struct line_maps *set, enum lc_reason reason, if (reason == LC_RENAME_VERBATIM) reason = LC_RENAME; + const line_map_ordinary *from = NULL; if (reason == LC_LEAVE) { /* When we are just leaving an "included" file, and jump to the next location inside the "includer" right after the #include "included", this variable points the map in use right before the #include "included", inside the same "includer" file. */ - line_map_ordinary *from; linemap_assert (!MAIN_FILE_P (map - 1)); /* (MAP - 1) points to the map we are leaving. The map from which (MAP - 1) got included should be the map that comes right before MAP in the same file. */ - from = INCLUDED_FROM (set, map - 1); + from = linemap_included_from_linemap (set, map - 1); /* A TO_FILE of NULL is special - we use the natural values. */ if (to_file == NULL) @@ -558,19 +553,24 @@ linemap_add (struct line_maps *set, enum lc_reason reason, if (reason == LC_ENTER) { - map->included_from = - set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2); + if (set->depth == 0) + map->included_from = 0; + else + /* The location of the end of the just-closed map. */ + map->included_from + = (((map[0].start_location - 1 - map[-1].start_location) + & ~((1 << map[-1].m_column_and_range_bits) - 1)) + + map[-1].start_location); set->depth++; if (set->trace_includes) trace_include (set, map); } else if (reason == LC_RENAME) - map->included_from = ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]); + map->included_from = linemap_included_from (&map[-1]); else if (reason == LC_LEAVE) { set->depth--; - map->included_from = - ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1)); + map->included_from = linemap_included_from (from); } return map; @@ -1781,17 +1781,13 @@ linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro) if (!is_macro) { const line_map_ordinary *ord_map = linemap_check_ordinary (map); - unsigned includer_ix; - const line_map_ordinary *includer_map; - - includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (ord_map); - includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set) - ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix) - : NULL; + const line_map_ordinary *includer_map + = linemap_included_from_linemap (set, ord_map); fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (ord_map), ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map)); - fprintf (stream, "Included from: [%d] %s\n", includer_ix, + fprintf (stream, "Included from: [%d] %s\n", + includer_map ? int (includer_map - set->info_ordinary.maps) : -1, includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None"); } else @@ -1841,9 +1837,11 @@ linemap_dump_location (struct line_maps *set, if (e) from = "N/A"; else - from = (INCLUDED_FROM (set, map)) - ? LINEMAP_FILE (INCLUDED_FROM (set, map)) - : "<NULL>"; + { + const line_map_ordinary *from_map + = linemap_included_from_linemap (set, map); + from = from_map ? LINEMAP_FILE (from_map) : "<NULL>"; + } } /* P: path, L: line, C: column, S: in-system-header, M: map address, @@ -1997,7 +1995,8 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary, /* Construct a rich_location with location LOC as its initial range. */ -rich_location::rich_location (line_maps *set, source_location loc) : +rich_location::rich_location (line_maps *set, source_location loc, + const range_label *label) : m_line_table (set), m_ranges (), m_column_override (0), @@ -2006,7 +2005,7 @@ rich_location::rich_location (line_maps *set, source_location loc) : m_seen_impossible_fixit (false), m_fixits_cannot_be_auto_applied (false) { - add_range (loc, true); + add_range (loc, SHOW_RANGE_WITH_CARET, label); } /* The destructor for class rich_location. */ @@ -2082,16 +2081,19 @@ rich_location::override_column (int column) /* Add the given range. */ void -rich_location::add_range (source_location loc, bool show_caret_p) +rich_location::add_range (source_location loc, + enum range_display_kind range_display_kind, + const range_label *label) { location_range range; range.m_loc = loc; - range.m_show_caret_p = show_caret_p; + range.m_range_display_kind = range_display_kind; + range.m_label = label; m_ranges.push (range); } /* Add or overwrite the location given by IDX, setting its location to LOC, - and setting its "should my caret be printed" flag to SHOW_CARET_P. + and setting its m_range_display_kind to RANGE_DISPLAY_KIND. It must either overwrite an existing location, or add one *exactly* on the end of the array. @@ -2105,19 +2107,19 @@ rich_location::add_range (source_location loc, bool show_caret_p) void rich_location::set_range (unsigned int idx, source_location loc, - bool show_caret_p) + enum range_display_kind range_display_kind) { /* We can either overwrite an existing range, or add one exactly on the end of the array. */ linemap_assert (idx <= m_ranges.count ()); if (idx == m_ranges.count ()) - add_range (loc, show_caret_p); + add_range (loc, range_display_kind); else { location_range *locrange = get_range (idx); locrange->m_loc = loc; - locrange->m_show_caret_p = show_caret_p; + locrange->m_range_display_kind = range_display_kind; } if (idx == 0) diff --git a/libcpp/macro.c b/libcpp/macro.c index 683f918..3629e83 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -85,8 +85,9 @@ struct macro_arg_token_iter 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 = @@ -308,15 +309,14 @@ static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *, 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 *, cpp_macro *); +static bool parse_params (cpp_reader *, unsigned *, bool *); static void check_trad_stringification (cpp_reader *, const cpp_macro *, const cpp_string *); static bool reached_end_of_context (cpp_context *); @@ -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; @@ -1235,13 +1235,14 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node, 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 @@ -1273,17 +1274,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, function where set this flag to FALSE. */ pfile->about_to_expand_macro_p = true; - if ((node->flags & NODE_BUILTIN) && !(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if ((!pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, node)) - && pfile->cb.used_define) - 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; @@ -1329,13 +1320,9 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, /* Disable the macro within its expansion. */ node->flags |= NODE_DISABLED; - if (!(node->flags & NODE_USED)) - { - node->flags |= NODE_USED; - if (pfile->cb.used_define) - pfile->cb.used_define (pfile, pfile->directive_line, node); - } - + /* Laziness can only affect the expansion tokens of the macro, + not its fun-likeness or parameters. */ + _cpp_maybe_notify_macro_use (pfile, node); if (pfile->cb.used) pfile->cb.used (pfile, location, node); @@ -1413,10 +1400,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 @@ -1776,7 +1761,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, 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 { @@ -2746,7 +2731,7 @@ cpp_get_token_1 (cpp_reader *pfile, source_location *location) 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)) @@ -2996,7 +2981,6 @@ static bool warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, const cpp_macro *macro2) { - const cpp_macro *macro1; unsigned int i; /* Some redefinitions need to be warned about regardless. */ @@ -3005,9 +2989,7 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, /* Suppress warnings for builtins that lack the NODE_WARN flag, unless Wbuiltin-macro-redefined. */ - if (node->flags & NODE_BUILTIN - && (!pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, node))) + if (cpp_builtin_macro_p (node)) return CPP_OPTION (pfile, warn_builtin_macro_redefined); /* Redefinitions of conditional (context-sensitive) macros, on @@ -3015,9 +2997,17 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, if (node->flags & NODE_CONDITIONAL) return false; + cpp_macro *macro1 = node->value.macro; + if (macro1->lazy) + { + /* We don't want to mark MACRO as used, but do need to finalize + its laziness. */ + pfile->cb.user_lazy_macro (pfile, macro1, macro1->lazy - 1); + macro1->lazy = 0; + } + /* Redefinition of a macro is allowed if and only if the old and new definitions are the same. (6.10.3 paragraph 2). */ - macro1 = node->value.macro; /* Don't check count here as it can be different in valid traditional redefinitions with just whitespace differences. */ @@ -3028,7 +3018,7 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, /* Check parameter spellings. */ for (i = 0; i < macro1->paramc; i++) - if (macro1->params[i] != macro2->params[i]) + if (macro1->parm.params[i] != macro2->parm.params[i]) return true; /* Check the replacement text or tokens. */ @@ -3051,124 +3041,164 @@ _cpp_free_definition (cpp_hashnode *h) { /* 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 - macro MACRO. Returns zero on success, nonzero if the parameter is - a duplicate. */ + macro MACRO. Returns true on success, false on failure. */ bool -_cpp_save_parameter (cpp_reader *pfile, cpp_macro *macro, cpp_hashnode *node, +_cpp_save_parameter (cpp_reader *pfile, unsigned n, cpp_hashnode *node, cpp_hashnode *spelling) { - unsigned int len; /* 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)); - return true; + return false; } - if (BUFF_ROOM (pfile->a_buff) - < (macro->paramc + 1) * sizeof (cpp_hashnode *)) - _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *)); - - ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = spelling; - node->flags |= NODE_MACRO_ARG; - len = macro->paramc * sizeof (struct macro_arg_saved_data); + unsigned len = (n + 1) * sizeof (struct macro_arg_saved_data); if (len > pfile->macro_buffer_len) { - pfile->macro_buffer = XRESIZEVEC (unsigned char, pfile->macro_buffer, - len); + pfile->macro_buffer + = XRESIZEVEC (unsigned char, pfile->macro_buffer, len); pfile->macro_buffer_len = len; } - struct macro_arg_saved_data save; - save.value = node->value; - save.canonical_node = node; - ((struct macro_arg_saved_data *) pfile->macro_buffer)[macro->paramc - 1] - = save; - node->value.arg_index = macro->paramc; - return false; + 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->type = NT_MACRO_ARG; + /* Index is 1 based. */ + node->value.arg_index = n + 1; + + return true; } -/* Check the syntax of the parameters in a MACRO definition. Returns - false if an error occurs. */ +/* Restore the parameters to their previous state. */ +void +_cpp_unsave_parameters (cpp_reader *pfile, unsigned n) +{ + /* Clear the fast argument lookup indices. */ + while (n--) + { + struct macro_arg_saved_data *save = + &((struct macro_arg_saved_data *) pfile->macro_buffer)[n]; + + struct cpp_hashnode *node = save->canonical_node; + node->type = save->type; + node->value = save->value; + } +} + +/* Check the syntax of the parameters in a MACRO definition. Return + false on failure. Set *N_PTR and *VARADIC_PTR as appropriate. + '(' ')' + '(' parm-list ',' last-parm ')' + '(' last-parm ')' + parm-list: name + | parm-list, name + last-parm: name + | name '...' + | '...' +*/ + static bool -parse_params (cpp_reader *pfile, cpp_macro *macro) +parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) { - unsigned int prev_ident = 0; + unsigned nparms = 0; + bool ok = false; - for (;;) + for (bool prev_ident = false;;) { const cpp_token *token = _cpp_lex_token (pfile); switch (token->type) { - default: + case CPP_COMMENT: /* Allow/ignore comments in parameter lists if we are preserving comments in macro expansions. */ - if (token->type == CPP_COMMENT - && ! CPP_OPTION (pfile, discard_comments_in_macro_exp)) - continue; + if (!CPP_OPTION (pfile, discard_comments_in_macro_exp)) + break; - cpp_error (pfile, CPP_DL_ERROR, - "\"%s\" may not appear in macro parameter list", - cpp_token_as_text (pfile, token)); - return false; + /* FALLTHRU */ + default: + bad: + { + const char *const msgs[5] = + { + N_("expected parameter name, found \"%s\""), + N_("expected ',' or ')', found \"%s\""), + N_("expected parameter name before end of line"), + N_("expected ')' before end of line"), + N_("expected ')' after \"...\"") + }; + unsigned ix = prev_ident; + const unsigned char *as_text = NULL; + if (*varadic_ptr) + ix = 4; + else if (token->type == CPP_EOF) + ix += 2; + else + as_text = cpp_token_as_text (pfile, token); + cpp_error (pfile, CPP_DL_ERROR, msgs[ix], as_text); + } + goto out; case CPP_NAME: - if (prev_ident) - { - cpp_error (pfile, CPP_DL_ERROR, - "macro parameters must be comma-separated"); - return false; - } - prev_ident = 1; - - if (_cpp_save_parameter (pfile, macro, token->val.node.node, - token->val.node.spelling)) - return false; - continue; + if (prev_ident || *varadic_ptr) + goto bad; + prev_ident = true; + + if (!_cpp_save_parameter (pfile, nparms, token->val.node.node, + token->val.node.spelling)) + goto out; + nparms++; + break; case CPP_CLOSE_PAREN: - if (prev_ident || macro->paramc == 0) - return true; + if (prev_ident || !nparms || *varadic_ptr) + { + ok = true; + goto out; + } - /* Fall through to pick up the error. */ /* FALLTHRU */ case CPP_COMMA: - if (!prev_ident) - { - cpp_error (pfile, CPP_DL_ERROR, "parameter name missing"); - return false; - } - prev_ident = 0; - continue; + if (!prev_ident || *varadic_ptr) + goto bad; + prev_ident = false; + break; case CPP_ELLIPSIS: - macro->variadic = 1; + if (*varadic_ptr) + goto bad; + *varadic_ptr = true; if (!prev_ident) { - _cpp_save_parameter (pfile, macro, + /* An ISO bare ellipsis. */ + _cpp_save_parameter (pfile, nparms, pfile->spec_nodes.n__VA_ARGS__, pfile->spec_nodes.n__VA_ARGS__); + nparms++; pfile->state.va_args_ok = 1; if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, cpp_pedantic) && CPP_OPTION (pfile, warn_variadic_macros)) - { - if (CPP_OPTION (pfile, cplusplus)) - cpp_pedwarning - (pfile, CPP_W_VARIADIC_MACROS, - "anonymous variadic macros were introduced in C++11"); - else - cpp_pedwarning - (pfile, CPP_W_VARIADIC_MACROS, - "anonymous variadic macros were introduced in C99"); - } + cpp_pedwarning + (pfile, CPP_W_VARIADIC_MACROS, + CPP_OPTION (pfile, cplusplus) + ? N_("anonymous variadic macros were introduced in C++11") + : N_("anonymous variadic macros were introduced in C99")); else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0 && ! CPP_OPTION (pfile, cplusplus)) cpp_error (pfile, CPP_DL_WARNING, @@ -3176,54 +3206,38 @@ parse_params (cpp_reader *pfile, cpp_macro *macro) } else if (CPP_OPTION (pfile, cpp_pedantic) && CPP_OPTION (pfile, warn_variadic_macros)) - { - if (CPP_OPTION (pfile, cplusplus)) - cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS, - "ISO C++ does not permit named variadic macros"); - else - cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS, - "ISO C does not permit named variadic macros"); - } - - /* We're at the end, and just expect a closing parenthesis. */ - token = _cpp_lex_token (pfile); - if (token->type == CPP_CLOSE_PAREN) - return true; - /* Fall through. */ - - case CPP_EOF: - cpp_error (pfile, CPP_DL_ERROR, "missing ')' in macro parameter list"); - return false; + cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS, + CPP_OPTION (pfile, cplusplus) + ? N_("ISO C++ does not permit named variadic macros") + : N_("ISO C does not permit named variadic macros")); + break; } } -} -/* 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)); + out: + *n_ptr = nparms; - return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++]; + return ok; } /* 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? */ - 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; @@ -3233,62 +3247,58 @@ lex_expansion_token (cpp_reader *pfile, cpp_macro *macro) && (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; + + /* 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; - /* Get the first token of the expansion (or the '(' of a - function-like macro). */ - ctoken = _cpp_lex_token (pfile); - - if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE)) + if (token->flags & PREV_WHITE) + /* Preceeded by space, must be part of expansion. */; + else if (token->type == CPP_OPEN_PAREN) { - bool ok = parse_params (pfile, macro); - macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff); - if (!ok) - return false; + /* An open-paren, get a parameter list. */ + if (!parse_params (pfile, &nparms, &varadic)) + goto out; - /* 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; + params = (cpp_hashnode **)_cpp_commit_buff + (pfile, sizeof (cpp_hashnode *) * nparms); + token = NULL; } - else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE)) + 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 from the basic source character set there. */ if (CPP_OPTION (pfile, c99)) - { - if (CPP_OPTION (pfile, cplusplus)) - cpp_error (pfile, CPP_DL_PEDWARN, - "ISO C++11 requires whitespace after the macro name"); - else - cpp_error (pfile, CPP_DL_PEDWARN, - "ISO C99 requires whitespace after the macro name"); - } + cpp_error (pfile, CPP_DL_PEDWARN, + CPP_OPTION (pfile, cplusplus) + ? N_("ISO C++11 requires whitespace after the macro name") + : N_("ISO C99 requires whitespace after the macro name")); else { int warntype = CPP_DL_WARNING; - switch (ctoken->type) + switch (token->type) { case CPP_ATSIGN: case CPP_AT_NAME: @@ -3299,7 +3309,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) 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: @@ -3312,19 +3322,32 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) } } - 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->parm.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; } - /* The argument doesn't matter here. */ - vaopt_state vaopt_tracker (pfile, macro->variadic, true); - - for (;;) + 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) @@ -3346,7 +3369,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) { cpp_error (pfile, CPP_DL_ERROR, "'#' is not followed by a macro parameter"); - return false; + goto out; } } @@ -3358,8 +3381,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (following_paste_op) { cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg); - return false; + goto out; } + if (!vaopt_tracker.completed ()) + goto out; break; } @@ -3371,17 +3396,19 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) if (macro->count == 1) { cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg); - return false; + 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) @@ -3389,78 +3416,67 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) 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) - return false; - - following_paste_op = (token->type == CPP_PASTE); - token = lex_expansion_token (pfile, macro); + goto out; } - if (!vaopt_tracker.completed ()) - return false; - - macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); - macro->traditional = 0; + /* We're committed to winning now. */ + ok = true; /* 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]; - return true; + out: + pfile->state.va_args_ok = 0; + _cpp_unsave_parameters (pfile, nparms); + + 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; - unsigned int i; - 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->parm.params = 0; + macro->lazy = 0; macro->paramc = 0; macro->variadic = 0; macro->used = !CPP_OPTION (pfile, warn_unused_macros); @@ -3470,62 +3486,51 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) /* To suppress some diagnostics. */ macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; - if (CPP_OPTION (pfile, traditional)) - ok = _cpp_create_trad_definition (pfile, macro); - else - { - ok = create_iso_definition (pfile, macro); + macro->kind = kind; - /* We set the type for SEEN_EOL() in directives.c. - - Longer term we should lex the whole line before coming here, - and just copy the expansion. */ + return macro; +} - /* Stop the lexer accepting __VA_ARGS__. */ - pfile->state.va_args_ok = 0; - } +/* Parse a macro and save its expansion. Returns nonzero on success. */ +bool +_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) +{ + cpp_macro *macro; - /* Clear the fast argument lookup indices. */ - for (i = macro->paramc; i-- > 0; ) - { - struct macro_arg_saved_data *save = - &((struct macro_arg_saved_data *) pfile->macro_buffer)[i]; - struct cpp_hashnode *node = save->canonical_node; - node->flags &= ~ NODE_MACRO_ARG; - node->value = save->value; - } + if (CPP_OPTION (pfile, traditional)) + macro = _cpp_create_trad_definition (pfile); + else + 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); 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->type = NT_USER_MACRO; node->value.macro = macro; if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")) && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_FORMAT_MACROS") @@ -3541,7 +3546,52 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) conditional flag */ node->flags &= ~NODE_CONDITIONAL; - return ok; + return true; +} + +extern void +cpp_define_lazily (cpp_reader *pfile, cpp_hashnode *node, unsigned num) +{ + cpp_macro *macro = node->value.macro; + + gcc_checking_assert (pfile->cb.user_lazy_macro && macro && num < UCHAR_MAX); + + macro->lazy = num + 1; +} + +/* 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_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; + + 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 @@ -3572,7 +3622,7 @@ check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro, identifier inside the string matches one of them. */ for (i = 0; i < macro->paramc; i++) { - const cpp_hashnode *node = macro->params[i]; + const cpp_hashnode *node = macro->parm.params[i]; if (NODE_LEN (node) == len && !memcmp (p, NODE_NAME (node), len)) @@ -3586,15 +3636,6 @@ check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro, } } -/* Returns true of NODE is a function-like macro. */ -bool -cpp_fun_like_macro_p (cpp_hashnode *node) -{ - return (node->type == NT_MACRO - && (node->flags & (NODE_BUILTIN | NODE_MACRO_ARG)) == 0 - && node->value.macro->fun_like); -} - /* Returns the name, arguments and expansion of a macro, in a format suitable to be read back in again, and therefore also for DWARF 2 debugging info. e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION". @@ -3604,23 +3645,12 @@ const unsigned char * cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) { unsigned int i, len; - const cpp_macro *macro; unsigned char *buffer; - if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN)) - { - if (node->type != NT_MACRO - || !pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, node)) - { - cpp_error (pfile, CPP_DL_ICE, - "invalid hash type %d in cpp_macro_definition", - node->type); - return 0; - } - } + gcc_checking_assert (cpp_user_macro_p (node)); + + const cpp_macro *macro = node->value.macro; - macro = node->value.macro; /* Calculate length. */ len = NODE_LEN (node) * 10 + 2; /* ' ' and NUL. */ if (macro->fun_like) @@ -3628,7 +3658,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) len += 4; /* "()" plus possible final ".." of named varargs (we have + 1 below). */ for (i = 0; i < macro->paramc; i++) - len += NODE_LEN (macro->params[i]) + 1; /* "," */ + len += NODE_LEN (macro->parm.params[i]) + 1; /* "," */ } /* This should match below where we fill in the buffer. */ @@ -3639,7 +3669,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) 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); @@ -3672,7 +3702,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) *buffer++ = '('; for (i = 0; i < macro->paramc; i++) { - cpp_hashnode *param = macro->params[i]; + cpp_hashnode *param = macro->parm.params[i]; if (param != pfile->spec_nodes.n__VA_ARGS__) { @@ -3703,7 +3733,7 @@ cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) 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++ = ' '; diff --git a/libcpp/pch.c b/libcpp/pch.c index 997c4da..04d7094 100644 --- a/libcpp/pch.c +++ b/libcpp/pch.c @@ -50,50 +50,47 @@ static int 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) - && (!pfile->cb.user_builtin_macro - || !pfile->cb.user_builtin_macro (pfile, hn))) - 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: @@ -228,8 +225,11 @@ count_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) 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. */ @@ -250,10 +250,6 @@ count_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) } return 1; - case NT_ASSERTION: - /* Not currently implemented. */ - return 1; - default: abort (); } @@ -267,8 +263,11 @@ write_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) 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. */ @@ -289,10 +288,6 @@ write_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p) } return 1; - case NT_ASSERTION: - /* Not currently implemented. */ - return 1; - default: abort (); } @@ -623,7 +618,7 @@ cpp_valid_state (cpp_reader *r, const char *name, int fd) 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 @@ -760,13 +755,7 @@ save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p) { struct save_macro_data *data = (struct save_macro_data *)data_p; - if ((h->flags & NODE_BUILTIN) - && h->type == NT_MACRO - && r->cb.user_builtin_macro) - r->cb.user_builtin_macro (r, h); - - if (h->type != NT_VOID - && (h->flags & NODE_BUILTIN) == 0) + if (cpp_user_macro_p (h)) { if (data->count == data->array_size) { @@ -774,28 +763,14 @@ save_macros (cpp_reader *r, cpp_hashnode *h, void *data_p) 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; } diff --git a/libcpp/traditional.c b/libcpp/traditional.c index b25d522..51c3e35 100644 --- a/libcpp/traditional.c +++ b/libcpp/traditional.c @@ -89,7 +89,7 @@ static cpp_hashnode *lex_identifier (cpp_reader *, const uchar *); static const uchar *copy_comment (cpp_reader *, const uchar *, int); static void check_output_buffer (cpp_reader *, size_t); static void push_replacement_text (cpp_reader *, cpp_hashnode *); -static bool scan_parameters (cpp_reader *, cpp_macro *); +static bool scan_parameters (cpp_reader *, unsigned *); static bool recursive_macro (cpp_reader *, cpp_hashnode *); static void save_replacement_text (cpp_reader *, cpp_macro *, unsigned int); static void maybe_start_funlike (cpp_reader *, cpp_hashnode *, const uchar *, @@ -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) @@ -545,7 +545,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro, 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. */ @@ -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); @@ -853,7 +853,6 @@ push_replacement_text (cpp_reader *pfile, cpp_hashnode *node) cpp_macro *macro = node->value.macro; macro->used = 1; text = macro->exp.text; - macro->traditional = 1; len = macro->count; } @@ -919,7 +918,7 @@ _cpp_replacement_text_len (const cpp_macro *macro) len += b->text_len; if (b->arg_index == 0) break; - len += NODE_LEN (macro->params[b->arg_index - 1]); + len += NODE_LEN (macro->parm.params[b->arg_index - 1]); exp += BLOCK_LEN (b->text_len); } } @@ -948,7 +947,7 @@ _cpp_copy_replacement_text (const cpp_macro *macro, uchar *dest) dest += b->text_len; if (b->arg_index == 0) break; - param = macro->params[b->arg_index - 1]; + param = macro->parm.params[b->arg_index - 1]; memcpy (dest, NODE_NAME (param), NODE_LEN (param)); dest += NODE_LEN (param); exp += BLOCK_LEN (b->text_len); @@ -1082,11 +1081,12 @@ replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro) duplicate parameter). On success, CUR (pfile->context) is just past the closing parenthesis. */ static bool -scan_parameters (cpp_reader *pfile, cpp_macro *macro) +scan_parameters (cpp_reader *pfile, unsigned *n_ptr) { const uchar *cur = CUR (pfile->context) + 1; bool ok; + unsigned nparms = 0; for (;;) { cur = skip_whitespace (pfile, cur, true /* skip_comments */); @@ -1095,8 +1095,9 @@ scan_parameters (cpp_reader *pfile, cpp_macro *macro) { struct cpp_hashnode *id = lex_identifier (pfile, cur); ok = false; - if (_cpp_save_parameter (pfile, macro, id, id)) + if (!_cpp_save_parameter (pfile, nparms, id, id)) break; + nparms++; cur = skip_whitespace (pfile, CUR (pfile->context), true /* skip_comments */); if (*cur == ',') @@ -1108,10 +1109,12 @@ scan_parameters (cpp_reader *pfile, cpp_macro *macro) break; } - ok = (*cur == ')' && macro->paramc == 0); + ok = (*cur == ')' && !nparms); break; } + *n_ptr = nparms; + if (!ok) cpp_error (pfile, CPP_DL_ERROR, "syntax error in macro parameter list"); @@ -1139,7 +1142,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, memcpy (exp, pfile->out.base, len); exp[len] = '\n'; macro->exp.text = exp; - macro->traditional = 1; macro->count = len; } else @@ -1155,7 +1157,6 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, 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; @@ -1175,12 +1176,15 @@ save_replacement_text (cpp_reader *pfile, cpp_macro *macro, /* 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. */ @@ -1192,20 +1196,23 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) /* Is this a function-like macro? */ if (* CUR (context) == '(') { - bool ok = scan_parameters (pfile, macro); + 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->parm.params = params; + macro->paramc = nparms; + macro->fun_like = fun_like != 0; } /* Skip leading whitespace in the replacement text. */ @@ -1217,18 +1224,20 @@ _cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro) _cpp_scan_out_logical_line (pfile, macro, false); pfile->state.prevent_expansion--; - if (!macro) - return false; + _cpp_unsave_parameters (pfile, nparms); - /* 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 |