From: Jason Merrill <jason@redhat.com>
To: Jakub Jelinek <jakub@redhat.com>, Joseph Myers <joseph@codesourcery.com>
Cc: Marek Polacek <polacek@redhat.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH, v2] c++: Implement C++23 P2334R1 - #elifdef/#elifndef
Date: Tue, 5 Oct 2021 23:02:32 -0400 [thread overview]
Message-ID: <67da478b-2029-9487-5117-38a4afe6e3a2@redhat.com> (raw)
In-Reply-To: <20211005202452.GZ304296@tucnak>
On 10/5/21 16:24, Jakub Jelinek wrote:
> On Tue, Oct 05, 2021 at 05:23:26PM +0000, Joseph Myers wrote:
>>> One is in the patch below, ignores that sentence and only implements it
>>> for -std=c++23/-std=gnu++23 like it is only implemented for -std=c23.
>>> Another option would be to implement it also in the older GNU modes but
>>> not in the C/CXX modes (but it would be strange if we did that just for
>>> C++ and not for C).
>>> Yet another option is to enable it unconditionally.
>>> And yet another option would be to enable it unconditionally but emit
>>> a warning (or pedwarn) when it is seen.
>>> Note, when it is enabled for the older language modes, as Joseph wrote
>>> in the c11-elifdef-1.c testcase, it can result e.g. in rejecting previously
>>> valid code:
>>
>> It would probably be reasonable to enable it in older GNU modes for C as
>> well as C++ if desired (and, in that case, emit a pedwarn-if-pedantic when
>> it's acted on) - cases where it affects compatibility should be rare.
>> Enabling with a pedwarn in strict modes is problematic because it changes
>> semantics of valid code where it was inside #if 0, however. It doesn't
>> make sense at all to me to think of a new feature like this (one with no
>> prior art in C mentioned in the WG14 proposal) as a defect fix.
>>
>> Any normal directive - i.e. one that has no effect on the preprocessor #if
>> structure and so is ignored inside #if 0 for all language versions - can
>> more reasonably be enabled for all language versions with a pedwarn when
>> used for old versions. (In particular, that will be appropriate for
>> #warning, where the "don't pedwarn in C2X modes" part needs implementing
>> after N2686 was accepted at the August / September WG14 meeting - I don't
>> know if C++ is doing anything with #warning.)
>
> Ok, here is an updated version which accepts them in both
> CPP_OPTION (pfile, elifdef) (aka -std={gnu,c}{2x,++2b,++23} modes) or
> !CPP_OPTION (pfile, std) (aka -std=gnu* modes), but for the latter
> pedwarns if pedantic (but only if the directive actually changes the
> preprocessing behavior or if it would be rejected with corresponding
> -std=c*).
> The second hunk in directives.c is for the cases where it would otherwise
> error about unknown directive, the third hunk is for the case where it
> changes the skipping state. If pfile->state.skipping is true before
> encountering the directive and after it as well, then whether the directive
> is there or not makes no difference.
LGTM.
> 2021-10-05 Jakub Jelinek <jakub@redhat.com>
>
> libcpp/
> * init.c (lang_defaults): Implement P2334R1, enable elifdef for
> -std=c++23 and -std=gnu++23.
> * directives.c (_cpp_handle_directive): Support elifdef/elifndef if
> either CPP_OPTION (pfile, elifdef) or !CPP_OPTION (pfile, std).
> (do_elif): For older non-std modes if pedantic pedwarn about
> #elifdef/#elifndef directives that change behavior.
> gcc/testsuite/
> * gcc.dg/cpp/gnu11-elifdef-1.c: New test.
> * gcc.dg/cpp/gnu11-elifdef-2.c: New test.
> * gcc.dg/cpp/gnu11-elifdef-3.c: New test.
> * gcc.dg/cpp/gnu11-elifdef-4.c: New test.
> * g++.dg/cpp/elifdef-1.C: New test.
> * g++.dg/cpp/elifdef-2.C: New test.
> * g++.dg/cpp/elifdef-3.C: New test.
> * g++.dg/cpp/elifdef-4.C: New test.
> * g++.dg/cpp/elifdef-5.C: New test.
> * g++.dg/cpp/elifdef-6.C: New test.
> * g++.dg/cpp/elifdef-7.C: New test.
>
> --- libcpp/init.c.jj 2021-09-02 10:01:15.954715595 +0200
> +++ libcpp/init.c 2021-10-05 09:55:15.010620700 +0200
> @@ -122,8 +122,8 @@ static const struct lang_flags lang_defa
> /* CXX17 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0 },
> /* GNUCXX20 */ { 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
> /* CXX20 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
> - /* GNUCXX23 */ { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
> - /* CXX23 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
> + /* GNUCXX23 */ { 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1 },
> + /* CXX23 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1 },
> /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
> };
>
> --- libcpp/directives.c.jj 2021-05-12 09:44:55.080621650 +0200
> +++ libcpp/directives.c 2021-10-05 22:05:52.303984796 +0200
> @@ -447,7 +447,11 @@ _cpp_handle_directive (cpp_reader *pfile
> if (dname->val.node.node->is_directive)
> {
> dir = &dtable[dname->val.node.node->directive_index];
> - if ((dir->flags & ELIFDEF) && !CPP_OPTION (pfile, elifdef))
> + if ((dir->flags & ELIFDEF)
> + && !CPP_OPTION (pfile, elifdef)
> + /* For -std=gnu* modes elifdef is supported with
> + a pedwarn if pedantic. */
> + && CPP_OPTION (pfile, std))
> dir = 0;
> }
> }
> @@ -2117,7 +2121,26 @@ do_elif (cpp_reader *pfile)
> are skipped and their controlling directives are processed as
> if they were in a group that is skipped." */
> if (ifs->skip_elses)
> - pfile->state.skipping = 1;
> + {
> + /* In older GNU standards, #elifdef/#elifndef is supported
> + as an extension, but pedwarn if -pedantic if the presence
> + of the directive would be rejected. */
> + if (pfile->directive != &dtable[T_ELIF]
> + && ! CPP_OPTION (pfile, elifdef)
> + && CPP_PEDANTIC (pfile)
> + && !pfile->state.skipping)
> + {
> + if (CPP_OPTION (pfile, cplusplus))
> + cpp_error (pfile, CPP_DL_PEDWARN,
> + "#%s before C++23 is a GCC extension",
> + pfile->directive->name);
> + else
> + cpp_error (pfile, CPP_DL_PEDWARN,
> + "#%s before C2X is a GCC extension",
> + pfile->directive->name);
> + }
> + pfile->state.skipping = 1;
> + }
> else
> {
> if (pfile->directive == &dtable[T_ELIF])
> @@ -2139,6 +2162,22 @@ do_elif (cpp_reader *pfile)
> if (pfile->cb.used)
> pfile->cb.used (pfile, pfile->directive_line, node);
> check_eol (pfile, false);
> + /* In older GNU standards, #elifdef/#elifndef is supported
> + as an extension, but pedwarn if -pedantic if the presence
> + of the directive would change behavior. */
> + if (! CPP_OPTION (pfile, elifdef)
> + && CPP_PEDANTIC (pfile)
> + && pfile->state.skipping != skip)
> + {
> + if (CPP_OPTION (pfile, cplusplus))
> + cpp_error (pfile, CPP_DL_PEDWARN,
> + "#%s before C++23 is a GCC extension",
> + pfile->directive->name);
> + else
> + cpp_error (pfile, CPP_DL_PEDWARN,
> + "#%s before C2X is a GCC extension",
> + pfile->directive->name);
> + }
> pfile->state.skipping = skip;
> }
> }
> --- gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c.jj 2021-10-05 21:18:52.451803413 +0200
> +++ gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-1.c 2021-10-05 21:20:26.883511595 +0200
> @@ -0,0 +1,5 @@
> +/* Test #elifdef and #elifndef in GNU11. */
> +/* { dg-do preprocess } */
> +/* { dg-options "-std=gnu11" } */
> +
> +#include "c2x-elifdef-1.c"
> --- gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c.jj 2021-10-05 21:19:49.714020075 +0200
> +++ gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-2.c 2021-10-05 21:21:14.554859458 +0200
> @@ -0,0 +1,63 @@
> +/* Test #elifdef and #elifndef in GNU11: erroneous usages. */
> +/* { dg-do preprocess } */
> +/* { dg-options "-std=gnu11" } */
> +
> +#define A
> +#undef B
> +
> +#elifdef A /* { dg-error "#elifdef without #if" } */
> +#elifdef B /* { dg-error "#elifdef without #if" } */
> +#elifndef A /* { dg-error "#elifndef without #if" } */
> +#elifndef B /* { dg-error "#elifndef without #if" } */
> +
> +#if 1 /* { dg-error "-:began here" } */
> +#else
> +#elifdef A /* { dg-error "#elifdef after #else" } */
> +#endif
> +
> +#if 1 /* { dg-error "-:began here" } */
> +#else
> +#elifdef B /* { dg-error "#elifdef after #else" } */
> +#endif
> +
> +#if 1 /* { dg-error "-:began here" } */
> +#else
> +#elifndef A /* { dg-error "#elifndef after #else" } */
> +#endif
> +
> +#if 1 /* { dg-error "-:began here" } */
> +#else
> +#elifndef B /* { dg-error "#elifndef after #else" } */
> +#endif
> +
> +#if 0
> +#elifdef A = /* { dg-warning "extra tokens at end of #elifdef directive" } */
> +#endif
> +
> +#if 0
> +#elifdef B = /* { dg-warning "extra tokens at end of #elifdef directive" } */
> +#endif
> +
> +#if 0
> +#elifndef A = /* { dg-warning "extra tokens at end of #elifndef directive" } */
> +#endif
> +
> +#if 0
> +#elifndef B = /* { dg-warning "extra tokens at end of #elifndef directive" } */
> +#endif
> +
> +#if 0
> +#elifdef /* { dg-error "no macro name given in #elifdef directive" } */
> +#endif
> +
> +#if 0
> +#elifndef /* { dg-error "no macro name given in #elifndef directive" } */
> +#endif
> +
> +#if 0
> +#elifdef , /* { dg-error "macro names must be identifiers" } */
> +#endif
> +
> +#if 0
> +#elifndef , /* { dg-error "macro names must be identifiers" } */
> +#endif
> --- gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c.jj 2021-10-05 21:22:42.682650532 +0200
> +++ gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-3.c 2021-10-05 22:15:51.698718704 +0200
> @@ -0,0 +1,65 @@
> +/* Test #elifdef and #elifndef in GNU11. */
> +/* { dg-do preprocess } */
> +/* { dg-options "-std=gnu11 -pedantic" } */
> +
> +#define A
> +#undef B
> +
> +#if 0
> +#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
> +#define M1 1
> +#endif
> +
> +#if M1 != 1
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifdef B
> +#error "#elifdef B applied"
> +#endif
> +
> +#if 0
> +#elifndef A
> +#error "#elifndef A applied"
> +#endif
> +
> +#if 0
> +#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
> +#define M2 2
> +#endif
> +
> +#if M2 != 2
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 0
> +#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
> +#else
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
> +#else
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 1
> +#elifdef A /* { dg-warning "#elifdef before C2X is a GCC extension" } */
> +#endif
> +
> +#if 1
> +#elifndef B /* { dg-warning "#elifndef before C2X is a GCC extension" } */
> +#endif
> +
> +/* As with #elif, the syntax of the new directives is relaxed after a
> + non-skipped group. */
> +
> +#if 1
> +#elifdef x * y /* { dg-warning "#elifdef before C2X is a GCC extension" } */
> +#endif
> +
> +#if 1
> +#elifndef ! /* { dg-warning "#elifndef before C2X is a GCC extension" } */
> +#endif
> --- gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c.jj 2021-10-05 21:26:35.671449109 +0200
> +++ gcc/testsuite/gcc.dg/cpp/gnu11-elifdef-4.c 2021-10-05 22:16:23.762276538 +0200
> @@ -0,0 +1,65 @@
> +/* Test #elifdef and #elifndef in GNU11. */
> +/* { dg-do preprocess } */
> +/* { dg-options "-std=gnu11 -pedantic-errors" } */
> +
> +#define A
> +#undef B
> +
> +#if 0
> +#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
> +#define M1 1
> +#endif
> +
> +#if M1 != 1
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifdef B
> +#error "#elifdef B applied"
> +#endif
> +
> +#if 0
> +#elifndef A
> +#error "#elifndef A applied"
> +#endif
> +
> +#if 0
> +#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
> +#define M2 2
> +#endif
> +
> +#if M2 != 2
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 0
> +#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
> +#else
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
> +#else
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 1
> +#elifdef A /* { dg-error "#elifdef before C2X is a GCC extension" } */
> +#endif
> +
> +#if 1
> +#elifndef B /* { dg-error "#elifndef before C2X is a GCC extension" } */
> +#endif
> +
> +/* As with #elif, the syntax of the new directives is relaxed after a
> + non-skipped group. */
> +
> +#if 1
> +#elifdef x * y /* { dg-error "#elifdef before C2X is a GCC extension" } */
> +#endif
> +
> +#if 1
> +#elifndef ! /* { dg-error "#elifndef before C2X is a GCC extension" } */
> +#endif
> --- gcc/testsuite/g++.dg/cpp/elifdef-1.C.jj 2021-10-05 10:00:41.410057024 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-1.C 2021-10-05 10:00:33.110173069 +0200
> @@ -0,0 +1,3 @@
> +// { dg-do preprocess { target { ! c++23 } } }
> +
> +#include "../../gcc.dg/cpp/c11-elifdef-1.c"
> --- gcc/testsuite/g++.dg/cpp/elifdef-2.C.jj 2021-10-05 10:01:30.345372808 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-2.C 2021-10-05 10:03:36.560608083 +0200
> @@ -0,0 +1,4 @@
> +// P2334R1
> +// { dg-do preprocess { target c++23 } }
> +
> +#include "../../gcc.dg/cpp/c2x-elifdef-1.c"
> --- gcc/testsuite/g++.dg/cpp/elifdef-3.C.jj 2021-10-05 10:01:36.029293338 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-3.C 2021-10-05 21:27:52.627391684 +0200
> @@ -0,0 +1,62 @@
> +// P2334R1
> +// { dg-do preprocess { target c++23 } }
> +
> +#define A
> +#undef B
> +
> +#elifdef A // { dg-error "#elifdef without #if" }
> +#elifdef B // { dg-error "#elifdef without #if" }
> +#elifndef A // { dg-error "#elifndef without #if" }
> +#elifndef B // { dg-error "#elifndef without #if" }
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifdef A // { dg-error "#elifdef after #else" }
> +#endif
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifdef B // { dg-error "#elifdef after #else" }
> +#endif
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifndef A // { dg-error "#elifndef after #else" }
> +#endif
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifndef B // { dg-error "#elifndef after #else" }
> +#endif
> +
> +#if 0
> +#elifdef A = // { dg-error "extra tokens at end of #elifdef directive" }
> +#endif
> +
> +#if 0
> +#elifdef B = // { dg-error "extra tokens at end of #elifdef directive" }
> +#endif
> +
> +#if 0
> +#elifndef A = // { dg-error "extra tokens at end of #elifndef directive" }
> +#endif
> +
> +#if 0
> +#elifndef B = // { dg-error "extra tokens at end of #elifndef directive" }
> +#endif
> +
> +#if 0
> +#elifdef // { dg-error "no macro name given in #elifdef directive" }
> +#endif
> +
> +#if 0
> +#elifndef // { dg-error "no macro name given in #elifndef directive" }
> +#endif
> +
> +#if 0
> +#elifdef , // { dg-error "macro names must be identifiers" }
> +#endif
> +
> +#if 0
> +#elifndef , // { dg-error "macro names must be identifiers" }
> +#endif
> --- gcc/testsuite/g++.dg/cpp/elifdef-4.C.jj 2021-10-05 21:11:19.112005054 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-4.C 2021-10-05 21:11:39.873721037 +0200
> @@ -0,0 +1,5 @@
> +// P2334R1
> +// { dg-do preprocess }
> +// { dg-options "" }
> +
> +#include "../../gcc.dg/cpp/c2x-elifdef-1.c"
> --- gcc/testsuite/g++.dg/cpp/elifdef-5.C.jj 2021-10-05 21:11:54.602519548 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-5.C 2021-10-05 21:28:13.093110471 +0200
> @@ -0,0 +1,63 @@
> +// P2334R1
> +// { dg-do preprocess }
> +// { dg-options "" }
> +
> +#define A
> +#undef B
> +
> +#elifdef A // { dg-error "#elifdef without #if" }
> +#elifdef B // { dg-error "#elifdef without #if" }
> +#elifndef A // { dg-error "#elifndef without #if" }
> +#elifndef B // { dg-error "#elifndef without #if" }
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifdef A // { dg-error "#elifdef after #else" }
> +#endif
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifdef B // { dg-error "#elifdef after #else" }
> +#endif
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifndef A // { dg-error "#elifndef after #else" }
> +#endif
> +
> +#if 1 // { dg-error "-:began here" }
> +#else
> +#elifndef B // { dg-error "#elifndef after #else" }
> +#endif
> +
> +#if 0
> +#elifdef A = // { dg-warning "extra tokens at end of #elifdef directive" }
> +#endif
> +
> +#if 0
> +#elifdef B = // { dg-warning "extra tokens at end of #elifdef directive" }
> +#endif
> +
> +#if 0
> +#elifndef A = // { dg-warning "extra tokens at end of #elifndef directive" }
> +#endif
> +
> +#if 0
> +#elifndef B = // { dg-warning "extra tokens at end of #elifndef directive" }
> +#endif
> +
> +#if 0
> +#elifdef // { dg-error "no macro name given in #elifdef directive" }
> +#endif
> +
> +#if 0
> +#elifndef // { dg-error "no macro name given in #elifndef directive" }
> +#endif
> +
> +#if 0
> +#elifdef , // { dg-error "macro names must be identifiers" }
> +#endif
> +
> +#if 0
> +#elifndef , // { dg-error "macro names must be identifiers" }
> +#endif
> --- gcc/testsuite/g++.dg/cpp/elifdef-6.C.jj 2021-10-05 21:27:05.784035343 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-6.C 2021-10-05 22:17:09.120651040 +0200
> @@ -0,0 +1,65 @@
> +// P2334R1
> +// { dg-do preprocess }
> +// { dg-options "-pedantic" }
> +
> +#define A
> +#undef B
> +
> +#if 0
> +#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#define M1 1
> +#endif
> +
> +#if M1 != 1
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifdef B
> +#error "#elifdef B applied"
> +#endif
> +
> +#if 0
> +#elifndef A
> +#error "#elifndef A applied"
> +#endif
> +
> +#if 0
> +#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#define M2 2
> +#endif
> +
> +#if M2 != 2
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 0
> +#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#else
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#else
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 1
> +#elifdef A // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> +
> +#if 1
> +#elifndef B // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> +
> +// As with #elif, the syntax of the new directives is relaxed after a
> + non-skipped group.
> +
> +#if 1
> +#elifdef x * y // { dg-warning "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> +
> +#if 1
> +#elifndef ! // { dg-warning "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> --- gcc/testsuite/g++.dg/cpp/elifdef-7.C.jj 2021-10-05 21:29:18.132216791 +0200
> +++ gcc/testsuite/g++.dg/cpp/elifdef-7.C 2021-10-05 22:17:45.439150203 +0200
> @@ -0,0 +1,65 @@
> +// P2334R1
> +// { dg-do preprocess }
> +// { dg-options "-pedantic-errors" }
> +
> +#define A
> +#undef B
> +
> +#if 0
> +#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#define M1 1
> +#endif
> +
> +#if M1 != 1
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifdef B
> +#error "#elifdef B applied"
> +#endif
> +
> +#if 0
> +#elifndef A
> +#error "#elifndef A applied"
> +#endif
> +
> +#if 0
> +#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#define M2 2
> +#endif
> +
> +#if M2 != 2
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 0
> +#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#else
> +#error "#elifdef A did not apply"
> +#endif
> +
> +#if 0
> +#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#else
> +#error "#elifndef B did not apply"
> +#endif
> +
> +#if 1
> +#elifdef A // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> +
> +#if 1
> +#elifndef B // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> +
> +// As with #elif, the syntax of the new directives is relaxed after a
> + non-skipped group.
> +
> +#if 1
> +#elifdef x * y // { dg-error "#elifdef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
> +
> +#if 1
> +#elifndef ! // { dg-error "#elifndef before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } }
> +#endif
>
>
> Jakub
>
prev parent reply other threads:[~2021-10-06 3:02 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-05 8:35 [PATCH] " Jakub Jelinek
2021-10-05 15:24 ` Marek Polacek
2021-10-05 17:23 ` Joseph Myers
2021-10-05 20:24 ` [PATCH, v2] " Jakub Jelinek
2021-10-06 3:02 ` Jason Merrill [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=67da478b-2029-9487-5117-38a4afe6e3a2@redhat.com \
--to=jason@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=joseph@codesourcery.com \
--cc=polacek@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).