X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=libcpp%2Fdirectives.c;h=1ada834da17482ebd75fd9ed57312b0e41cd24a7;hb=09d943db95964895157c8bb6a691dc4f3719afe6;hp=631557df8bb5eec62ef2b28b19c06f286676de1d;hpb=a7d2e480fef2ab41d6a0de9ecaeb7897d401153e;p=thirdparty%2Fgcc.git diff --git a/libcpp/directives.c b/libcpp/directives.c index 631557df8bb5..1ada834da174 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -1,5 +1,5 @@ /* CPP Library. (Directive handling.) - Copyright (C) 1986-2014 Free Software Foundation, Inc. + Copyright (C) 1986-2019 Free Software Foundation, Inc. Contributed by Per Bothner, 1994-95. Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 @@ -30,7 +30,7 @@ along with this program; see the file COPYING3. If not see struct if_stack { struct if_stack *next; - source_location line; /* Line where condition started. */ + location_t line; /* Line where condition started. */ const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */ bool skip_elses; /* Can future #else / #elif be skipped? */ bool was_skipping; /* If were skipping on entry. */ @@ -98,11 +98,12 @@ static void directive_diagnostics (cpp_reader *, const directive *, int); static void run_directive (cpp_reader *, int, const char *, size_t); static char *glue_header_name (cpp_reader *); static const char *parse_include (cpp_reader *, int *, const cpp_token ***, - source_location *); + location_t *); static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *); static unsigned int read_flag (cpp_reader *, unsigned int); static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *); -static void do_diagnostic (cpp_reader *, int, int, int); +static void do_diagnostic (cpp_reader *, enum cpp_diagnostic_level code, + enum cpp_warning_reason reason, int); static cpp_hashnode *lex_macro_node (cpp_reader *, bool); static int undefine_macros (cpp_reader *, cpp_hashnode *, void *); static void do_include_common (cpp_reader *, enum include_type); @@ -122,44 +123,40 @@ static void do_pragma_error (cpp_reader *); static void do_linemarker (cpp_reader *); 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 *); -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 void destringize_and_run (cpp_reader *, const cpp_string *, + location_t); +static bool parse_answer (cpp_reader *, int, location_t, 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 *); static void cpp_pop_definition (cpp_reader *, struct def_pragma_macro *); -/* This is the table of directive handlers. It is ordered by - frequency of occurrence; the numbers at the end are directive - counts from all the source code I have lying around (egcs and libc - CVS as of 1999-05-18, plus grub-0.5.91, linux-2.2.9, and - pcmcia-cs-3.0.9). This is no longer important as directive lookup - is now O(1). All extensions other than #warning, #include_next, - and #import are deprecated. The name is where the extension - appears to have come from. */ +/* This is the table of directive handlers. All extensions other than + #warning, #include_next, and #import are deprecated. The name is + where the extension appears to have come from. */ #define DIRECTIVE_TABLE \ -D(define, T_DEFINE = 0, KANDR, IN_I) /* 270554 */ \ -D(include, T_INCLUDE, KANDR, INCL | EXPAND) /* 52262 */ \ -D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \ -D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \ -D(if, T_IF, KANDR, COND | IF_COND | EXPAND) /* 18162 */ \ -D(else, T_ELSE, KANDR, COND) /* 9863 */ \ -D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) /* 9675 */ \ -D(undef, T_UNDEF, KANDR, IN_I) /* 4837 */ \ -D(line, T_LINE, KANDR, EXPAND) /* 2465 */ \ -D(elif, T_ELIF, STDC89, COND | EXPAND) /* 610 */ \ -D(error, T_ERROR, STDC89, 0) /* 475 */ \ -D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \ -D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \ -D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND) /* 19 */ \ -D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \ -D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* 0 ObjC */ \ -D(assert, T_ASSERT, EXTENSION, DEPRECATED) /* 0 SVR4 */ \ -D(unassert, T_UNASSERT, EXTENSION, DEPRECATED) /* 0 SVR4 */ \ -D(sccs, T_SCCS, EXTENSION, IN_I) /* 0 SVR4? */ + D(define, T_DEFINE = 0, KANDR, IN_I) \ + D(include, T_INCLUDE, KANDR, INCL | EXPAND) \ + D(endif, T_ENDIF, KANDR, COND) \ + D(ifdef, T_IFDEF, KANDR, COND | IF_COND) \ + D(if, T_IF, KANDR, COND | IF_COND | EXPAND) \ + D(else, T_ELSE, KANDR, COND) \ + D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) \ + D(undef, T_UNDEF, KANDR, IN_I) \ + D(line, T_LINE, KANDR, EXPAND) \ + D(elif, T_ELIF, STDC89, COND | EXPAND) \ + D(error, T_ERROR, STDC89, 0) \ + D(pragma, T_PRAGMA, STDC89, IN_I) \ + D(warning, T_WARNING, EXTENSION, 0) \ + D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND) \ + D(ident, T_IDENT, EXTENSION, IN_I) \ + D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* ObjC */ \ + D(assert, T_ASSERT, EXTENSION, DEPRECATED) /* SVR4 */ \ + D(unassert, T_UNASSERT, EXTENSION, DEPRECATED) /* SVR4 */ \ + D(sccs, T_SCCS, EXTENSION, IN_I) /* SVR4? */ /* #sccs is synonymous with #ident. */ #define do_sccs do_ident @@ -187,6 +184,16 @@ static const directive dtable[] = DIRECTIVE_TABLE }; #undef D + +/* A NULL-terminated array of directive names for use + when suggesting corrections for misspelled directives. */ +#define D(name, t, origin, flags) #name, +static const char * const directive_names[] = { +DIRECTIVE_TABLE + NULL +}; +#undef D + #undef DIRECTIVE_TABLE /* Wrapper struct directive for linemarkers. @@ -197,8 +204,6 @@ static const directive linemarker_dir = do_linemarker, UC"#", 1, KANDR, IN_I }; -#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF) - /* Skip any remaining tokens in a directive. */ static void skip_rest_of_line (cpp_reader *pfile) @@ -213,16 +218,33 @@ skip_rest_of_line (cpp_reader *pfile) ; } -/* Ensure there are no stray tokens at the end of a directive. If - EXPAND is true, tokens macro-expanding to nothing are allowed. */ +/* Helper function for check_oel. */ + static void -check_eol (cpp_reader *pfile, bool expand) +check_eol_1 (cpp_reader *pfile, bool expand, enum cpp_warning_reason reason) { if (! SEEN_EOL () && (expand ? cpp_get_token (pfile) : _cpp_lex_token (pfile))->type != CPP_EOF) - cpp_error (pfile, CPP_DL_PEDWARN, "extra tokens at end of #%s directive", - pfile->directive->name); + cpp_pedwarning (pfile, reason, "extra tokens at end of #%s directive", + pfile->directive->name); +} + +/* Variant of check_eol used for Wendif-labels warnings. */ + +static void +check_eol_endif_labels (cpp_reader *pfile) +{ + check_eol_1 (pfile, false, CPP_W_ENDIF_LABELS); +} + +/* Ensure there are no stray tokens at the end of a directive. If + EXPAND is true, tokens macro-expanding to nothing are allowed. */ + +static void +check_eol (cpp_reader *pfile, bool expand) +{ + check_eol_1 (pfile, expand, CPP_W_NONE); } /* Ensure there are no stray tokens other than comments at the end of @@ -329,7 +351,7 @@ prepare_directive_trad (cpp_reader *pfile) if (no_expand) pfile->state.prevent_expansion++; - _cpp_scan_out_logical_line (pfile, NULL); + _cpp_scan_out_logical_line (pfile, NULL, false); if (no_expand) pfile->state.prevent_expansion--; @@ -480,8 +502,35 @@ _cpp_handle_directive (cpp_reader *pfile, int indented) if (CPP_OPTION (pfile, lang) == CLK_ASM) skip = 0; else if (!pfile->state.skipping) - cpp_error (pfile, CPP_DL_ERROR, "invalid preprocessing directive #%s", - cpp_token_as_text (pfile, dname)); + { + const char *unrecognized + = (const char *)cpp_token_as_text (pfile, dname); + const char *hint = NULL; + + /* Call back into gcc to get a spelling suggestion. Ideally + we'd just use best_match from gcc/spellcheck.h (and filter + out the uncommon directives), but that requires moving it + to a support library. */ + if (pfile->cb.get_suggestion) + hint = pfile->cb.get_suggestion (pfile, unrecognized, + directive_names); + + if (hint) + { + rich_location richloc (pfile->line_table, dname->src_loc); + source_range misspelled_token_range + = get_range_from_loc (pfile->line_table, dname->src_loc); + richloc.add_fixit_replace (misspelled_token_range, hint); + cpp_error_at (pfile, CPP_DL_ERROR, &richloc, + "invalid preprocessing directive #%s;" + " did you mean #%s?", + unrecognized, hint); + } + else + cpp_error (pfile, CPP_DL_ERROR, + "invalid preprocessing directive #%s", + unrecognized); + } } pfile->directive = dir; @@ -549,6 +598,11 @@ lex_macro_node (cpp_reader *pfile, bool is_def_or_undef) if (is_def_or_undef && node == pfile->spec_nodes.n_defined) cpp_error (pfile, CPP_DL_ERROR, "\"defined\" cannot be used as a macro name"); + else if (is_def_or_undef + && (node == pfile->spec_nodes.n__has_include__ + || node == pfile->spec_nodes.n__has_include_next__)) + cpp_error (pfile, CPP_DL_ERROR, + "\"__has_include__\" cannot be used as a macro name"); else if (! (node->flags & NODE_POISONED)) return node; } @@ -605,12 +659,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, @@ -635,7 +689,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; } @@ -699,7 +754,7 @@ glue_header_name (cpp_reader *pfile) static const char * parse_include (cpp_reader *pfile, int *pangle_brackets, - const cpp_token ***buf, source_location *location) + const cpp_token ***buf, location_t *location) { char *fname; const cpp_token *header; @@ -757,7 +812,7 @@ do_include_common (cpp_reader *pfile, enum include_type type) const char *fname; int angle_brackets; const cpp_token **buf = NULL; - source_location location; + location_t location; /* Re-enable saving of comments if requested, so that the include callback can dump comments which follow #include. */ @@ -765,22 +820,15 @@ do_include_common (cpp_reader *pfile, enum include_type type) fname = parse_include (pfile, &angle_brackets, &buf, &location); if (!fname) - { - if (buf) - XDELETEVEC (buf); - return; - } + goto done; if (!*fname) - { - cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, - "empty filename in #%s", - pfile->directive->name); - XDELETEVEC (fname); - if (buf) - XDELETEVEC (buf); - return; - } + { + cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, + "empty filename in #%s", + pfile->directive->name); + goto done; + } /* Prevent #include recursion. */ if (pfile->line_table->depth >= CPP_STACK_MAX) @@ -795,9 +843,10 @@ do_include_common (cpp_reader *pfile, enum include_type type) pfile->directive->name, fname, angle_brackets, buf); - _cpp_stack_include (pfile, fname, angle_brackets, type); + _cpp_stack_include (pfile, fname, angle_brackets, type, location); } + done: XDELETEVEC (fname); if (buf) XDELETEVEC (buf); @@ -889,8 +938,8 @@ strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) static void do_line (cpp_reader *pfile) { - const struct line_maps *line_table = pfile->line_table; - const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table); + struct line_maps *line_table = pfile->line_table; + const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table); /* skip_rest_of_line() may cause line table to be realloc()ed so note down sysp right now. */ @@ -943,6 +992,7 @@ do_line (cpp_reader *pfile) skip_rest_of_line (pfile); _cpp_do_file_change (pfile, LC_RENAME_VERBATIM, new_file, new_lineno, map_sysp); + line_table->seen_line_directive = true; } /* Interpret the # 44 "file" [flags] notation, which has slightly @@ -951,8 +1001,8 @@ do_line (cpp_reader *pfile) static void do_linemarker (cpp_reader *pfile) { - const struct line_maps *line_table = pfile->line_table; - const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table); + struct line_maps *line_table = pfile->line_table; + const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table); const cpp_token *token; const char *new_file = ORDINARY_MAP_FILE_NAME (map); linenum_type new_lineno; @@ -1022,14 +1072,32 @@ do_linemarker (cpp_reader *pfile) skip_rest_of_line (pfile); + if (reason == LC_LEAVE) + { + /* Reread map since cpp_get_token can invalidate it with a + reallocation. */ + map = LINEMAPS_LAST_ORDINARY_MAP (line_table); + const line_map_ordinary *from + = linemap_included_from_linemap (line_table, map); + if (MAIN_FILE_P (map) + || (from + && filename_cmp (ORDINARY_MAP_FILE_NAME (from), new_file) != 0)) + { + cpp_warning (pfile, CPP_W_NONE, + "file \"%s\" linemarker ignored due to " + "incorrect nesting", new_file); + return; + } + } /* Compensate for the increment in linemap_add that occurs in _cpp_do_file_change. We're currently at the start of the line - *following* the #line directive. A separate source_location for this + *following* the #line directive. A separate location_t for this location makes no sense (until we do the LC_LEAVE), and complicates LAST_SOURCE_LINE_LOCATION. */ pfile->line_table->highest_location--; _cpp_do_file_change (pfile, reason, new_file, new_lineno, new_sysp); + line_table->seen_line_directive = true; } /* Arrange the file_change callback. pfile->line has changed to @@ -1041,25 +1109,31 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason, const char *to_file, linenum_type file_line, unsigned int sysp) { + linemap_assert (reason != LC_ENTER_MACRO); const struct line_map *map = linemap_add (pfile->line_table, reason, sysp, to_file, file_line); + const line_map_ordinary *ord_map = NULL; if (map != NULL) - linemap_line_start (pfile->line_table, - ORDINARY_MAP_STARTING_LINE_NUMBER (map), - 127); + { + ord_map = linemap_check_ordinary (map); + linemap_line_start (pfile->line_table, + ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map), + 127); + } if (pfile->cb.file_change) - pfile->cb.file_change (pfile, map); + pfile->cb.file_change (pfile, ord_map); } /* Report a warning or error detected by the program we are processing. Use the directive's tokens in the error message. */ static void -do_diagnostic (cpp_reader *pfile, int code, int reason, int print_dir) +do_diagnostic (cpp_reader *pfile, enum cpp_diagnostic_level code, + enum cpp_warning_reason reason, int print_dir) { const unsigned char *dir_name; unsigned char *line; - source_location src_loc = pfile->cur_token[-1].src_loc; + location_t src_loc = pfile->cur_token[-1].src_loc; if (print_dir) dir_name = pfile->directive->name; @@ -1081,7 +1155,7 @@ do_diagnostic (cpp_reader *pfile, int code, int reason, int print_dir) static void do_error (cpp_reader *pfile) { - do_diagnostic (pfile, CPP_DL_ERROR, 0, 1); + do_diagnostic (pfile, CPP_DL_ERROR, CPP_W_NONE, 1); } static void @@ -1356,7 +1430,7 @@ do_pragma (cpp_reader *pfile) { const struct pragma_entry *p = NULL; const cpp_token *token, *pragma_token; - source_location pragma_token_virt_loc = 0; + location_t pragma_token_virt_loc = 0; cpp_token ns_token; unsigned int count = 1; @@ -1462,7 +1536,7 @@ do_pragma_push_macro (cpp_reader *pfile) txt = get__Pragma_string (pfile); if (!txt) { - source_location src_loc = pfile->cur_token[-1].src_loc; + location_t src_loc = pfile->cur_token[-1].src_loc; cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0, "invalid #pragma push_macro directive"); check_eol (pfile, false); @@ -1517,7 +1591,7 @@ do_pragma_pop_macro (cpp_reader *pfile) txt = get__Pragma_string (pfile); if (!txt) { - source_location src_loc = pfile->cur_token[-1].src_loc; + location_t src_loc = pfile->cur_token[-1].src_loc; cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0, "invalid #pragma pop_macro directive"); check_eol (pfile, false); @@ -1582,7 +1656,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); @@ -1619,7 +1693,7 @@ do_pragma_dependency (cpp_reader *pfile) { const char *fname; int angle_brackets, ordering; - source_location location; + location_t location; fname = parse_include (pfile, &angle_brackets, NULL, &location); if (!fname) @@ -1635,7 +1709,7 @@ do_pragma_dependency (cpp_reader *pfile) if (cpp_get_token (pfile)->type != CPP_EOF) { _cpp_backup_tokens (pfile, 1); - do_diagnostic (pfile, CPP_DL_WARNING, 0, 0); + do_diagnostic (pfile, CPP_DL_WARNING, CPP_W_NONE, 0); } } @@ -1724,7 +1798,8 @@ get__Pragma_string (cpp_reader *pfile) /* Destringize IN into a temporary buffer, by removing the first \ of \" and \\ sequences, and process the result as a #pragma directive. */ static void -destringize_and_run (cpp_reader *pfile, const cpp_string *in) +destringize_and_run (cpp_reader *pfile, const cpp_string *in, + location_t expansion_loc) { const unsigned char *src, *limit; char *dest, *result; @@ -1804,6 +1879,12 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in) toks = XRESIZEVEC (cpp_token, toks, maxcount); } toks[count] = *cpp_get_token (pfile); + /* _Pragma is a builtin, so we're not within a macro-map, and so + the token locations are set to bogus ordinary locations + near to, but after that of the "_Pragma". + Paper over this by setting them equal to the location of the + _Pragma itself (PR preprocessor/69126). */ + toks[count].src_loc = expansion_loc; /* Macros have been already expanded by cpp_get_token if the pragma allowed expansion. */ toks[count++].flags |= NO_EXPAND; @@ -1838,14 +1919,14 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in) /* Handle the _Pragma operator. Return 0 on error, 1 if ok. */ int -_cpp_do__Pragma (cpp_reader *pfile) +_cpp_do__Pragma (cpp_reader *pfile, location_t expansion_loc) { const cpp_token *string = get__Pragma_string (pfile); pfile->directive_result.type = CPP_PADDING; if (string) { - destringize_and_run (pfile, &string->val.str); + destringize_and_run (pfile, &string->val.str, expansion_loc); return 1; } cpp_error (pfile, CPP_DL_ERROR, @@ -1869,26 +1950,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); @@ -1915,26 +1979,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); @@ -1990,7 +2038,7 @@ do_else (cpp_reader *pfile) /* Only check EOL if was not originally skipping. */ if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels)) - check_eol (pfile, false); + check_eol_endif_labels (pfile); } } @@ -2014,23 +2062,16 @@ do_elif (cpp_reader *pfile) } ifs->type = T_ELIF; - if (! ifs->was_skipping) + /* See DR#412: "Only the first group whose control condition + evaluates to true (nonzero) is processed; any following groups + are skipped and their controlling directives are processed as + if they were in a group that is skipped." */ + if (ifs->skip_elses) + pfile->state.skipping = 1; + else { - bool value; - /* The standard mandates that the expression be parsed even - if we are skipping elses at this point -- the lexical - restrictions on #elif only apply to skipped groups, but - this group is not being skipped. Temporarily set - skipping to false to get lexer warnings. */ - pfile->state.skipping = 0; - value = _cpp_parse_expr (pfile, false); - if (ifs->skip_elses) - pfile->state.skipping = 1; - else - { - pfile->state.skipping = ! value; - ifs->skip_elses = value; - } + pfile->state.skipping = ! _cpp_parse_expr (pfile, false); + ifs->skip_elses = ! pfile->state.skipping; } /* Invalidate any controlling macro. */ @@ -2051,7 +2092,7 @@ do_endif (cpp_reader *pfile) { /* Only check EOL if was not originally skipping. */ if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels)) - check_eol (pfile, false); + check_eol_endif_labels (pfile); /* If potential control macro, we go back outside again. */ if (ifs->next == 0 && ifs->mi_cmacro) @@ -2098,17 +2139,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, location_t 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) @@ -2118,23 +2155,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; @@ -2142,57 +2182,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); @@ -2204,25 +2239,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) @@ -2239,18 +2276,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); @@ -2262,43 +2299,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); } } @@ -2307,25 +2330,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; - - /* Remove the answer from the list. */ - temp = *p; - if (temp) - *p = temp->next; + cpp_macro **p = find_answer (node, answer); - /* 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); } @@ -2378,11 +2395,11 @@ cpp_define (cpp_reader *pfile, const char *str) void cpp_define_formatted (cpp_reader *pfile, const char *fmt, ...) { - char *ptr = NULL; + char *ptr; va_list ap; va_start (ap, fmt); - vasprintf (&ptr, fmt, ap); + ptr = xvasprintf (fmt, ap); va_end (ap); cpp_define (pfile, ptr); @@ -2424,18 +2441,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; @@ -2446,8 +2463,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) { @@ -2590,6 +2605,8 @@ _cpp_pop_buffer (cpp_reader *pfile) _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0); } + else if (to_free) + free ((void *)to_free); } /* Enter all recognized directives in the hash table. */ @@ -2606,3 +2623,12 @@ _cpp_init_directives (cpp_reader *pfile) node->directive_index = i; } } + +/* Extract header file from a bracket include. Parsing starts after '<'. + The string is malloced and must be freed by the caller. */ +char * +_cpp_bracket_include(cpp_reader *pfile) +{ + return glue_header_name (pfile); +} +