public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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
> 


      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).