aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/c-c++-common/cpp/va-opt-4.c20
-rw-r--r--libcpp/ChangeLog17
-rw-r--r--libcpp/macro.c61
4 files changed, 85 insertions, 19 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a262bdd..e42751e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-14 Jakub Jelinek <jakub@redhat.com>
+
+ Partially implement P1042R1: __VA_OPT__ wording clarifications
+ PR preprocessor/92319
+ * c-c++-common/cpp/va-opt-4.c: New test.
+
2020-02-13 Jakub Jelinek <jakub@redhat.com>
PR c/93576
diff --git a/gcc/testsuite/c-c++-common/cpp/va-opt-4.c b/gcc/testsuite/c-c++-common/cpp/va-opt-4.c
new file mode 100644
index 0000000..57241bc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/va-opt-4.c
@@ -0,0 +1,20 @@
+/* PR preprocessor/92319 */
+/* { dg-do preprocess } */
+/* { dg-options "-std=gnu99" { target c } } */
+/* { dg-options "-std=c++2a" { target c++ } } */
+
+#define f1(...) b##__VA_OPT__(c)
+#define e
+#define e2 e
+#define e3 1
+#define e5 e3
+t1 f1 (e);
+/* { dg-final { scan-file va-opt-4.i "t1 b;" } } */
+t2 f1 (e2);
+/* { dg-final { scan-file va-opt-4.i "t2 b;" } } */
+t3 f1 (e3);
+/* { dg-final { scan-file va-opt-4.i "t3 bc;" } } */
+t4 f1 (e4);
+/* { dg-final { scan-file va-opt-4.i "t4 bc;" } } */
+t5 f1 (e5);
+/* { dg-final { scan-file va-opt-4.i "t5 bc;" } } */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 65e8f40..307cf3a 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,20 @@
+2020-02-14 Jakub Jelinek <jakub@redhat.com>
+
+ Partially implement P1042R1: __VA_OPT__ wording clarifications
+ PR preprocessor/92319
+ * macro.c (expand_arg): Move declarations before vaopt_state
+ definition.
+ (class vaopt_state): Move enum update_type definition earlier. Remove
+ m_allowed member, add m_arg and m_update members.
+ (vaopt_state::vaopt_state): Change last argument from bool any_args
+ to macro_arg *arg, initialize m_arg and m_update instead of m_allowed.
+ (vaopt_state::update): When bumping m_state from 1 to 2 and m_update
+ is ERROR, determine if __VA_ARGS__ expansion has any non-CPP_PADDING
+ tokens and set m_update to INCLUDE if it has any, DROP otherwise.
+ Return m_update instead of m_allowed ? INCLUDE : DROP in m_state >= 2.
+ (replace_args, create_iso_definition): Adjust last argument to
+ vaopt_state ctor.
+
2020-02-05 Martin Sebor <msebor@redhat.com>
* include/cpplib.h (cpp_builtin_type): Remove trailing comma to
diff --git a/libcpp/macro.c b/libcpp/macro.c
index ec00307..2573f31 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -93,6 +93,8 @@ struct macro_arg_saved_data {
static const char *vaopt_paste_error =
N_("'##' cannot appear at either end of __VA_OPT__");
+static void expand_arg (cpp_reader *, macro_arg *);
+
/* A class for tracking __VA_OPT__ state while iterating over a
sequence of tokens. This is used during both macro definition and
expansion. */
@@ -100,28 +102,29 @@ class vaopt_state {
public:
+ enum update_type
+ {
+ ERROR,
+ DROP,
+ INCLUDE,
+ BEGIN,
+ END
+ };
+
/* Initialize the state tracker. ANY_ARGS is true if variable
arguments were provided to the macro invocation. */
- vaopt_state (cpp_reader *pfile, bool is_variadic, bool any_args)
+ vaopt_state (cpp_reader *pfile, bool is_variadic, macro_arg *arg)
: m_pfile (pfile),
- m_allowed (any_args),
+ m_arg (arg),
m_variadic (is_variadic),
m_last_was_paste (false),
m_state (0),
m_paste_location (0),
- m_location (0)
+ m_location (0),
+ m_update (ERROR)
{
}
- enum update_type
- {
- ERROR,
- DROP,
- INCLUDE,
- BEGIN,
- END
- };
-
/* Given a token, update the state of this tracker and return a
boolean indicating whether the token should be be included in the
expansion. */
@@ -154,6 +157,23 @@ class vaopt_state {
return ERROR;
}
++m_state;
+ if (m_update == ERROR)
+ {
+ if (m_arg == NULL)
+ m_update = INCLUDE;
+ else
+ {
+ m_update = DROP;
+ if (!m_arg->expanded)
+ expand_arg (m_pfile, m_arg);
+ for (unsigned idx = 0; idx < m_arg->expanded_count; ++idx)
+ if (m_arg->expanded[idx]->type != CPP_PADDING)
+ {
+ m_update = INCLUDE;
+ break;
+ }
+ }
+ }
return DROP;
}
else if (m_state >= 2)
@@ -197,7 +217,7 @@ class vaopt_state {
return END;
}
}
- return m_allowed ? INCLUDE : DROP;
+ return m_update;
}
/* Nothing to do with __VA_OPT__. */
@@ -219,8 +239,9 @@ class vaopt_state {
/* The cpp_reader. */
cpp_reader *m_pfile;
- /* True if there were varargs. */
- bool m_allowed;
+ /* The __VA_ARGS__ argument. */
+ macro_arg *m_arg;
+
/* True if the macro is variadic. */
bool m_variadic;
/* If true, the previous token was ##. This is used to detect when
@@ -239,6 +260,10 @@ class vaopt_state {
/* Location of the __VA_OPT__ token. */
location_t m_location;
+
+ /* If __VA_ARGS__ substitutes to no preprocessing tokens,
+ INCLUDE, otherwise DROP. ERROR when unknown yet. */
+ update_type m_update;
};
/* Macro expansion. */
@@ -256,7 +281,6 @@ static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
_cpp_buff **, unsigned *);
static cpp_context *next_context (cpp_reader *);
static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
-static void expand_arg (cpp_reader *, macro_arg *);
static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
static void paste_all_tokens (cpp_reader *, const cpp_token *);
@@ -1924,8 +1948,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
num_macro_tokens);
}
i = 0;
- vaopt_state vaopt_tracker (pfile, macro->variadic,
- args[macro->paramc - 1].count > 0);
+ vaopt_state vaopt_tracker (pfile, macro->variadic, &args[macro->paramc - 1]);
const cpp_token **vaopt_start = NULL;
for (src = macro->exp.tokens; src < limit; src++)
{
@@ -3424,7 +3447,7 @@ create_iso_definition (cpp_reader *pfile)
macro->count = 1;
}
- for (vaopt_state vaopt_tracker (pfile, macro->variadic, true);; token = NULL)
+ for (vaopt_state vaopt_tracker (pfile, macro->variadic, NULL);; token = NULL)
{
if (!token)
{