diff options
author | Nathan Sidwell <nathan@acm.org> | 2020-01-28 07:58:29 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2020-01-28 08:02:17 -0800 |
commit | 3d056cbfb3484f4037b34c908b26e1c6776c86b5 (patch) | |
tree | 591410d4cd98b8777276072cc5af998a3f97d97c /libcpp/macro.c | |
parent | a5d81aaab6d54379cd3835b33d84d9be5c5be099 (diff) | |
download | gcc-3d056cbfb3484f4037b34c908b26e1c6776c86b5.zip gcc-3d056cbfb3484f4037b34c908b26e1c6776c86b5.tar.gz gcc-3d056cbfb3484f4037b34c908b26e1c6776c86b5.tar.bz2 |
preprocessor: Make __has_include a builtin macro [PR93452]
The clever hack of '#define __has_include __has_include' breaks -dD
and -fdirectives-only, because that emits definitions. This turns
__has_include into a proper builtin macro. Thus it's never emitted
via -dD, and because use outside of directive processing is undefined,
we can just expand it anywhere.
PR preprocessor/93452
* internal.h (struct spec_nodes): Drop n__has_include{,_next}.
* directives.c (lex_macro_node): Don't check __has_include redef.
* expr.c (eval_token): Drop __has_include eval.
(parse_has_include): Move to ...
* macro.c (builtin_has_include): ... here.
(_cpp_builtin_macro_text): Eval __has_include{,_next}.
* include/cpplib.h (enum cpp_builtin_type): Add BT_HAS_INCLUDE{,_NEXT}.
* init.c (builtin_array): Add them.
(cpp_init_builtins): Drop __has_include{,_next} init here ...
* pch.c (cpp_read_state): ... and here.
* traditional.c (enum ls): Drop has_include states ...
(_cpp_scan_out_logical_line): ... and here.
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r-- | libcpp/macro.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/libcpp/macro.c b/libcpp/macro.c index dbd7a28..ec3f8b7 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -336,6 +336,56 @@ unsigned num_expanded_macros_counter = 0; from macro expansion. */ unsigned num_macro_tokens_counter = 0; +/* Handle meeting "__has_include" builtin macro. */ + +static int +builtin_has_include (cpp_reader *pfile, cpp_hashnode *op, bool has_next) +{ + int result = 0; + + pfile->state.angled_headers = true; + const cpp_token *token = cpp_get_token (pfile); + bool paren = token->type == CPP_OPEN_PAREN; + if (paren) + token = cpp_get_token (pfile); + else + cpp_error (pfile, CPP_DL_ERROR, + "missing '(' before \"%s\" operand", NODE_NAME (op)); + pfile->state.angled_headers = false; + + bool bracket = token->type != CPP_STRING; + char *fname = NULL; + if (token->type == CPP_STRING || token->type == CPP_HEADER_NAME) + { + fname = XNEWVEC (char, token->val.str.len - 1); + memcpy (fname, token->val.str.text + 1, token->val.str.len - 2); + fname[token->val.str.len - 2] = '\0'; + } + else if (token->type == CPP_LESS) + fname = _cpp_bracket_include (pfile); + else + cpp_error (pfile, CPP_DL_ERROR, + "operator \"%s\" requires a header-name", NODE_NAME (op)); + + if (fname) + { + /* Do not do the lookup if we're skipping, that's unnecessary + IO. */ + if (!pfile->state.skip_eval + && _cpp_has_header (pfile, fname, bracket, + has_next ? IT_INCLUDE_NEXT : IT_INCLUDE)) + result = 1; + + XDELETEVEC (fname); + } + + if (paren && !SEEN_EOL () && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN) + cpp_error (pfile, CPP_DL_ERROR, + "missing ')' after \"%s\" operand", NODE_NAME (op)); + + return result; +} + /* Emits a warning if NODE is a macro defined in the main file that has not been used. */ int @@ -572,6 +622,12 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, case BT_HAS_BUILTIN: number = pfile->cb.has_builtin (pfile); break; + + case BT_HAS_INCLUDE: + case BT_HAS_INCLUDE_NEXT: + number = builtin_has_include (pfile, node, + node->value.builtin == BT_HAS_INCLUDE_NEXT); + break; } if (result == NULL) |