aboutsummaryrefslogtreecommitdiff
path: root/libcpp/macro.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-01-28 07:58:29 -0800
committerNathan Sidwell <nathan@acm.org>2020-01-28 08:02:17 -0800
commit3d056cbfb3484f4037b34c908b26e1c6776c86b5 (patch)
tree591410d4cd98b8777276072cc5af998a3f97d97c /libcpp/macro.c
parenta5d81aaab6d54379cd3835b33d84d9be5c5be099 (diff)
downloadgcc-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.c56
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)