diff options
Diffstat (limited to 'libcpp/directives.c')
-rw-r--r-- | libcpp/directives.c | 77 |
1 files changed, 66 insertions, 11 deletions
diff --git a/libcpp/directives.c b/libcpp/directives.c index 0d09da7..261a584 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -1,5 +1,5 @@ /* CPP Library. (Directive handling.) - Copyright (C) 1986-2020 Free Software Foundation, Inc. + Copyright (C) 1986-2021 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 @@ -56,10 +56,12 @@ struct pragma_entry /* Values for the origin field of struct directive. KANDR directives come from traditional (K&R) C. STDC89 directives come from the - 1989 C standard. EXTENSION directives are extensions. */ + 1989 C standard. STDC2X directives come from the C2X standard. EXTENSION + directives are extensions. */ #define KANDR 0 #define STDC89 1 -#define EXTENSION 2 +#define STDC2X 2 +#define EXTENSION 3 /* Values for the flags field of struct directive. COND indicates a conditional; IF_COND an opening conditional. INCL means to treat @@ -67,13 +69,17 @@ struct pragma_entry means this directive should be handled even if -fpreprocessed is in effect (these are the directives with callback hooks). - EXPAND is set on directives that are always macro-expanded. */ + EXPAND is set on directives that are always macro-expanded. + + ELIFDEF is set on directives that are only handled for standards with the + #elifdef / #elifndef feature. */ #define COND (1 << 0) #define IF_COND (1 << 1) #define INCL (1 << 2) #define IN_I (1 << 3) #define EXPAND (1 << 4) #define DEPRECATED (1 << 5) +#define ELIFDEF (1 << 6) /* Defines one #-directive, including how to handle it. */ typedef void (*directive_handler) (cpp_reader *); @@ -148,6 +154,8 @@ static void cpp_pop_definition (cpp_reader *, struct def_pragma_macro *); D(undef, T_UNDEF, KANDR, IN_I) \ D(line, T_LINE, KANDR, EXPAND) \ D(elif, T_ELIF, STDC89, COND | EXPAND) \ + D(elifdef, T_ELIFDEF, STDC2X, COND | ELIFDEF) \ + D(elifndef, T_ELIFNDEF, STDC2X, COND | ELIFDEF) \ D(error, T_ERROR, STDC89, 0) \ D(pragma, T_PRAGMA, STDC89, IN_I) \ D(warning, T_WARNING, EXTENSION, 0) \ @@ -437,7 +445,11 @@ _cpp_handle_directive (cpp_reader *pfile, bool indented) if (dname->type == CPP_NAME) { if (dname->val.node.node->is_directive) - dir = &dtable[dname->val.node.node->directive_index]; + { + dir = &dtable[dname->val.node.node->directive_index]; + if ((dir->flags & ELIFDEF) && !CPP_OPTION (pfile, elifdef)) + dir = 0; + } } /* We do not recognize the # followed by a number extension in assembler code. */ @@ -922,12 +934,19 @@ strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) linenum_type reg = 0; uchar c; + bool seen_digit_sep = false; *wrapped = false; while (len--) { c = *str++; + if (!seen_digit_sep && c == '\'' && len) + { + seen_digit_sep = true; + continue; + } if (!ISDIGIT (c)) return true; + seen_digit_sep = false; if (reg > ((linenum_type) -1) / 10) *wrapped = true; reg *= 10; @@ -2072,8 +2091,8 @@ do_else (cpp_reader *pfile) } } -/* Handle a #elif directive by not changing if_stack either. See the - comment above do_else. */ +/* Handle a #elif, #elifdef or #elifndef directive by not changing if_stack + either. See the comment above do_else. */ static void do_elif (cpp_reader *pfile) { @@ -2081,12 +2100,13 @@ do_elif (cpp_reader *pfile) struct if_stack *ifs = buffer->if_stack; if (ifs == NULL) - cpp_error (pfile, CPP_DL_ERROR, "#elif without #if"); + cpp_error (pfile, CPP_DL_ERROR, "#%s without #if", pfile->directive->name); else { if (ifs->type == T_ELSE) { - cpp_error (pfile, CPP_DL_ERROR, "#elif after #else"); + cpp_error (pfile, CPP_DL_ERROR, "#%s after #else", + pfile->directive->name); cpp_error_with_line (pfile, CPP_DL_ERROR, ifs->line, 0, "the conditional began here"); } @@ -2100,8 +2120,29 @@ do_elif (cpp_reader *pfile) pfile->state.skipping = 1; else { - pfile->state.skipping = ! _cpp_parse_expr (pfile, false); - ifs->skip_elses = ! pfile->state.skipping; + if (pfile->directive == &dtable[T_ELIF]) + pfile->state.skipping = !_cpp_parse_expr (pfile, false); + else + { + cpp_hashnode *node = lex_macro_node (pfile, false); + + if (node) + { + bool macro_defined = _cpp_defined_macro_p (node); + if (!_cpp_maybe_notify_macro_use (pfile, node, + pfile->directive_line)) + /* It wasn't a macro after all. */ + macro_defined = false; + bool skip = (pfile->directive == &dtable[T_ELIFDEF] + ? !macro_defined + : macro_defined); + if (pfile->cb.used) + pfile->cb.used (pfile, pfile->directive_line, node); + check_eol (pfile, false); + pfile->state.skipping = skip; + } + } + ifs->skip_elses = !pfile->state.skipping; } /* Invalidate any controlling macro. */ @@ -2109,6 +2150,20 @@ do_elif (cpp_reader *pfile) } } +/* Handle a #elifdef directive. */ +static void +do_elifdef (cpp_reader *pfile) +{ + do_elif (pfile); +} + +/* Handle a #elifndef directive. */ +static void +do_elifndef (cpp_reader *pfile) +{ + do_elif (pfile); +} + /* #endif pops the if stack and resets pfile->state.skipping. */ static void do_endif (cpp_reader *pfile) |