mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 10:20:29 +08:00
c++: Partially implement P1042R1: __VA_OPT__ wording clarifications [PR92319]
I've noticed we claim in cxx-status.html that we implement P1042R1, but it seems we don't implement any of the changes from there. The following patch implements just the change that __VA_OPT__ determines whether to expand to nothing or the enclosed tokens no longer based on whether there were any tokens passed to __VA_ARGS__, but whether __VA_ARGS__ expands to any tokens (from testing apparently it has to be non-CPP_PADDING tokens). I'm afraid I'm completely lost about the padding preservation/removal changes that are also in the paper, so haven't touched that part. 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. * c-c++-common/cpp/va-opt-4.c: New test.
This commit is contained in:
parent
c595ad44fa
commit
e235031d49
@ -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
|
||||
|
20
gcc/testsuite/c-c++-common/cpp/va-opt-4.c
Normal file
20
gcc/testsuite/c-c++-common/cpp/va-opt-4.c
Normal file
@ -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;" } } */
|
@ -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
|
||||
|
@ -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,19 +102,6 @@ class vaopt_state {
|
||||
|
||||
public:
|
||||
|
||||
/* 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)
|
||||
: m_pfile (pfile),
|
||||
m_allowed (any_args),
|
||||
m_variadic (is_variadic),
|
||||
m_last_was_paste (false),
|
||||
m_state (0),
|
||||
m_paste_location (0),
|
||||
m_location (0)
|
||||
{
|
||||
}
|
||||
|
||||
enum update_type
|
||||
{
|
||||
ERROR,
|
||||
@ -122,6 +111,20 @@ class vaopt_state {
|
||||
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, macro_arg *arg)
|
||||
: m_pfile (pfile),
|
||||
m_arg (arg),
|
||||
m_variadic (is_variadic),
|
||||
m_last_was_paste (false),
|
||||
m_state (0),
|
||||
m_paste_location (0),
|
||||
m_location (0),
|
||||
m_update (ERROR)
|
||||
{
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user