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