aboutsummaryrefslogtreecommitdiff
path: root/libcpp
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
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')
-rw-r--r--libcpp/ChangeLog16
-rw-r--r--libcpp/directives.c4
-rw-r--r--libcpp/expr.c58
-rw-r--r--libcpp/include/cpplib.h4
-rw-r--r--libcpp/init.c13
-rw-r--r--libcpp/internal.h2
-rw-r--r--libcpp/macro.c56
-rw-r--r--libcpp/pch.c2
-rw-r--r--libcpp/traditional.c20
9 files changed, 82 insertions, 93 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index ea9d602..f749622 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,19 @@
+2020-01-28 Nathan Sidwell <nathan@acm.org>
+
+ 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.
+
2020-01-27 Andrew Burgess <andrew.burgess@embecosm.com>
* configure: Regenerate.
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 10735c8..bbfdfcd 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -596,9 +596,7 @@ lex_macro_node (cpp_reader *pfile, bool is_def_or_undef)
cpp_hashnode *node = token->val.node.node;
if (is_def_or_undef
- && (node == pfile->spec_nodes.n_defined
- || node == pfile->spec_nodes.n__has_include
- || node == pfile->spec_nodes.n__has_include_next))
+ && node == pfile->spec_nodes.n_defined)
cpp_error (pfile, CPP_DL_ERROR,
"\"%s\" cannot be used as a macro name",
NODE_NAME (node));
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 6c56803..2ae9be0 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -64,8 +64,6 @@ static unsigned int interpret_float_suffix (cpp_reader *, const uchar *, size_t)
static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t);
static void check_promotion (cpp_reader *, const struct op *);
-static cpp_num parse_has_include (cpp_reader *, cpp_hashnode *, include_type);
-
/* Token type abuse to create unary plus and minus operators. */
#define CPP_UPLUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1))
#define CPP_UMINUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 2))
@@ -1159,10 +1157,6 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
case CPP_NAME:
if (token->val.node.node == pfile->spec_nodes.n_defined)
return parse_defined (pfile);
- else if (token->val.node.node == pfile->spec_nodes.n__has_include)
- return parse_has_include (pfile, token->val.node.node, IT_INCLUDE);
- else if (token->val.node.node == pfile->spec_nodes.n__has_include_next)
- return parse_has_include (pfile, token->val.node.node, IT_INCLUDE_NEXT);
else if (CPP_OPTION (pfile, cplusplus)
&& (token->val.node.node == pfile->spec_nodes.n_true
|| token->val.node.node == pfile->spec_nodes.n_false))
@@ -2189,55 +2183,3 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
return lhs;
}
-/* Handle meeting "__has_include" in a preprocessor expression. */
-static cpp_num
-parse_has_include (cpp_reader *pfile, cpp_hashnode *op, include_type type)
-{
- cpp_num result;
-
- result.unsignedp = false;
- result.high = 0;
- result.overflow = false;
- result.low = 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, type))
- result.low = 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;
-}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 56cbbd8..07caadb 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -860,7 +860,9 @@ enum cpp_builtin_type
BT_TIMESTAMP, /* `__TIMESTAMP__' */
BT_COUNTER, /* `__COUNTER__' */
BT_HAS_ATTRIBUTE, /* `__has_attribute(x)' */
- BT_HAS_BUILTIN /* `__has_builtin(x)' */
+ BT_HAS_BUILTIN, /* `__has_builtin(x)' */
+ BT_HAS_INCLUDE, /* `__has_include(x)' */
+ BT_HAS_INCLUDE_NEXT, /* `__has_include_next(x)' */
};
#define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE))
diff --git a/libcpp/init.c b/libcpp/init.c
index e798140..a3cd8e2 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -404,6 +404,8 @@ static const struct builtin_macro builtin_array[] =
B("__has_attribute", BT_HAS_ATTRIBUTE, true),
B("__has_cpp_attribute", BT_HAS_ATTRIBUTE, true),
B("__has_builtin", BT_HAS_BUILTIN, true),
+ B("__has_include", BT_HAS_INCLUDE, true),
+ B("__has_include_next",BT_HAS_INCLUDE_NEXT, true),
/* Keep builtins not used for -traditional-cpp at the end, and
update init_builtins() if any more are added. */
B("_Pragma", BT_PRAGMA, true),
@@ -578,17 +580,6 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
if (CPP_OPTION (pfile, objc))
_cpp_define_builtin (pfile, "__OBJC__ 1");
-
- /* These two behave as macros for #ifdef, but are evaluated
- specially inside #if. */
- _cpp_define_builtin (pfile, "__has_include __has_include");
- _cpp_define_builtin (pfile, "__has_include_next __has_include_next");
- pfile->spec_nodes.n__has_include
- = cpp_lookup (pfile, DSC("__has_include"));
- pfile->spec_nodes.n__has_include->flags |= NODE_DIAGNOSTIC;
- pfile->spec_nodes.n__has_include_next
- = cpp_lookup (pfile, DSC("__has_include_next"));
- pfile->spec_nodes.n__has_include_next->flags |= NODE_DIAGNOSTIC;
}
/* Sanity-checks are dependent on command-line options, so it is
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 5453c3b..97d9bdb 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -290,8 +290,6 @@ struct spec_nodes
cpp_hashnode *n_false; /* C++ keyword false */
cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
cpp_hashnode *n__VA_OPT__; /* C++ vararg macros */
- cpp_hashnode *n__has_include; /* __has_include operator */
- cpp_hashnode *n__has_include_next; /* __has_include_next operator */
};
typedef struct _cpp_line_note _cpp_line_note;
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)
diff --git a/libcpp/pch.c b/libcpp/pch.c
index e631050..fcdf387 100644
--- a/libcpp/pch.c
+++ b/libcpp/pch.c
@@ -811,8 +811,6 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
s->n_false = cpp_lookup (r, DSC("false"));
s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__"));
s->n__VA_OPT__ = cpp_lookup (r, DSC("__VA_OPT__"));
- s->n__has_include = cpp_lookup (r, DSC("__has_include"));
- s->n__has_include_next = cpp_lookup (r, DSC("__has_include_next"));
}
old_state = r->state;
diff --git a/libcpp/traditional.c b/libcpp/traditional.c
index ff06d31..039fcfe 100644
--- a/libcpp/traditional.c
+++ b/libcpp/traditional.c
@@ -77,9 +77,8 @@ enum ls {ls_none = 0, /* Normal state. */
ls_defined_close, /* Looking for ')' of defined(). */
ls_hash, /* After # in preprocessor conditional. */
ls_predicate, /* After the predicate, maybe paren? */
- ls_answer, /* In answer to predicate. */
- ls_has_include, /* After __has_include. */
- ls_has_include_close}; /* Looking for ')' of __has_include. */
+ ls_answer /* In answer to predicate. */
+};
/* Lexing TODO: Maybe handle space in escaped newlines. Stop lex.c
from recognizing comments and directives during its lexing pass. */
@@ -564,13 +563,6 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro,
lex_state = ls_defined;
continue;
}
- else if (pfile->state.in_expression
- && (node == pfile->spec_nodes.n__has_include
- || node == pfile->spec_nodes.n__has_include_next))
- {
- lex_state = ls_has_include;
- continue;
- }
}
break;
@@ -594,8 +586,6 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro,
lex_state = ls_answer;
else if (lex_state == ls_defined)
lex_state = ls_defined_close;
- else if (lex_state == ls_has_include)
- lex_state = ls_has_include_close;
}
break;
@@ -729,8 +719,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro,
goto new_context;
}
}
- else if (lex_state == ls_answer || lex_state == ls_defined_close
- || lex_state == ls_has_include_close)
+ else if (lex_state == ls_answer || lex_state == ls_defined_close)
lex_state = ls_none;
}
break;
@@ -811,8 +800,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro,
lex_state = ls_none;
else if (lex_state == ls_hash
|| lex_state == ls_predicate
- || lex_state == ls_defined
- || lex_state == ls_has_include)
+ || lex_state == ls_defined)
lex_state = ls_none;
/* ls_answer and ls_defined_close keep going until ')'. */