]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++, c: Introduce -Wkeyword-macro warning/pedwarn - part of C++26 P2843R3 [PR120778]
authorJakub Jelinek <jakub@redhat.com>
Thu, 7 Aug 2025 06:47:44 +0000 (08:47 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 7 Aug 2025 06:47:44 +0000 (08:47 +0200)
The following patch introduces a -Wkeyword-macro warning that clang has
since 2014 to implement part of C++26 P2843R3 Preprocessing is never undefined
paper.
The relevant change in the paper is moving [macro.names]/2 paragraph to
https://eel.is/c++draft/cpp.replace.general#9 :
"A translation unit shall not #define or #undef names lexically identical to
keywords, to the identifiers listed in Table 4, or to the attribute-tokens
described in [dcl.attr], except that the names likely and unlikely may be
defined as function-like macros."

Now, my understanding of the paper is that in [macro.names] and surrounding
sections the word shall bears different meaning from [cpp.replace.general],
where only the latter location implies ill-formed, diagnostic required.

The warning in clang when introduced diagnosed all #define/#undef directives
on keywords, but shortly after introduction has been changed not to
diagnose #undef at all (with "#undef a keyword is generally harmless but used
often in configuration scripts" message) and later on even the #define
part tweaked - not warn about say
  #define inline
(or const, extern, static), or
  #define keyword keyword
or
  #define keyword __keyword
or
  #define keyword __keyword__
Later on the warning has been moved to be only pedantic diagnostic unless
requested by users.  Clearly some code in the wild does e.g.
  #define private public
and similar games, or e.g. Linux kernel (sure, C) does
  #define inline __inline__ __attribute__((__always_inline__))
etc.
Now, I believe at least with the current C++26 wording such exceptions
aren't allowed (unless it is changed to IFNDR).  But given that this is just
pedantic stuff, the following patch makes the warning off by default for
C and C++ before C++26 and even for C++26 it enables it by default only
if -pedantic/-pedantic-errors (in that case it pedwarns, otherwise it
warns).  And it diagnoses both #define and #undef without exceptions.

From what I can see, all the current NODE_WARN cases are macros starting
with __ with one exception (_Pragma).  As the NODE_* flags seem to be a
limited resource, I chose to just use NODE_WARN as well and differentiate
on the node names (if they don't start with __ or _P, they are considered
to be -Wkeyword-macro registered ones, otherwise old NODE_WARN cases,
typically builtin macros or __STDC* macros).

2025-08-07  Jakub Jelinek  <jakub@redhat.com>

PR preprocessor/120778
gcc/
* doc/invoke.texi (Wkeyword-macro): Document.
gcc/c-family/
* c.opt (Wkeyword-macro): New option.
* c.opt.urls: Regenerate.
* c-common.h (cxx_dialect): Comment formatting fix.
* c-opts.cc (c_common_post_options): Default to
-Wkeyword-macro for C++26 if pedantic.
gcc/c/
* c-decl.cc (c_init_decl_processing): Mark cpp nodes corresponding
to keywords as NODE_WARN if warn_keyword_macro.
gcc/cp/
* lex.cc (cxx_init): Mark cpp nodes corresponding
to keywords, identifiers with special meaning and standard
attribute identifiers as NODE_WARN if warn_keyword_macro.
gcc/testsuite/
* gcc.dg/Wkeyword-macro-1.c: New test.
* gcc.dg/Wkeyword-macro-2.c: New test.
* gcc.dg/Wkeyword-macro-3.c: New test.
* gcc.dg/Wkeyword-macro-4.c: New test.
* gcc.dg/Wkeyword-macro-5.c: New test.
* gcc.dg/Wkeyword-macro-6.c: New test.
* gcc.dg/Wkeyword-macro-7.c: New test.
* gcc.dg/Wkeyword-macro-8.c: New test.
* gcc.dg/Wkeyword-macro-9.c: New test.
* g++.dg/warn/Wkeyword-macro-1.C: New test.
* g++.dg/warn/Wkeyword-macro-2.C: New test.
* g++.dg/warn/Wkeyword-macro-3.C: New test.
* g++.dg/warn/Wkeyword-macro-4.C: New test.
* g++.dg/warn/Wkeyword-macro-5.C: New test.
* g++.dg/warn/Wkeyword-macro-6.C: New test.
* g++.dg/warn/Wkeyword-macro-7.C: New test.
* g++.dg/warn/Wkeyword-macro-8.C: New test.
* g++.dg/warn/Wkeyword-macro-9.C: New test.
* g++.dg/warn/Wkeyword-macro-10.C: New test.
* g++.dg/opt/pr82577.C: Don't #define register to nothing for
C++17 and later.  Instead define reg macro to nothing for C++17
and later or to register and use it instead of register.
* g++.dg/modules/atom-preamble-3.C: Add -Wno-keyword-macro to
dg-additional-options.
* g++.dg/template/sfinae17.C (static_assert): Rename macro to ...
(my_static_assert): ... this.
(main): Use my_static_assert instead of static_assert.
libcpp/
* include/cpplib.h (struct cpp_options): Add cpp_warn_keyword_macro.
(enum cpp_warning_reason): Add CPP_W_KEYWORD_MACRO enumerator.
(cpp_keyword_p): New inline function.
* directives.cc (do_undef): Support -Wkeyword-macro diagnostics.
* macro.cc (warn_of_redefinition): Ignore NODE_WARN flag on nodes
registered for -Wkeyword-macro.
(_cpp_create_definition): Support -Wkeyword-macro diagnostics.
Formatting fixes.

32 files changed:
gcc/c-family/c-common.h
gcc/c-family/c-opts.cc
gcc/c-family/c.opt
gcc/c-family/c.opt.urls
gcc/c/c-decl.cc
gcc/cp/lex.cc
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/modules/atom-preamble-3.C
gcc/testsuite/g++.dg/opt/pr82577.C
gcc/testsuite/g++.dg/template/sfinae17.C
gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wkeyword-macro-9.c [new file with mode: 0644]
libcpp/directives.cc
libcpp/include/cpplib.h
libcpp/macro.cc

index 7c7e21d2d0eb1b7a9d54e4cec6db4441bbc66895..009c8ef65a635a454a7b119e4ae4d1d1f0793299 100644 (file)
@@ -747,7 +747,7 @@ enum cxx_dialect {
   cxx26
 };
 
-/* The C++ dialect being used. C++98 is the default.  */
+/* The C++ dialect being used.  C++17 is the default.  */
 extern enum cxx_dialect cxx_dialect;
 
 /* Maximum template instantiation depth.  This limit is rather
index c652e82a8c7a7eed09fae5fd3608e94b36dbea63..3fb12b984f235727cec78097920ef70c4b383152 100644 (file)
@@ -959,6 +959,15 @@ c_common_post_options (const char **pfilename)
   if (warn_enum_compare == -1)
     warn_enum_compare = c_dialect_cxx () ? 1 : 0;
 
+  /* For C++26 default to -Wkeyword-macro if -Wpedantic.  */
+  if (cxx_dialect >= cxx26 && pedantic)
+    {
+      SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                          warn_keyword_macro, 1);
+      if (warn_keyword_macro)
+       cpp_opts->cpp_warn_keyword_macro = warn_keyword_macro;
+    }
+
   /* -Wpacked-bitfield-compat is on by default for the C languages.  The
      warning is issued in stor-layout.cc which is not part of the front-end so
      we need to selectively turn it on here.  */
index 12877eb0e1756a2b68004da18d9b3cba6433a86b..0ee2c302c0f1315f335ea82d07c229743954de36 100644 (file)
@@ -964,6 +964,10 @@ Enum(warn_leading_whitespace_kind) String(tabs) Value(2)
 EnumValue
 Enum(warn_leading_whitespace_kind) String(blanks) Value(3)
 
+Wkeyword-macro
+C ObjC C++ ObjC++ CPP(cpp_warn_keyword_macro) CppReason(CPP_W_KEYWORD_MACRO) Var(warn_keyword_macro) Init(0) Warning
+Warn about defining or undefining macros with identifiers equal to keywords (or for C++ conditional keywords or standard attribute names).
+
 Wleading-whitespace=
 C ObjC C++ ObjC++ CPP(cpp_warn_leading_whitespace) CppReason(CPP_W_LEADING_WHITESPACE) Enum(warn_leading_whitespace_kind) Joined RejectNegative Var(warn_leading_whitespace) Init(0) Warning
 Warn about leading whitespace style issues on lines except when in raw string literals.
index 5c97593d703bcb4d954e29da4860ff17b969dd28..6eb117848b484668a2e75551fbedcefc7922765f 100644 (file)
@@ -508,6 +508,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Winvalid-utf8)
 Wjump-misses-init
 UrlSuffix(gcc/Warning-Options.html#index-Wjump-misses-init)
 
+Wkeyword-macro
+UrlSuffix(gcc/Warning-Options.html#index-Wkeyword-macro)
+
 Wleading-whitespace=
 UrlSuffix(gcc/Warning-Options.html#index-Wleading-whitespace_003d)
 
index 7850365f35c600ee48a3fd844986e2b530e7ded0..8e8bac6c32b9564b2662869dcb5c4c94c15c9709 100644 (file)
@@ -4825,6 +4825,29 @@ c_init_decl_processing (void)
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
+
+  if (warn_keyword_macro)
+    {
+      for (unsigned int i = 0; i < num_c_common_reswords; ++i)
+       /* For C register keywords which don't start with underscore
+          or start with just single underscore.  Don't complain about
+          ObjC or Transactional Memory keywords.  */
+       if (c_common_reswords[i].word[0] == '_'
+           && c_common_reswords[i].word[1] == '_')
+         continue;
+       else if (c_common_reswords[i].disable
+                & (D_TRANSMEM | D_OBJC | D_CXX_OBJC))
+         continue;
+       else
+         {
+           tree id = get_identifier (c_common_reswords[i].word);
+           if (C_IS_RESERVED_WORD (id)
+               && C_RID_CODE (id) != RID_CXX_COMPAT_WARN)
+             cpp_lookup (parse_in,
+                         (const unsigned char *) IDENTIFIER_POINTER (id),
+                         IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+         }
+    }
 }
 
 /* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
index 08a634830f52aa4f68b3f0c3c4a3f7a4104d8c7e..b7d2ac62b177d42f8f6aae12a97cdadc036e7f49 100644 (file)
@@ -368,6 +368,66 @@ cxx_init (void)
 
   cxx_init_decl_processing ();
 
+  if (warn_keyword_macro)
+    {
+      for (unsigned int i = 0; i < num_c_common_reswords; ++i)
+       /* For C++ none of the keywords in [lex.key] starts with underscore,
+          don't register anything like that.  Don't complain about
+          ObjC or Transactional Memory keywords.  */
+       if (c_common_reswords[i].word[0] == '_')
+         continue;
+       else if (c_common_reswords[i].disable & (D_TRANSMEM | D_OBJC))
+         continue;
+       else
+         {
+           tree id = get_identifier (c_common_reswords[i].word);
+           if (IDENTIFIER_KEYWORD_P (id)
+               /* Don't register keywords with spaces.  */
+               && IDENTIFIER_POINTER (id)[IDENTIFIER_LENGTH (id) - 1] != ' ')
+             cpp_lookup (parse_in,
+                         (const unsigned char *) IDENTIFIER_POINTER (id),
+                         IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+         }
+      auto warn_on = [] (const char *name) {
+       cpp_lookup (parse_in, (const unsigned char *) name,
+                   strlen (name))->flags |= NODE_WARN;
+      };
+      if (cxx_dialect >= cxx11)
+       {
+         warn_on ("final");
+         warn_on ("override");
+         warn_on ("noreturn");
+         if (cxx_dialect < cxx26)
+           warn_on ("carries_dependency");
+       }
+      if (cxx_dialect >= cxx14)
+       warn_on ("deprecated");
+      if (cxx_dialect >= cxx17)
+       {
+         warn_on ("fallthrough");
+         warn_on ("maybe_unused");
+         warn_on ("nodiscard");
+       }
+      if (cxx_dialect >= cxx20)
+       {
+         warn_on ("likely");
+         warn_on ("unlikely");
+         warn_on ("no_unique_address");
+       }
+      if (flag_modules)
+       {
+         warn_on ("import");
+         warn_on ("module");
+       }
+      if (cxx_dialect >= cxx23)
+       warn_on ("assume");
+      if (cxx_dialect >= cxx26)
+       {
+         warn_on ("replaceable_if_eligible");
+         warn_on ("trivially_relocatable_if_eligible");
+       }
+    }
+
   if (c_common_init () == false)
     {
       input_location = saved_loc;
index 00468a72adaaf1cf8a3a3dd88d68af0a2fe91d80..33ae98c40afb31f4ad7efaa9972dfec9db2b75d9 100644 (file)
@@ -388,6 +388,7 @@ Objective-C and Objective-C++ Dialects}.
 -Winit-self  -Winline  -Wno-int-conversion  -Wint-in-bool-context
 -Wno-int-to-pointer-cast  -Wno-invalid-memory-model
 -Winvalid-pch  -Winvalid-utf8  -Wno-unicode  -Wjump-misses-init
+-Wkeyword-macro
 -Wlarger-than=@var{byte-size}  -Wleading-whitespace=@var{kind}
 -Wlogical-not-parentheses  -Wlogical-op
 -Wlong-long  -Wno-lto-type-mismatch -Wmain  -Wmaybe-uninitialized
@@ -10399,6 +10400,14 @@ Do not warn if certain built-in macros are redefined.  This suppresses
 warnings for redefinition of @code{__TIMESTAMP__}, @code{__TIME__},
 @code{__DATE__}, @code{__FILE__}, and @code{__BASE_FILE__}.
 
+@opindex Wkeyword-macro
+@opindex Wno-keyword-macro
+@item -Wkeyword-macro
+Warn if a keyword is defined as a macro or undefined.
+For C++ identifiers with special meaning or standard attribute identifiers
+are diagnosed as well.  This warning is enabled by default for C++26
+if @code{-Wpedantic} and emits a pedwarn in that case.
+
 @opindex Wfree-labels
 @opindex Wno-free-labels
 @item -Wfree-labels @r{(C and Objective-C only)}
index 74dba7d23a640f1fbdfbb92619682e3c93976d32..915fa743a485cb5a45540ef9bb93b5ceda38254d 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts" }
+// { dg-additional-options "-fmodules-ts -Wno-keyword-macro" }
 #define import import
 import malcolm; // { dg-error "object-like macro" }
 // { dg-error "failed to read" "" { target *-*-* } 0 }
index 1a06897a403e779a1abf72a98ac28c9413b08953..8a4f36d37ea5d6838e451d400c52bd8c36a107e2 100644 (file)
@@ -3,7 +3,9 @@
 
 #if __cplusplus > 201500L
 // register is no longer a keyword in C++17.
-#define register
+#define reg
+#else
+#define reg register
 #endif
 
 class a {
@@ -14,8 +16,8 @@ struct c {
   int d;
   a e;
 } f;
-void fn1(register c *g) {
-  register int *h;
+void fn1(reg c *g) {
+  reg int *h;
   do
     (h) = g->e.b() + (g)->d;
   while (&f);
index eb043cbddfbec165814d483d2fb09f17916aff42..8628726c1927e34a6d0c27c96b0196e0060f4d06 100644 (file)
@@ -1,7 +1,7 @@
 // The conversion from D* to B* is ambiguous, but that should not produce
 // an error, it should remove the first f overload by SFINAE.
 
-#define static_assert(TEST,STR) \
+#define my_static_assert(TEST,STR) \
   do { int ar[(TEST)?1:-1]; } while (0);
 
 struct B {};
@@ -23,6 +23,6 @@ template <class T>
 
 int main()
 {
-  static_assert(sizeof f<int>(0) == sizeof(two), "");
-  static_assert(sizeof f<B *>(0) == sizeof(two), "");
+  my_static_assert(sizeof f<int>(0) == sizeof(two), "");
+  my_static_assert(sizeof f<B *>(0) == sizeof(two), "");
 }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C
new file mode 100644 (file)
index 0000000..f47de7a
--- /dev/null
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#define alignas 1                      // { dg-error "keyword 'alignas' defined as macro" "" { target c++26 } }
+#define alignof 1                      // { dg-error "keyword 'alignof' defined as macro" "" { target c++26 } }
+#define asm 1                          // { dg-error "keyword 'asm' defined as macro" "" { target c++26 } }
+#define auto 1                         // { dg-error "keyword 'auto' defined as macro" "" { target c++26 } }
+#define bool 1                         // { dg-error "keyword 'bool' defined as macro" "" { target c++26 } }
+#define break 1                                // { dg-error "keyword 'break' defined as macro" "" { target c++26 } }
+#define case 1                         // { dg-error "keyword 'case' defined as macro" "" { target c++26 } }
+#define catch 1                                // { dg-error "keyword 'catch' defined as macro" "" { target c++26 } }
+#define char 1                         // { dg-error "keyword 'char' defined as macro" "" { target c++26 } }
+#define char16_t 1                     // { dg-error "keyword 'char16_t' defined as macro" "" { target c++26 } }
+#define char32_t 1                     // { dg-error "keyword 'char32_t' defined as macro" "" { target c++26 } }
+#define char8_t 1                      // { dg-error "keyword 'char8_t' defined as macro" "" { target c++26 } }
+#define class 1                                // { dg-error "keyword 'class' defined as macro" "" { target c++26 } }
+#define co_await 1                     // { dg-error "keyword 'co_await' defined as macro" "" { target c++26 } }
+#define concept 1                      // { dg-error "keyword 'concept' defined as macro" "" { target c++26 } }
+#define const 1                                // { dg-error "keyword 'const' defined as macro" "" { target c++26 } }
+#define const_cast 1                   // { dg-error "keyword 'const_cast' defined as macro" "" { target c++26 } }
+#define consteval 1                    // { dg-error "keyword 'consteval' defined as macro" "" { target c++26 } }
+#define constexpr 1                    // { dg-error "keyword 'constexpr' defined as macro" "" { target c++26 } }
+#define constinit 1                    // { dg-error "keyword 'constinit' defined as macro" "" { target c++26 } }
+#define continue 1                     // { dg-error "keyword 'continue' defined as macro" "" { target c++26 } }
+#define contract_assert 1
+#define co_return 1                    // { dg-error "keyword 'co_return' defined as macro" "" { target c++26 } }
+#define co_yield 1                     // { dg-error "keyword 'co_yield' defined as macro" "" { target c++26 } }
+#define decltype 1                     // { dg-error "keyword 'decltype' defined as macro" "" { target c++26 } }
+#define default 1                      // { dg-error "keyword 'default' defined as macro" "" { target c++26 } }
+#define delete 1                       // { dg-error "keyword 'delete' defined as macro" "" { target c++26 } }
+#define do 1                           // { dg-error "keyword 'do' defined as macro" "" { target c++26 } }
+#define double 1                       // { dg-error "keyword 'double' defined as macro" "" { target c++26 } }
+#define dynamic_cast 1                 // { dg-error "keyword 'dynamic_cast' defined as macro" "" { target c++26 } }
+#define else 1                         // { dg-error "keyword 'else' defined as macro" "" { target c++26 } }
+#define enum 1                         // { dg-error "keyword 'enum' defined as macro" "" { target c++26 } }
+#define explicit 1                     // { dg-error "keyword 'explicit' defined as macro" "" { target c++26 } }
+#define export 1                       // { dg-error "keyword 'export' defined as macro" "" { target c++26 } }
+#define extern 1                       // { dg-error "keyword 'extern' defined as macro" "" { target c++26 } }
+#define false 1                                // { dg-error "keyword 'false' defined as macro" "" { target c++26 } }
+#define float 1                                // { dg-error "keyword 'float' defined as macro" "" { target c++26 } }
+#define for 1                          // { dg-error "keyword 'for' defined as macro" "" { target c++26 } }
+#define friend 1                       // { dg-error "keyword 'friend' defined as macro" "" { target c++26 } }
+#define goto 1                         // { dg-error "keyword 'goto' defined as macro" "" { target c++26 } }
+#define if 1                           // { dg-error "keyword 'if' defined as macro" "" { target c++26 } }
+#define inline 1                       // { dg-error "keyword 'inline' defined as macro" "" { target c++26 } }
+#define int 1                          // { dg-error "keyword 'int' defined as macro" "" { target c++26 } }
+#define long 1                         // { dg-error "keyword 'long' defined as macro" "" { target c++26 } }
+#define mutable 1                      // { dg-error "keyword 'mutable' defined as macro" "" { target c++26 } }
+#define namespace 1                    // { dg-error "keyword 'namespace' defined as macro" "" { target c++26 } }
+#define new 1                          // { dg-error "keyword 'new' defined as macro" "" { target c++26 } }
+#define noexcept 1                     // { dg-error "keyword 'noexcept' defined as macro" "" { target c++26 } }
+#define nullptr 1                      // { dg-error "keyword 'nullptr' defined as macro" "" { target c++26 } }
+#define operator 1                     // { dg-error "keyword 'operator' defined as macro" "" { target c++26 } }
+#define private 1                      // { dg-error "keyword 'private' defined as macro" "" { target c++26 } }
+#define protected 1                    // { dg-error "keyword 'protected' defined as macro" "" { target c++26 } }
+#define public 1                       // { dg-error "keyword 'public' defined as macro" "" { target c++26 } }
+#define register 1                     // { dg-error "keyword 'register' defined as macro" "" { target c++26 } }
+#define reinterpret_cast 1             // { dg-error "keyword 'reinterpret_cast' defined as macro" "" { target c++26 } }
+#define requires 1                     // { dg-error "keyword 'requires' defined as macro" "" { target c++26 } }
+#define return 1                       // { dg-error "keyword 'return' defined as macro" "" { target c++26 } }
+#define short 1                                // { dg-error "keyword 'short' defined as macro" "" { target c++26 } }
+#define signed 1                       // { dg-error "keyword 'signed' defined as macro" "" { target c++26 } }
+#define sizeof 1                       // { dg-error "keyword 'sizeof' defined as macro" "" { target c++26 } }
+#define static 1                       // { dg-error "keyword 'static' defined as macro" "" { target c++26 } }
+#define static_assert 1                        // { dg-error "keyword 'static_assert' defined as macro" "" { target c++26 } }
+#define static_cast 1                  // { dg-error "keyword 'static_cast' defined as macro" "" { target c++26 } }
+#define struct 1                       // { dg-error "keyword 'struct' defined as macro" "" { target c++26 } }
+#define switch 1                       // { dg-error "keyword 'switch' defined as macro" "" { target c++26 } }
+#define template 1                     // { dg-error "keyword 'template' defined as macro" "" { target c++26 } }
+#define this 1                         // { dg-error "keyword 'this' defined as macro" "" { target c++26 } }
+#define thread_local 1                 // { dg-error "keyword 'thread_local' defined as macro" "" { target c++26 } }
+#define throw 1                                // { dg-error "keyword 'throw' defined as macro" "" { target c++26 } }
+#define true 1                         // { dg-error "keyword 'true' defined as macro" "" { target c++26 } }
+#define try 1                          // { dg-error "keyword 'try' defined as macro" "" { target c++26 } }
+#define typedef 1                      // { dg-error "keyword 'typedef' defined as macro" "" { target c++26 } }
+#define typeid 1                       // { dg-error "keyword 'typeid' defined as macro" "" { target c++26 } }
+#define typename 1                     // { dg-error "keyword 'typename' defined as macro" "" { target c++26 } }
+#define union 1                                // { dg-error "keyword 'union' defined as macro" "" { target c++26 } }
+#define unsigned 1                     // { dg-error "keyword 'unsigned' defined as macro" "" { target c++26 } }
+#define using 1                                // { dg-error "keyword 'using' defined as macro" "" { target c++26 } }
+#define virtual 1                      // { dg-error "keyword 'virtual' defined as macro" "" { target c++26 } }
+#define void 1                         // { dg-error "keyword 'void' defined as macro" "" { target c++26 } }
+#define volatile 1                     // { dg-error "keyword 'volatile' defined as macro" "" { target c++26 } }
+#define wchar_t 1                      // { dg-error "keyword 'wchar_t' defined as macro" "" { target c++26 } }
+#define while 1                                // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+
+// [lex.name]
+#define final 1                                // { dg-error "keyword 'final' defined as macro" "" { target c++26 } }
+#define import 1                       // { dg-error "keyword 'import' defined as macro" "" { target c++26 } }
+#define module 1                       // { dg-error "keyword 'module' defined as macro" "" { target c++26 } }
+#define override 1                     // { dg-error "keyword 'override' defined as macro" "" { target c++26 } }
+#define post 1
+#define pre 1
+#define replaceable_if_eligible 1      // { dg-error "keyword 'replaceable_if_eligible' defined as macro" "" { target c++26 } }
+#define trivially_relocatable_if_eligible 1    // { dg-error "keyword 'trivially_relocatable_if_eligible' defined as macro" "" { target c++26 } }
+
+// [dcl.attr]
+#define assume 1                       // { dg-error "keyword 'assume' defined as macro" "" { target c++26 } }
+#define carries_dependency 1
+#define deprecated 1                   // { dg-error "keyword 'deprecated' defined as macro" "" { target c++26 } }
+#define fallthrough 1                  // { dg-error "keyword 'fallthrough' defined as macro" "" { target c++26 } }
+#define indeterminate 1
+#define likely 1                       // { dg-error "keyword 'likely' defined as macro" "" { target c++26 } }
+#define maybe_unused 1                 // { dg-error "keyword 'maybe_unused' defined as macro" "" { target c++26 } }
+#define nodiscard 1                    // { dg-error "keyword 'nodiscard' defined as macro" "" { target c++26 } }
+#define noreturn 1                     // { dg-error "keyword 'noreturn' defined as macro" "" { target c++26 } }
+#define no_unique_address 1            // { dg-error "keyword 'no_unique_address' defined as macro" "" { target c++26 } }
+#define unlikely 1                     // { dg-error "keyword 'unlikely' defined as macro" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C
new file mode 100644 (file)
index 0000000..e6fafcd
--- /dev/null
@@ -0,0 +1,23 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+
+#undef for                             // { dg-warning "undefining keyword 'for'" }
+#define for for                                // { dg-warning "keyword 'for' defined as macro" }
+#undef for                             // { dg-warning "undefining keyword 'for'" }
+#define while do                       // { dg-warning "keyword 'while' defined as macro" }
+#define while do                       // { dg-warning "keyword 'while' defined as macro" }
+#define while for                      // { dg-warning "keyword 'while' defined as macro" }
+                                       // { dg-warning "'while' redefined" "" { target *-*-* } .-1 }
+#undef while                           // { dg-warning "undefining keyword 'while'" }
+#define while while                    // { dg-warning "keyword 'while' defined as macro" }
+#define private public                 // { dg-warning "keyword 'private' defined as macro" }
+#define inline                         // { dg-warning "keyword 'inline' defined as macro" }
+#undef inline                          // { dg-warning "undefining keyword 'inline'" }
+#define inline __inline__ __attribute__((__always_inline__))   // { dg-warning "keyword 'inline' defined as macro" }
+#define likely(a) a
+#undef likely                          // { dg-warning "undefining keyword 'likely'" "" { target c++20 } }
+#define unlikely(a, b, c) a + b + c
+#define unlikely(a, b, c) a + b + c
+#undef unlikely                                // { dg-warning "undefining keyword 'unlikely'" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C
new file mode 100644 (file)
index 0000000..b1a9aa2
--- /dev/null
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#define alignas 1                      // { dg-warning "keyword 'alignas' defined as macro" "" { target c++26 } }
+#define alignof 1                      // { dg-warning "keyword 'alignof' defined as macro" "" { target c++26 } }
+#define asm 1                          // { dg-warning "keyword 'asm' defined as macro" "" { target c++26 } }
+#define auto 1                         // { dg-warning "keyword 'auto' defined as macro" "" { target c++26 } }
+#define bool 1                         // { dg-warning "keyword 'bool' defined as macro" "" { target c++26 } }
+#define break 1                                // { dg-warning "keyword 'break' defined as macro" "" { target c++26 } }
+#define case 1                         // { dg-warning "keyword 'case' defined as macro" "" { target c++26 } }
+#define catch 1                                // { dg-warning "keyword 'catch' defined as macro" "" { target c++26 } }
+#define char 1                         // { dg-warning "keyword 'char' defined as macro" "" { target c++26 } }
+#define char16_t 1                     // { dg-warning "keyword 'char16_t' defined as macro" "" { target c++26 } }
+#define char32_t 1                     // { dg-warning "keyword 'char32_t' defined as macro" "" { target c++26 } }
+#define char8_t 1                      // { dg-warning "keyword 'char8_t' defined as macro" "" { target c++26 } }
+#define class 1                                // { dg-warning "keyword 'class' defined as macro" "" { target c++26 } }
+#define co_await 1                     // { dg-warning "keyword 'co_await' defined as macro" "" { target c++26 } }
+#define concept 1                      // { dg-warning "keyword 'concept' defined as macro" "" { target c++26 } }
+#define const 1                                // { dg-warning "keyword 'const' defined as macro" "" { target c++26 } }
+#define const_cast 1                   // { dg-warning "keyword 'const_cast' defined as macro" "" { target c++26 } }
+#define consteval 1                    // { dg-warning "keyword 'consteval' defined as macro" "" { target c++26 } }
+#define constexpr 1                    // { dg-warning "keyword 'constexpr' defined as macro" "" { target c++26 } }
+#define constinit 1                    // { dg-warning "keyword 'constinit' defined as macro" "" { target c++26 } }
+#define continue 1                     // { dg-warning "keyword 'continue' defined as macro" "" { target c++26 } }
+#define contract_assert 1
+#define co_return 1                    // { dg-warning "keyword 'co_return' defined as macro" "" { target c++26 } }
+#define co_yield 1                     // { dg-warning "keyword 'co_yield' defined as macro" "" { target c++26 } }
+#define decltype 1                     // { dg-warning "keyword 'decltype' defined as macro" "" { target c++26 } }
+#define default 1                      // { dg-warning "keyword 'default' defined as macro" "" { target c++26 } }
+#define delete 1                       // { dg-warning "keyword 'delete' defined as macro" "" { target c++26 } }
+#define do 1                           // { dg-warning "keyword 'do' defined as macro" "" { target c++26 } }
+#define double 1                       // { dg-warning "keyword 'double' defined as macro" "" { target c++26 } }
+#define dynamic_cast 1                 // { dg-warning "keyword 'dynamic_cast' defined as macro" "" { target c++26 } }
+#define else 1                         // { dg-warning "keyword 'else' defined as macro" "" { target c++26 } }
+#define enum 1                         // { dg-warning "keyword 'enum' defined as macro" "" { target c++26 } }
+#define explicit 1                     // { dg-warning "keyword 'explicit' defined as macro" "" { target c++26 } }
+#define export 1                       // { dg-warning "keyword 'export' defined as macro" "" { target c++26 } }
+#define extern 1                       // { dg-warning "keyword 'extern' defined as macro" "" { target c++26 } }
+#define false 1                                // { dg-warning "keyword 'false' defined as macro" "" { target c++26 } }
+#define float 1                                // { dg-warning "keyword 'float' defined as macro" "" { target c++26 } }
+#define for 1                          // { dg-warning "keyword 'for' defined as macro" "" { target c++26 } }
+#define friend 1                       // { dg-warning "keyword 'friend' defined as macro" "" { target c++26 } }
+#define goto 1                         // { dg-warning "keyword 'goto' defined as macro" "" { target c++26 } }
+#define if 1                           // { dg-warning "keyword 'if' defined as macro" "" { target c++26 } }
+#define inline 1                       // { dg-warning "keyword 'inline' defined as macro" "" { target c++26 } }
+#define int 1                          // { dg-warning "keyword 'int' defined as macro" "" { target c++26 } }
+#define long 1                         // { dg-warning "keyword 'long' defined as macro" "" { target c++26 } }
+#define mutable 1                      // { dg-warning "keyword 'mutable' defined as macro" "" { target c++26 } }
+#define namespace 1                    // { dg-warning "keyword 'namespace' defined as macro" "" { target c++26 } }
+#define new 1                          // { dg-warning "keyword 'new' defined as macro" "" { target c++26 } }
+#define noexcept 1                     // { dg-warning "keyword 'noexcept' defined as macro" "" { target c++26 } }
+#define nullptr 1                      // { dg-warning "keyword 'nullptr' defined as macro" "" { target c++26 } }
+#define operator 1                     // { dg-warning "keyword 'operator' defined as macro" "" { target c++26 } }
+#define private 1                      // { dg-warning "keyword 'private' defined as macro" "" { target c++26 } }
+#define protected 1                    // { dg-warning "keyword 'protected' defined as macro" "" { target c++26 } }
+#define public 1                       // { dg-warning "keyword 'public' defined as macro" "" { target c++26 } }
+#define register 1                     // { dg-warning "keyword 'register' defined as macro" "" { target c++26 } }
+#define reinterpret_cast 1             // { dg-warning "keyword 'reinterpret_cast' defined as macro" "" { target c++26 } }
+#define requires 1                     // { dg-warning "keyword 'requires' defined as macro" "" { target c++26 } }
+#define return 1                       // { dg-warning "keyword 'return' defined as macro" "" { target c++26 } }
+#define short 1                                // { dg-warning "keyword 'short' defined as macro" "" { target c++26 } }
+#define signed 1                       // { dg-warning "keyword 'signed' defined as macro" "" { target c++26 } }
+#define sizeof 1                       // { dg-warning "keyword 'sizeof' defined as macro" "" { target c++26 } }
+#define static 1                       // { dg-warning "keyword 'static' defined as macro" "" { target c++26 } }
+#define static_assert 1                        // { dg-warning "keyword 'static_assert' defined as macro" "" { target c++26 } }
+#define static_cast 1                  // { dg-warning "keyword 'static_cast' defined as macro" "" { target c++26 } }
+#define struct 1                       // { dg-warning "keyword 'struct' defined as macro" "" { target c++26 } }
+#define switch 1                       // { dg-warning "keyword 'switch' defined as macro" "" { target c++26 } }
+#define template 1                     // { dg-warning "keyword 'template' defined as macro" "" { target c++26 } }
+#define this 1                         // { dg-warning "keyword 'this' defined as macro" "" { target c++26 } }
+#define thread_local 1                 // { dg-warning "keyword 'thread_local' defined as macro" "" { target c++26 } }
+#define throw 1                                // { dg-warning "keyword 'throw' defined as macro" "" { target c++26 } }
+#define true 1                         // { dg-warning "keyword 'true' defined as macro" "" { target c++26 } }
+#define try 1                          // { dg-warning "keyword 'try' defined as macro" "" { target c++26 } }
+#define typedef 1                      // { dg-warning "keyword 'typedef' defined as macro" "" { target c++26 } }
+#define typeid 1                       // { dg-warning "keyword 'typeid' defined as macro" "" { target c++26 } }
+#define typename 1                     // { dg-warning "keyword 'typename' defined as macro" "" { target c++26 } }
+#define union 1                                // { dg-warning "keyword 'union' defined as macro" "" { target c++26 } }
+#define unsigned 1                     // { dg-warning "keyword 'unsigned' defined as macro" "" { target c++26 } }
+#define using 1                                // { dg-warning "keyword 'using' defined as macro" "" { target c++26 } }
+#define virtual 1                      // { dg-warning "keyword 'virtual' defined as macro" "" { target c++26 } }
+#define void 1                         // { dg-warning "keyword 'void' defined as macro" "" { target c++26 } }
+#define volatile 1                     // { dg-warning "keyword 'volatile' defined as macro" "" { target c++26 } }
+#define wchar_t 1                      // { dg-warning "keyword 'wchar_t' defined as macro" "" { target c++26 } }
+#define while 1                                // { dg-warning "keyword 'while' defined as macro" "" { target c++26 } }
+
+// [lex.name]
+#define final 1                                // { dg-warning "keyword 'final' defined as macro" "" { target c++26 } }
+#define import 1                       // { dg-warning "keyword 'import' defined as macro" "" { target c++26 } }
+#define module 1                       // { dg-warning "keyword 'module' defined as macro" "" { target c++26 } }
+#define override 1                     // { dg-warning "keyword 'override' defined as macro" "" { target c++26 } }
+#define post 1
+#define pre 1
+#define replaceable_if_eligible 1      // { dg-warning "keyword 'replaceable_if_eligible' defined as macro" "" { target c++26 } }
+#define trivially_relocatable_if_eligible 1    // { dg-warning "keyword 'trivially_relocatable_if_eligible' defined as macro" "" { target c++26 } }
+
+// [dcl.attr]
+#define assume 1                       // { dg-warning "keyword 'assume' defined as macro" "" { target c++26 } }
+#define carries_dependency 1
+#define deprecated 1                   // { dg-warning "keyword 'deprecated' defined as macro" "" { target c++26 } }
+#define fallthrough 1                  // { dg-warning "keyword 'fallthrough' defined as macro" "" { target c++26 } }
+#define indeterminate 1
+#define likely 1                       // { dg-warning "keyword 'likely' defined as macro" "" { target c++26 } }
+#define maybe_unused 1                 // { dg-warning "keyword 'maybe_unused' defined as macro" "" { target c++26 } }
+#define nodiscard 1                    // { dg-warning "keyword 'nodiscard' defined as macro" "" { target c++26 } }
+#define noreturn 1                     // { dg-warning "keyword 'noreturn' defined as macro" "" { target c++26 } }
+#define no_unique_address 1            // { dg-warning "keyword 'no_unique_address' defined as macro" "" { target c++26 } }
+#define unlikely 1                     // { dg-warning "keyword 'unlikely' defined as macro" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C
new file mode 100644 (file)
index 0000000..8576b64
--- /dev/null
@@ -0,0 +1,7 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+#include "Wkeyword-macro-1.C"
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C
new file mode 100644 (file)
index 0000000..9ff974d
--- /dev/null
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#undef alignas                                 // { dg-error "undefining keyword 'alignas'" "" { target c++26 } }
+#undef alignof                                 // { dg-error "undefining keyword 'alignof'" "" { target c++26 } }
+#undef asm                             // { dg-error "undefining keyword 'asm'" "" { target c++26 } }
+#undef auto                            // { dg-error "undefining keyword 'auto'" "" { target c++26 } }
+#undef bool                            // { dg-error "undefining keyword 'bool'" "" { target c++26 } }
+#undef break                           // { dg-error "undefining keyword 'break'" "" { target c++26 } }
+#undef case                            // { dg-error "undefining keyword 'case'" "" { target c++26 } }
+#undef catch                           // { dg-error "undefining keyword 'catch'" "" { target c++26 } }
+#undef char                            // { dg-error "undefining keyword 'char'" "" { target c++26 } }
+#undef char16_t                        // { dg-error "undefining keyword 'char16_t'" "" { target c++26 } }
+#undef char32_t                        // { dg-error "undefining keyword 'char32_t'" "" { target c++26 } }
+#undef char8_t                                 // { dg-error "undefining keyword 'char8_t'" "" { target c++26 } }
+#undef class                           // { dg-error "undefining keyword 'class'" "" { target c++26 } }
+#undef co_await                        // { dg-error "undefining keyword 'co_await'" "" { target c++26 } }
+#undef concept                                 // { dg-error "undefining keyword 'concept'" "" { target c++26 } }
+#undef const                           // { dg-error "undefining keyword 'const'" "" { target c++26 } }
+#undef const_cast                      // { dg-error "undefining keyword 'const_cast'" "" { target c++26 } }
+#undef consteval                       // { dg-error "undefining keyword 'consteval'" "" { target c++26 } }
+#undef constexpr                       // { dg-error "undefining keyword 'constexpr'" "" { target c++26 } }
+#undef constinit                       // { dg-error "undefining keyword 'constinit'" "" { target c++26 } }
+#undef continue                        // { dg-error "undefining keyword 'continue'" "" { target c++26 } }
+#undef contract_assert
+#undef co_return                       // { dg-error "undefining keyword 'co_return'" "" { target c++26 } }
+#undef co_yield                        // { dg-error "undefining keyword 'co_yield'" "" { target c++26 } }
+#undef decltype                        // { dg-error "undefining keyword 'decltype'" "" { target c++26 } }
+#undef default                                 // { dg-error "undefining keyword 'default'" "" { target c++26 } }
+#undef delete                          // { dg-error "undefining keyword 'delete'" "" { target c++26 } }
+#undef do                              // { dg-error "undefining keyword 'do'" "" { target c++26 } }
+#undef double                          // { dg-error "undefining keyword 'double'" "" { target c++26 } }
+#undef dynamic_cast                    // { dg-error "undefining keyword 'dynamic_cast'" "" { target c++26 } }
+#undef else                            // { dg-error "undefining keyword 'else'" "" { target c++26 } }
+#undef enum                            // { dg-error "undefining keyword 'enum'" "" { target c++26 } }
+#undef explicit                        // { dg-error "undefining keyword 'explicit'" "" { target c++26 } }
+#undef export                          // { dg-error "undefining keyword 'export'" "" { target c++26 } }
+#undef extern                          // { dg-error "undefining keyword 'extern'" "" { target c++26 } }
+#undef false                           // { dg-error "undefining keyword 'false'" "" { target c++26 } }
+#undef float                           // { dg-error "undefining keyword 'float'" "" { target c++26 } }
+#undef for                             // { dg-error "undefining keyword 'for'" "" { target c++26 } }
+#undef friend                          // { dg-error "undefining keyword 'friend'" "" { target c++26 } }
+#undef goto                            // { dg-error "undefining keyword 'goto'" "" { target c++26 } }
+#undef if                              // { dg-error "undefining keyword 'if'" "" { target c++26 } }
+#undef inline                          // { dg-error "undefining keyword 'inline'" "" { target c++26 } }
+#undef int                             // { dg-error "undefining keyword 'int'" "" { target c++26 } }
+#undef long                            // { dg-error "undefining keyword 'long'" "" { target c++26 } }
+#undef mutable                                 // { dg-error "undefining keyword 'mutable'" "" { target c++26 } }
+#undef namespace                       // { dg-error "undefining keyword 'namespace'" "" { target c++26 } }
+#undef new                             // { dg-error "undefining keyword 'new'" "" { target c++26 } }
+#undef noexcept                        // { dg-error "undefining keyword 'noexcept'" "" { target c++26 } }
+#undef nullptr                                 // { dg-error "undefining keyword 'nullptr'" "" { target c++26 } }
+#undef operator                        // { dg-error "undefining keyword 'operator'" "" { target c++26 } }
+#undef private                                 // { dg-error "undefining keyword 'private'" "" { target c++26 } }
+#undef protected                       // { dg-error "undefining keyword 'protected'" "" { target c++26 } }
+#undef public                          // { dg-error "undefining keyword 'public'" "" { target c++26 } }
+#undef register                        // { dg-error "undefining keyword 'register'" "" { target c++26 } }
+#undef reinterpret_cast                // { dg-error "undefining keyword 'reinterpret_cast'" "" { target c++26 } }
+#undef requires                        // { dg-error "undefining keyword 'requires'" "" { target c++26 } }
+#undef return                          // { dg-error "undefining keyword 'return'" "" { target c++26 } }
+#undef short                           // { dg-error "undefining keyword 'short'" "" { target c++26 } }
+#undef signed                          // { dg-error "undefining keyword 'signed'" "" { target c++26 } }
+#undef sizeof                          // { dg-error "undefining keyword 'sizeof'" "" { target c++26 } }
+#undef static                          // { dg-error "undefining keyword 'static'" "" { target c++26 } }
+#undef static_assert                   // { dg-error "undefining keyword 'static_assert'" "" { target c++26 } }
+#undef static_cast                     // { dg-error "undefining keyword 'static_cast'" "" { target c++26 } }
+#undef struct                          // { dg-error "undefining keyword 'struct'" "" { target c++26 } }
+#undef switch                          // { dg-error "undefining keyword 'switch'" "" { target c++26 } }
+#undef template                        // { dg-error "undefining keyword 'template'" "" { target c++26 } }
+#undef this                            // { dg-error "undefining keyword 'this'" "" { target c++26 } }
+#undef thread_local                    // { dg-error "undefining keyword 'thread_local'" "" { target c++26 } }
+#undef throw                           // { dg-error "undefining keyword 'throw'" "" { target c++26 } }
+#undef true                            // { dg-error "undefining keyword 'true'" "" { target c++26 } }
+#undef try                             // { dg-error "undefining keyword 'try'" "" { target c++26 } }
+#undef typedef                                 // { dg-error "undefining keyword 'typedef'" "" { target c++26 } }
+#undef typeid                          // { dg-error "undefining keyword 'typeid'" "" { target c++26 } }
+#undef typename                        // { dg-error "undefining keyword 'typename'" "" { target c++26 } }
+#undef union                           // { dg-error "undefining keyword 'union'" "" { target c++26 } }
+#undef unsigned                        // { dg-error "undefining keyword 'unsigned'" "" { target c++26 } }
+#undef using                           // { dg-error "undefining keyword 'using'" "" { target c++26 } }
+#undef virtual                                 // { dg-error "undefining keyword 'virtual'" "" { target c++26 } }
+#undef void                            // { dg-error "undefining keyword 'void'" "" { target c++26 } }
+#undef volatile                        // { dg-error "undefining keyword 'volatile'" "" { target c++26 } }
+#undef wchar_t                                 // { dg-error "undefining keyword 'wchar_t'" "" { target c++26 } }
+#undef while                           // { dg-error "undefining keyword 'while'" "" { target c++26 } }
+
+// [lex.name]
+#undef final                           // { dg-error "undefining keyword 'final'" "" { target c++26 } }
+#undef import                          // { dg-error "undefining keyword 'import'" "" { target c++26 } }
+#undef module                          // { dg-error "undefining keyword 'module'" "" { target c++26 } }
+#undef override                        // { dg-error "undefining keyword 'override'" "" { target c++26 } }
+#undef post
+#undef pre
+#undef replaceable_if_eligible         // { dg-error "undefining keyword 'replaceable_if_eligible'" "" { target c++26 } }
+#undef trivially_relocatable_if_eligible       // { dg-error "undefining keyword 'trivially_relocatable_if_eligible'" "" { target c++26 } }
+
+// [dcl.attr]
+#undef assume                          // { dg-error "undefining keyword 'assume'" "" { target c++26 } }
+#undef carries_dependency
+#undef deprecated                      // { dg-error "undefining keyword 'deprecated'" "" { target c++26 } }
+#undef fallthrough                     // { dg-error "undefining keyword 'fallthrough'" "" { target c++26 } }
+#undef indeterminate
+#undef likely                          // { dg-error "undefining keyword 'likely'" "" { target c++26 } }
+#undef maybe_unused                    // { dg-error "undefining keyword 'maybe_unused'" "" { target c++26 } }
+#undef nodiscard                       // { dg-error "undefining keyword 'nodiscard'" "" { target c++26 } }
+#undef noreturn                                // { dg-error "undefining keyword 'noreturn'" "" { target c++26 } }
+#undef no_unique_address               // { dg-error "undefining keyword 'no_unique_address'" "" { target c++26 } }
+#undef unlikely                                // { dg-error "undefining keyword 'unlikely'" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C
new file mode 100644 (file)
index 0000000..657797b
--- /dev/null
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#undef alignas                                 // { dg-warning "undefining keyword 'alignas'" "" { target c++26 } }
+#undef alignof                                 // { dg-warning "undefining keyword 'alignof'" "" { target c++26 } }
+#undef asm                             // { dg-warning "undefining keyword 'asm'" "" { target c++26 } }
+#undef auto                            // { dg-warning "undefining keyword 'auto'" "" { target c++26 } }
+#undef bool                            // { dg-warning "undefining keyword 'bool'" "" { target c++26 } }
+#undef break                           // { dg-warning "undefining keyword 'break'" "" { target c++26 } }
+#undef case                            // { dg-warning "undefining keyword 'case'" "" { target c++26 } }
+#undef catch                           // { dg-warning "undefining keyword 'catch'" "" { target c++26 } }
+#undef char                            // { dg-warning "undefining keyword 'char'" "" { target c++26 } }
+#undef char16_t                        // { dg-warning "undefining keyword 'char16_t'" "" { target c++26 } }
+#undef char32_t                        // { dg-warning "undefining keyword 'char32_t'" "" { target c++26 } }
+#undef char8_t                                 // { dg-warning "undefining keyword 'char8_t'" "" { target c++26 } }
+#undef class                           // { dg-warning "undefining keyword 'class'" "" { target c++26 } }
+#undef co_await                        // { dg-warning "undefining keyword 'co_await'" "" { target c++26 } }
+#undef concept                                 // { dg-warning "undefining keyword 'concept'" "" { target c++26 } }
+#undef const                           // { dg-warning "undefining keyword 'const'" "" { target c++26 } }
+#undef const_cast                      // { dg-warning "undefining keyword 'const_cast'" "" { target c++26 } }
+#undef consteval                       // { dg-warning "undefining keyword 'consteval'" "" { target c++26 } }
+#undef constexpr                       // { dg-warning "undefining keyword 'constexpr'" "" { target c++26 } }
+#undef constinit                       // { dg-warning "undefining keyword 'constinit'" "" { target c++26 } }
+#undef continue                        // { dg-warning "undefining keyword 'continue'" "" { target c++26 } }
+#undef contract_assert
+#undef co_return                       // { dg-warning "undefining keyword 'co_return'" "" { target c++26 } }
+#undef co_yield                        // { dg-warning "undefining keyword 'co_yield'" "" { target c++26 } }
+#undef decltype                        // { dg-warning "undefining keyword 'decltype'" "" { target c++26 } }
+#undef default                                 // { dg-warning "undefining keyword 'default'" "" { target c++26 } }
+#undef delete                          // { dg-warning "undefining keyword 'delete'" "" { target c++26 } }
+#undef do                              // { dg-warning "undefining keyword 'do'" "" { target c++26 } }
+#undef double                          // { dg-warning "undefining keyword 'double'" "" { target c++26 } }
+#undef dynamic_cast                    // { dg-warning "undefining keyword 'dynamic_cast'" "" { target c++26 } }
+#undef else                            // { dg-warning "undefining keyword 'else'" "" { target c++26 } }
+#undef enum                            // { dg-warning "undefining keyword 'enum'" "" { target c++26 } }
+#undef explicit                        // { dg-warning "undefining keyword 'explicit'" "" { target c++26 } }
+#undef export                          // { dg-warning "undefining keyword 'export'" "" { target c++26 } }
+#undef extern                          // { dg-warning "undefining keyword 'extern'" "" { target c++26 } }
+#undef false                           // { dg-warning "undefining keyword 'false'" "" { target c++26 } }
+#undef float                           // { dg-warning "undefining keyword 'float'" "" { target c++26 } }
+#undef for                             // { dg-warning "undefining keyword 'for'" "" { target c++26 } }
+#undef friend                          // { dg-warning "undefining keyword 'friend'" "" { target c++26 } }
+#undef goto                            // { dg-warning "undefining keyword 'goto'" "" { target c++26 } }
+#undef if                              // { dg-warning "undefining keyword 'if'" "" { target c++26 } }
+#undef inline                          // { dg-warning "undefining keyword 'inline'" "" { target c++26 } }
+#undef int                             // { dg-warning "undefining keyword 'int'" "" { target c++26 } }
+#undef long                            // { dg-warning "undefining keyword 'long'" "" { target c++26 } }
+#undef mutable                                 // { dg-warning "undefining keyword 'mutable'" "" { target c++26 } }
+#undef namespace                       // { dg-warning "undefining keyword 'namespace'" "" { target c++26 } }
+#undef new                             // { dg-warning "undefining keyword 'new'" "" { target c++26 } }
+#undef noexcept                        // { dg-warning "undefining keyword 'noexcept'" "" { target c++26 } }
+#undef nullptr                                 // { dg-warning "undefining keyword 'nullptr'" "" { target c++26 } }
+#undef operator                        // { dg-warning "undefining keyword 'operator'" "" { target c++26 } }
+#undef private                                 // { dg-warning "undefining keyword 'private'" "" { target c++26 } }
+#undef protected                       // { dg-warning "undefining keyword 'protected'" "" { target c++26 } }
+#undef public                          // { dg-warning "undefining keyword 'public'" "" { target c++26 } }
+#undef register                        // { dg-warning "undefining keyword 'register'" "" { target c++26 } }
+#undef reinterpret_cast                // { dg-warning "undefining keyword 'reinterpret_cast'" "" { target c++26 } }
+#undef requires                        // { dg-warning "undefining keyword 'requires'" "" { target c++26 } }
+#undef return                          // { dg-warning "undefining keyword 'return'" "" { target c++26 } }
+#undef short                           // { dg-warning "undefining keyword 'short'" "" { target c++26 } }
+#undef signed                          // { dg-warning "undefining keyword 'signed'" "" { target c++26 } }
+#undef sizeof                          // { dg-warning "undefining keyword 'sizeof'" "" { target c++26 } }
+#undef static                          // { dg-warning "undefining keyword 'static'" "" { target c++26 } }
+#undef static_assert                   // { dg-warning "undefining keyword 'static_assert'" "" { target c++26 } }
+#undef static_cast                     // { dg-warning "undefining keyword 'static_cast'" "" { target c++26 } }
+#undef struct                          // { dg-warning "undefining keyword 'struct'" "" { target c++26 } }
+#undef switch                          // { dg-warning "undefining keyword 'switch'" "" { target c++26 } }
+#undef template                        // { dg-warning "undefining keyword 'template'" "" { target c++26 } }
+#undef this                            // { dg-warning "undefining keyword 'this'" "" { target c++26 } }
+#undef thread_local                    // { dg-warning "undefining keyword 'thread_local'" "" { target c++26 } }
+#undef throw                           // { dg-warning "undefining keyword 'throw'" "" { target c++26 } }
+#undef true                            // { dg-warning "undefining keyword 'true'" "" { target c++26 } }
+#undef try                             // { dg-warning "undefining keyword 'try'" "" { target c++26 } }
+#undef typedef                                 // { dg-warning "undefining keyword 'typedef'" "" { target c++26 } }
+#undef typeid                          // { dg-warning "undefining keyword 'typeid'" "" { target c++26 } }
+#undef typename                        // { dg-warning "undefining keyword 'typename'" "" { target c++26 } }
+#undef union                           // { dg-warning "undefining keyword 'union'" "" { target c++26 } }
+#undef unsigned                        // { dg-warning "undefining keyword 'unsigned'" "" { target c++26 } }
+#undef using                           // { dg-warning "undefining keyword 'using'" "" { target c++26 } }
+#undef virtual                                 // { dg-warning "undefining keyword 'virtual'" "" { target c++26 } }
+#undef void                            // { dg-warning "undefining keyword 'void'" "" { target c++26 } }
+#undef volatile                        // { dg-warning "undefining keyword 'volatile'" "" { target c++26 } }
+#undef wchar_t                                 // { dg-warning "undefining keyword 'wchar_t'" "" { target c++26 } }
+#undef while                           // { dg-warning "undefining keyword 'while'" "" { target c++26 } }
+
+// [lex.name]
+#undef final                           // { dg-warning "undefining keyword 'final'" "" { target c++26 } }
+#undef import                          // { dg-warning "undefining keyword 'import'" "" { target c++26 } }
+#undef module                          // { dg-warning "undefining keyword 'module'" "" { target c++26 } }
+#undef override                        // { dg-warning "undefining keyword 'override'" "" { target c++26 } }
+#undef post
+#undef pre
+#undef replaceable_if_eligible         // { dg-warning "undefining keyword 'replaceable_if_eligible'" "" { target c++26 } }
+#undef trivially_relocatable_if_eligible       // { dg-warning "undefining keyword 'trivially_relocatable_if_eligible'" "" { target c++26 } }
+
+// [dcl.attr]
+#undef assume                          // { dg-warning "undefining keyword 'assume'" "" { target c++26 } }
+#undef carries_dependency
+#undef deprecated                      // { dg-warning "undefining keyword 'deprecated'" "" { target c++26 } }
+#undef fallthrough                     // { dg-warning "undefining keyword 'fallthrough'" "" { target c++26 } }
+#undef indeterminate
+#undef likely                          // { dg-warning "undefining keyword 'likely'" "" { target c++26 } }
+#undef maybe_unused                    // { dg-warning "undefining keyword 'maybe_unused'" "" { target c++26 } }
+#undef nodiscard                       // { dg-warning "undefining keyword 'nodiscard'" "" { target c++26 } }
+#undef noreturn                                // { dg-warning "undefining keyword 'noreturn'" "" { target c++26 } }
+#undef no_unique_address               // { dg-warning "undefining keyword 'no_unique_address'" "" { target c++26 } }
+#undef unlikely                                // { dg-warning "undefining keyword 'unlikely'" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C
new file mode 100644 (file)
index 0000000..881df8b
--- /dev/null
@@ -0,0 +1,7 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+#include "Wkeyword-macro-4.C"
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C
new file mode 100644 (file)
index 0000000..30a2c8d
--- /dev/null
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#define alignas 1                      // { dg-warning "keyword 'alignas' defined as macro" "" { target c++11 } }
+#define alignof 1                      // { dg-warning "keyword 'alignof' defined as macro" "" { target c++11 } }
+#define asm 1                          // { dg-warning "keyword 'asm' defined as macro" }
+#define auto 1                         // { dg-warning "keyword 'auto' defined as macro" }
+#define bool 1                         // { dg-warning "keyword 'bool' defined as macro" }
+#define break 1                                // { dg-warning "keyword 'break' defined as macro" }
+#define case 1                         // { dg-warning "keyword 'case' defined as macro" }
+#define catch 1                                // { dg-warning "keyword 'catch' defined as macro" }
+#define char 1                         // { dg-warning "keyword 'char' defined as macro" }
+#define char16_t 1                     // { dg-warning "keyword 'char16_t' defined as macro" "" { target c++11 } }
+#define char32_t 1                     // { dg-warning "keyword 'char32_t' defined as macro" "" { target c++11 } }
+#define char8_t 1                      // { dg-warning "keyword 'char8_t' defined as macro" "" { target c++20 } }
+#define class 1                                // { dg-warning "keyword 'class' defined as macro" }
+#define co_await 1                     // { dg-warning "keyword 'co_await' defined as macro" "" { target c++20 } }
+#define concept 1                      // { dg-warning "keyword 'concept' defined as macro" "" { target c++20 } }
+#define const 1                                // { dg-warning "keyword 'const' defined as macro" }
+#define const_cast 1                   // { dg-warning "keyword 'const_cast' defined as macro" }
+#define consteval 1                    // { dg-warning "keyword 'consteval' defined as macro" "" { target c++20 } }
+#define constexpr 1                    // { dg-warning "keyword 'constexpr' defined as macro" "" { target c++11 } }
+#define constinit 1                    // { dg-warning "keyword 'constinit' defined as macro" "" { target c++20 } }
+#define continue 1                     // { dg-warning "keyword 'continue' defined as macro" }
+#define contract_assert 1
+#define co_return 1                    // { dg-warning "keyword 'co_return' defined as macro" "" { target c++20 } }
+#define co_yield 1                     // { dg-warning "keyword 'co_yield' defined as macro" "" { target c++20 } }
+#define decltype 1                     // { dg-warning "keyword 'decltype' defined as macro" "" { target c++11 } }
+#define default 1                      // { dg-warning "keyword 'default' defined as macro" }
+#define delete 1                       // { dg-warning "keyword 'delete' defined as macro" }
+#define do 1                           // { dg-warning "keyword 'do' defined as macro" }
+#define double 1                       // { dg-warning "keyword 'double' defined as macro" }
+#define dynamic_cast 1                 // { dg-warning "keyword 'dynamic_cast' defined as macro" }
+#define else 1                         // { dg-warning "keyword 'else' defined as macro" }
+#define enum 1                         // { dg-warning "keyword 'enum' defined as macro" }
+#define explicit 1                     // { dg-warning "keyword 'explicit' defined as macro" }
+#define export 1                       // { dg-warning "keyword 'export' defined as macro" }
+#define extern 1                       // { dg-warning "keyword 'extern' defined as macro" }
+#define false 1                                // { dg-warning "keyword 'false' defined as macro" }
+#define float 1                                // { dg-warning "keyword 'float' defined as macro" }
+#define for 1                          // { dg-warning "keyword 'for' defined as macro" }
+#define friend 1                       // { dg-warning "keyword 'friend' defined as macro" }
+#define goto 1                         // { dg-warning "keyword 'goto' defined as macro" }
+#define if 1                           // { dg-warning "keyword 'if' defined as macro" }
+#define inline 1                       // { dg-warning "keyword 'inline' defined as macro" }
+#define int 1                          // { dg-warning "keyword 'int' defined as macro" }
+#define long 1                         // { dg-warning "keyword 'long' defined as macro" }
+#define mutable 1                      // { dg-warning "keyword 'mutable' defined as macro" }
+#define namespace 1                    // { dg-warning "keyword 'namespace' defined as macro" }
+#define new 1                          // { dg-warning "keyword 'new' defined as macro" }
+#define noexcept 1                     // { dg-warning "keyword 'noexcept' defined as macro" "" { target c++11 } }
+#define nullptr 1                      // { dg-warning "keyword 'nullptr' defined as macro" "" { target c++11 } }
+#define operator 1                     // { dg-warning "keyword 'operator' defined as macro" }
+#define private 1                      // { dg-warning "keyword 'private' defined as macro" }
+#define protected 1                    // { dg-warning "keyword 'protected' defined as macro" }
+#define public 1                       // { dg-warning "keyword 'public' defined as macro" }
+#define register 1                     // { dg-warning "keyword 'register' defined as macro" }
+#define reinterpret_cast 1             // { dg-warning "keyword 'reinterpret_cast' defined as macro" }
+#define requires 1                     // { dg-warning "keyword 'requires' defined as macro" "" { target c++20 } }
+#define return 1                       // { dg-warning "keyword 'return' defined as macro" }
+#define short 1                                // { dg-warning "keyword 'short' defined as macro" }
+#define signed 1                       // { dg-warning "keyword 'signed' defined as macro" }
+#define sizeof 1                       // { dg-warning "keyword 'sizeof' defined as macro" }
+#define static 1                       // { dg-warning "keyword 'static' defined as macro" }
+#define static_assert 1                        // { dg-warning "keyword 'static_assert' defined as macro" "" { target c++11 } }
+#define static_cast 1                  // { dg-warning "keyword 'static_cast' defined as macro" }
+#define struct 1                       // { dg-warning "keyword 'struct' defined as macro" }
+#define switch 1                       // { dg-warning "keyword 'switch' defined as macro" }
+#define template 1                     // { dg-warning "keyword 'template' defined as macro" }
+#define this 1                         // { dg-warning "keyword 'this' defined as macro" }
+#define thread_local 1                 // { dg-warning "keyword 'thread_local' defined as macro" "" { target c++11 } }
+#define throw 1                                // { dg-warning "keyword 'throw' defined as macro" }
+#define true 1                         // { dg-warning "keyword 'true' defined as macro" }
+#define try 1                          // { dg-warning "keyword 'try' defined as macro" }
+#define typedef 1                      // { dg-warning "keyword 'typedef' defined as macro" }
+#define typeid 1                       // { dg-warning "keyword 'typeid' defined as macro" }
+#define typename 1                     // { dg-warning "keyword 'typename' defined as macro" }
+#define union 1                                // { dg-warning "keyword 'union' defined as macro" }
+#define unsigned 1                     // { dg-warning "keyword 'unsigned' defined as macro" }
+#define using 1                                // { dg-warning "keyword 'using' defined as macro" }
+#define virtual 1                      // { dg-warning "keyword 'virtual' defined as macro" }
+#define void 1                         // { dg-warning "keyword 'void' defined as macro" }
+#define volatile 1                     // { dg-warning "keyword 'volatile' defined as macro" }
+#define wchar_t 1                      // { dg-warning "keyword 'wchar_t' defined as macro" }
+#define while 1                                // { dg-warning "keyword 'while' defined as macro" }
+
+// [lex.name]
+#define final 1                                // { dg-warning "keyword 'final' defined as macro" "" { target c++11 } }
+#define import 1                       // { dg-warning "keyword 'import' defined as macro" "" { target c++20 } }
+#define module 1                       // { dg-warning "keyword 'module' defined as macro" "" { target c++20 } }
+#define override 1                     // { dg-warning "keyword 'override' defined as macro" "" { target c++11 } }
+#define post 1
+#define pre 1
+#define replaceable_if_eligible 1      // { dg-warning "keyword 'replaceable_if_eligible' defined as macro" "" { target c++26 } }
+#define trivially_relocatable_if_eligible 1    // { dg-warning "keyword 'trivially_relocatable_if_eligible' defined as macro" "" { target c++26 } }
+
+// [dcl.attr]
+#define assume 1                       // { dg-warning "keyword 'assume' defined as macro" "" { target c++23 } }
+#define carries_dependency 1           // { dg-warning "keyword 'carries_dependency' defined as macro" "" { target { c++11 && c++23_down } } }
+#define deprecated 1                   // { dg-warning "keyword 'deprecated' defined as macro" "" { target c++14 } }
+#define fallthrough 1                  // { dg-warning "keyword 'fallthrough' defined as macro" "" { target c++17 } }
+#define indeterminate 1
+#define likely 1                       // { dg-warning "keyword 'likely' defined as macro" "" { target c++20 } }
+#define maybe_unused 1                 // { dg-warning "keyword 'maybe_unused' defined as macro" "" { target c++17 } }
+#define nodiscard 1                    // { dg-warning "keyword 'nodiscard' defined as macro" "" { target c++17 } }
+#define noreturn 1                     // { dg-warning "keyword 'noreturn' defined as macro" "" { target c++11 } }
+#define no_unique_address 1            // { dg-warning "keyword 'no_unique_address' defined as macro" "" { target c++20 } }
+#define unlikely 1                     // { dg-warning "keyword 'unlikely' defined as macro" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C
new file mode 100644 (file)
index 0000000..7dcc377
--- /dev/null
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#undef alignas                         // { dg-warning "undefining keyword 'alignas'" "" { target c++11 } }
+#undef alignof                         // { dg-warning "undefining keyword 'alignof'" "" { target c++11 } }
+#undef asm                             // { dg-warning "undefining keyword 'asm'" }
+#undef auto                            // { dg-warning "undefining keyword 'auto'" }
+#undef bool                            // { dg-warning "undefining keyword 'bool'" }
+#undef break                           // { dg-warning "undefining keyword 'break'" }
+#undef case                            // { dg-warning "undefining keyword 'case'" }
+#undef catch                           // { dg-warning "undefining keyword 'catch'" }
+#undef char                            // { dg-warning "undefining keyword 'char'" }
+#undef char16_t                                // { dg-warning "undefining keyword 'char16_t'" "" { target c++11 } }
+#undef char32_t                                // { dg-warning "undefining keyword 'char32_t'" "" { target c++11 } }
+#undef char8_t                         // { dg-warning "undefining keyword 'char8_t'" "" { target c++20 } }
+#undef class                           // { dg-warning "undefining keyword 'class'" }
+#undef co_await                                // { dg-warning "undefining keyword 'co_await'" "" { target c++20 } }
+#undef concept                         // { dg-warning "undefining keyword 'concept'" "" { target c++20 } }
+#undef const                           // { dg-warning "undefining keyword 'const'" }
+#undef const_cast                      // { dg-warning "undefining keyword 'const_cast'" }
+#undef consteval                       // { dg-warning "undefining keyword 'consteval'" "" { target c++20 } }
+#undef constexpr                       // { dg-warning "undefining keyword 'constexpr'" "" { target c++11 } }
+#undef constinit                       // { dg-warning "undefining keyword 'constinit'" "" { target c++20 } }
+#undef continue                                // { dg-warning "undefining keyword 'continue'" }
+#undef contract_assert
+#undef co_return                       // { dg-warning "undefining keyword 'co_return'" "" { target c++20 } }
+#undef co_yield                                // { dg-warning "undefining keyword 'co_yield'" "" { target c++20 } }
+#undef decltype                                // { dg-warning "undefining keyword 'decltype'" "" { target c++11 } }
+#undef default                         // { dg-warning "undefining keyword 'default'" }
+#undef delete                          // { dg-warning "undefining keyword 'delete'" }
+#undef do                              // { dg-warning "undefining keyword 'do'" }
+#undef double                          // { dg-warning "undefining keyword 'double'" }
+#undef dynamic_cast                    // { dg-warning "undefining keyword 'dynamic_cast'" }
+#undef else                            // { dg-warning "undefining keyword 'else'" }
+#undef enum                            // { dg-warning "undefining keyword 'enum'" }
+#undef explicit                                // { dg-warning "undefining keyword 'explicit'" }
+#undef export                          // { dg-warning "undefining keyword 'export'" }
+#undef extern                          // { dg-warning "undefining keyword 'extern'" }
+#undef false                           // { dg-warning "undefining keyword 'false'" }
+#undef float                           // { dg-warning "undefining keyword 'float'" }
+#undef for                             // { dg-warning "undefining keyword 'for'" }
+#undef friend                          // { dg-warning "undefining keyword 'friend'" }
+#undef goto                            // { dg-warning "undefining keyword 'goto'" }
+#undef if                              // { dg-warning "undefining keyword 'if'" }
+#undef inline                          // { dg-warning "undefining keyword 'inline'" }
+#undef int                             // { dg-warning "undefining keyword 'int'" }
+#undef long                            // { dg-warning "undefining keyword 'long'" }
+#undef mutable                         // { dg-warning "undefining keyword 'mutable'" }
+#undef namespace                       // { dg-warning "undefining keyword 'namespace'" }
+#undef new                             // { dg-warning "undefining keyword 'new'" }
+#undef noexcept                                // { dg-warning "undefining keyword 'noexcept'" "" { target c++11 } }
+#undef nullptr                         // { dg-warning "undefining keyword 'nullptr'" "" { target c++11 } }
+#undef operator                                // { dg-warning "undefining keyword 'operator'" }
+#undef private                         // { dg-warning "undefining keyword 'private'" }
+#undef protected                       // { dg-warning "undefining keyword 'protected'" }
+#undef public                          // { dg-warning "undefining keyword 'public'" }
+#undef register                                // { dg-warning "undefining keyword 'register'" }
+#undef reinterpret_cast                        // { dg-warning "undefining keyword 'reinterpret_cast'" }
+#undef requires                                // { dg-warning "undefining keyword 'requires'" "" { target c++20 } }
+#undef return                          // { dg-warning "undefining keyword 'return'" }
+#undef short                           // { dg-warning "undefining keyword 'short'" }
+#undef signed                          // { dg-warning "undefining keyword 'signed'" }
+#undef sizeof                          // { dg-warning "undefining keyword 'sizeof'" }
+#undef static                          // { dg-warning "undefining keyword 'static'" }
+#undef static_assert                   // { dg-warning "undefining keyword 'static_assert'" "" { target c++11 } }
+#undef static_cast                     // { dg-warning "undefining keyword 'static_cast'" }
+#undef struct                          // { dg-warning "undefining keyword 'struct'" }
+#undef switch                          // { dg-warning "undefining keyword 'switch'" }
+#undef template                                // { dg-warning "undefining keyword 'template'" }
+#undef this                            // { dg-warning "undefining keyword 'this'" }
+#undef thread_local                    // { dg-warning "undefining keyword 'thread_local'" "" { target c++11 } }
+#undef throw                           // { dg-warning "undefining keyword 'throw'" }
+#undef true                            // { dg-warning "undefining keyword 'true'" }
+#undef try                             // { dg-warning "undefining keyword 'try'" }
+#undef typedef                         // { dg-warning "undefining keyword 'typedef'" }
+#undef typeid                          // { dg-warning "undefining keyword 'typeid'" }
+#undef typename                                // { dg-warning "undefining keyword 'typename'" }
+#undef union                           // { dg-warning "undefining keyword 'union'" }
+#undef unsigned                                // { dg-warning "undefining keyword 'unsigned'" }
+#undef using                           // { dg-warning "undefining keyword 'using'" }
+#undef virtual                         // { dg-warning "undefining keyword 'virtual'" }
+#undef void                            // { dg-warning "undefining keyword 'void'" }
+#undef volatile                                // { dg-warning "undefining keyword 'volatile'" }
+#undef wchar_t                         // { dg-warning "undefining keyword 'wchar_t'" }
+#undef while                           // { dg-warning "undefining keyword 'while'" }
+
+// [lex.name]
+#undef final                           // { dg-warning "undefining keyword 'final'" "" { target c++11 } }
+#undef import                          // { dg-warning "undefining keyword 'import'" "" { target c++20 } }
+#undef module                          // { dg-warning "undefining keyword 'module'" "" { target c++20 } }
+#undef override                                // { dg-warning "undefining keyword 'override'" "" { target c++11 } }
+#undef post
+#undef pre
+#undef replaceable_if_eligible         // { dg-warning "undefining keyword 'replaceable_if_eligible'" "" { target c++26 } }
+#undef trivially_relocatable_if_eligible       // { dg-warning "undefining keyword 'trivially_relocatable_if_eligible'" "" { target c++26 } }
+
+// [dcl.attr]
+#undef assume                          // { dg-warning "undefining keyword 'assume'" "" { target c++23 } }
+#undef carries_dependency              // { dg-warning "undefining keyword 'carries_dependency'" "" { target { c++11 && c++23_down } } }
+#undef deprecated                      // { dg-warning "undefining keyword 'deprecated'" "" { target c++14 } }
+#undef fallthrough                     // { dg-warning "undefining keyword 'fallthrough'" "" { target c++17 } }
+#undef indeterminate
+#undef likely                          // { dg-warning "undefining keyword 'likely'" "" { target c++20 } }
+#undef maybe_unused                    // { dg-warning "undefining keyword 'maybe_unused'" "" { target c++17 } }
+#undef nodiscard                       // { dg-warning "undefining keyword 'nodiscard'" "" { target c++17 } }
+#undef noreturn                                // { dg-warning "undefining keyword 'noreturn'" "" { target c++11 } }
+#undef no_unique_address               // { dg-warning "undefining keyword 'no_unique_address'" "" { target c++20 } }
+#undef unlikely                                // { dg-warning "undefining keyword 'unlikely'" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C
new file mode 100644 (file)
index 0000000..741cdee
--- /dev/null
@@ -0,0 +1,22 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#undef for                             // { dg-error "undefining keyword 'for'" "" { target c++26 } }
+#define for for                                // { dg-error "keyword 'for' defined as macro" "" { target c++26 } }
+#undef for                             // { dg-error "undefining keyword 'for'" "" { target c++26 } }
+#define while do                       // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+#define while do                       // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+#define while for                      // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+                                       // { dg-error "'while' redefined" "" { target *-*-* } .-1 }
+#undef while                           // { dg-error "undefining keyword 'while'" "" { target c++26 } }
+#define while while                    // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+#define private public                 // { dg-error "keyword 'private' defined as macro" "" { target c++26 } }
+#define inline                         // { dg-error "keyword 'inline' defined as macro" "" { target c++26 } }
+#undef inline                          // { dg-error "undefining keyword 'inline'" "" { target c++26 } }
+#define inline __inline__ __attribute__((__always_inline__))   // { dg-error "keyword 'inline' defined as macro" "" { target c++26 } }
+#define likely(a) a
+#undef likely                          // { dg-error "undefining keyword 'likely'" "" { target c++26 } }
+#define unlikely(a, b, c) a + b + c
+#define unlikely(a, b, c) a + b + c
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-1.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-1.c
new file mode 100644 (file)
index 0000000..0b2d78f
--- /dev/null
@@ -0,0 +1,62 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c23" }
+
+#define _Alignas 1                     // { dg-warning "keyword '_Alignas' defined as macro" }
+#define _Alignof 1                     // { dg-warning "keyword '_Alignof' defined as macro" }
+#define _Atomic 1                      // { dg-warning "keyword '_Atomic' defined as macro" }
+#define _BitInt 1                      // { dg-warning "keyword '_BitInt' defined as macro" }
+#define _Bool 1                                // { dg-warning "keyword '_Bool' defined as macro" }
+#define _Complex 1                     // { dg-warning "keyword '_Complex' defined as macro" }
+#define _Decimal128 1                  // { dg-warning "keyword '_Decimal128' defined as macro" }
+#define _Decimal32 1                   // { dg-warning "keyword '_Decimal32' defined as macro" }
+#define _Decimal64 1                   // { dg-warning "keyword '_Decimal64' defined as macro" }
+#define _Generic 1                     // { dg-warning "keyword '_Generic' defined as macro" }
+#define _Imaginary 1                   // { dg-warning "keyword '_Imaginary' defined as macro" }
+#define _Noreturn 1                    // { dg-warning "keyword '_Noreturn' defined as macro" }
+#define _Static_assert 1               // { dg-warning "keyword '_Static_assert' defined as macro" }
+#define _Thread_local 1                        // { dg-warning "keyword '_Thread_local' defined as macro" }
+#define alignas 1                      // { dg-warning "keyword 'alignas' defined as macro" }
+#define alignof 1                      // { dg-warning "keyword 'alignof' defined as macro" }
+#define auto 1                         // { dg-warning "keyword 'auto' defined as macro" }
+#define bool 1                         // { dg-warning "keyword 'bool' defined as macro" }
+#define break 1                                // { dg-warning "keyword 'break' defined as macro" }
+#define case 1                         // { dg-warning "keyword 'case' defined as macro" }
+#define char 1                         // { dg-warning "keyword 'char' defined as macro" }
+#define const 1                                // { dg-warning "keyword 'const' defined as macro" }
+#define constexpr 1                    // { dg-warning "keyword 'constexpr' defined as macro" }
+#define continue 1                     // { dg-warning "keyword 'continue' defined as macro" }
+#define default 1                      // { dg-warning "keyword 'default' defined as macro" }
+#define do 1                           // { dg-warning "keyword 'do' defined as macro" }
+#define double 1                       // { dg-warning "keyword 'double' defined as macro" }
+#define else 1                         // { dg-warning "keyword 'else' defined as macro" }
+#define enum 1                         // { dg-warning "keyword 'enum' defined as macro" }
+#define extern 1                       // { dg-warning "keyword 'extern' defined as macro" }
+#define false 1                                // { dg-warning "keyword 'false' defined as macro" }
+#define float 1                                // { dg-warning "keyword 'float' defined as macro" }
+#define for 1                          // { dg-warning "keyword 'for' defined as macro" }
+#define goto 1                         // { dg-warning "keyword 'goto' defined as macro" }
+#define if 1                           // { dg-warning "keyword 'if' defined as macro" }
+#define inline 1                       // { dg-warning "keyword 'inline' defined as macro" }
+#define int 1                          // { dg-warning "keyword 'int' defined as macro" }
+#define long 1                         // { dg-warning "keyword 'long' defined as macro" }
+#define nullptr 1                      // { dg-warning "keyword 'nullptr' defined as macro" }
+#define register 1                     // { dg-warning "keyword 'register' defined as macro" }
+#define restrict 1                     // { dg-warning "keyword 'restrict' defined as macro" }
+#define return 1                       // { dg-warning "keyword 'return' defined as macro" }
+#define short 1                                // { dg-warning "keyword 'short' defined as macro" }
+#define signed 1                       // { dg-warning "keyword 'signed' defined as macro" }
+#define sizeof 1                       // { dg-warning "keyword 'sizeof' defined as macro" }
+#define static 1                       // { dg-warning "keyword 'static' defined as macro" }
+#define static_assert 1                        // { dg-warning "keyword 'static_assert' defined as macro" }
+#define struct 1                       // { dg-warning "keyword 'struct' defined as macro" }
+#define switch 1                       // { dg-warning "keyword 'switch' defined as macro" }
+#define thread_local 1                 // { dg-warning "keyword 'thread_local' defined as macro" }
+#define true 1                         // { dg-warning "keyword 'true' defined as macro" }
+#define typedef 1                      // { dg-warning "keyword 'typedef' defined as macro" }
+#define typeof 1                       // { dg-warning "keyword 'typeof' defined as macro" }
+#define typeof_unqual 1                        // { dg-warning "keyword 'typeof_unqual' defined as macro" }
+#define union 1                                // { dg-warning "keyword 'union' defined as macro" }
+#define unsigned 1                     // { dg-warning "keyword 'unsigned' defined as macro" }
+#define void 1                         // { dg-warning "keyword 'void' defined as macro" }
+#define volatile 1                     // { dg-warning "keyword 'volatile' defined as macro" }
+#define while 1                                // { dg-warning "keyword 'while' defined as macro" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-2.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-2.c
new file mode 100644 (file)
index 0000000..329a55a
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c23" }
+
+#include "Wkeyword-macro-1.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-3.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-3.c
new file mode 100644 (file)
index 0000000..f631b8e
--- /dev/null
@@ -0,0 +1,62 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c23" }
+
+#undef _Alignas                        // { dg-warning "undefining keyword '_Alignas'" }
+#undef _Alignof                        // { dg-warning "undefining keyword '_Alignof'" }
+#undef _Atomic                 // { dg-warning "undefining keyword '_Atomic'" }
+#undef _BitInt                 // { dg-warning "undefining keyword '_BitInt'" }
+#undef _Bool                   // { dg-warning "undefining keyword '_Bool'" }
+#undef _Complex                        // { dg-warning "undefining keyword '_Complex'" }
+#undef _Decimal128             // { dg-warning "undefining keyword '_Decimal128'" }
+#undef _Decimal32              // { dg-warning "undefining keyword '_Decimal32'" }
+#undef _Decimal64              // { dg-warning "undefining keyword '_Decimal64'" }
+#undef _Generic                        // { dg-warning "undefining keyword '_Generic'" }
+#undef _Imaginary              // { dg-warning "undefining keyword '_Imaginary'" }
+#undef _Noreturn               // { dg-warning "undefining keyword '_Noreturn'" }
+#undef _Static_assert          // { dg-warning "undefining keyword '_Static_assert'" }
+#undef _Thread_local           // { dg-warning "undefining keyword '_Thread_local'" }
+#undef alignas                 // { dg-warning "undefining keyword 'alignas'" }
+#undef alignof                 // { dg-warning "undefining keyword 'alignof'" }
+#undef auto                    // { dg-warning "undefining keyword 'auto'" }
+#undef bool                    // { dg-warning "undefining keyword 'bool'" }
+#undef break                   // { dg-warning "undefining keyword 'break'" }
+#undef case                    // { dg-warning "undefining keyword 'case'" }
+#undef char                    // { dg-warning "undefining keyword 'char'" }
+#undef const                   // { dg-warning "undefining keyword 'const'" }
+#undef constexpr               // { dg-warning "undefining keyword 'constexpr'" }
+#undef continue                        // { dg-warning "undefining keyword 'continue'" }
+#undef default                 // { dg-warning "undefining keyword 'default'" }
+#undef do                      // { dg-warning "undefining keyword 'do'" }
+#undef double                  // { dg-warning "undefining keyword 'double'" }
+#undef else                    // { dg-warning "undefining keyword 'else'" }
+#undef enum                    // { dg-warning "undefining keyword 'enum'" }
+#undef extern                  // { dg-warning "undefining keyword 'extern'" }
+#undef false                   // { dg-warning "undefining keyword 'false'" }
+#undef float                   // { dg-warning "undefining keyword 'float'" }
+#undef for                     // { dg-warning "undefining keyword 'for'" }
+#undef goto                    // { dg-warning "undefining keyword 'goto'" }
+#undef if                      // { dg-warning "undefining keyword 'if'" }
+#undef inline                  // { dg-warning "undefining keyword 'inline'" }
+#undef int                     // { dg-warning "undefining keyword 'int'" }
+#undef long                    // { dg-warning "undefining keyword 'long'" }
+#undef nullptr                 // { dg-warning "undefining keyword 'nullptr'" }
+#undef register                        // { dg-warning "undefining keyword 'register'" }
+#undef restrict                        // { dg-warning "undefining keyword 'restrict'" }
+#undef return                  // { dg-warning "undefining keyword 'return'" }
+#undef short                   // { dg-warning "undefining keyword 'short'" }
+#undef signed                  // { dg-warning "undefining keyword 'signed'" }
+#undef sizeof                  // { dg-warning "undefining keyword 'sizeof'" }
+#undef static                  // { dg-warning "undefining keyword 'static'" }
+#undef static_assert           // { dg-warning "undefining keyword 'static_assert'" }
+#undef struct                  // { dg-warning "undefining keyword 'struct'" }
+#undef switch                  // { dg-warning "undefining keyword 'switch'" }
+#undef thread_local            // { dg-warning "undefining keyword 'thread_local'" }
+#undef true                    // { dg-warning "undefining keyword 'true'" }
+#undef typedef                 // { dg-warning "undefining keyword 'typedef'" }
+#undef typeof                  // { dg-warning "undefining keyword 'typeof'" }
+#undef typeof_unqual           // { dg-warning "undefining keyword 'typeof_unqual'" }
+#undef union                   // { dg-warning "undefining keyword 'union'" }
+#undef unsigned                        // { dg-warning "undefining keyword 'unsigned'" }
+#undef void                    // { dg-warning "undefining keyword 'void'" }
+#undef volatile                        // { dg-warning "undefining keyword 'volatile'" }
+#undef while                   // { dg-warning "undefining keyword 'while'" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-4.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-4.c
new file mode 100644 (file)
index 0000000..796d654
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c23" }
+
+#include "Wkeyword-macro-3.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-5.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-5.c
new file mode 100644 (file)
index 0000000..c61a1ce
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c17" }
+
+#define _Alignas 1                     // { dg-warning "keyword '_Alignas' defined as macro" }
+#define _Alignof 1                     // { dg-warning "keyword '_Alignof' defined as macro" }
+#define _Atomic 1                      // { dg-warning "keyword '_Atomic' defined as macro" }
+#define _Bool 1                                // { dg-warning "keyword '_Bool' defined as macro" }
+#define _Complex 1                     // { dg-warning "keyword '_Complex' defined as macro" }
+#define _Generic 1                     // { dg-warning "keyword '_Generic' defined as macro" }
+#define _Imaginary 1                   // { dg-warning "keyword '_Imaginary' defined as macro" }
+#define _Noreturn 1                    // { dg-warning "keyword '_Noreturn' defined as macro" }
+#define _Static_assert 1               // { dg-warning "keyword '_Static_assert' defined as macro" }
+#define _Thread_local 1                        // { dg-warning "keyword '_Thread_local' defined as macro" }
+#define auto 1                         // { dg-warning "keyword 'auto' defined as macro" }
+#define break 1                                // { dg-warning "keyword 'break' defined as macro" }
+#define case 1                         // { dg-warning "keyword 'case' defined as macro" }
+#define char 1                         // { dg-warning "keyword 'char' defined as macro" }
+#define const 1                                // { dg-warning "keyword 'const' defined as macro" }
+#define continue 1                     // { dg-warning "keyword 'continue' defined as macro" }
+#define default 1                      // { dg-warning "keyword 'default' defined as macro" }
+#define do 1                           // { dg-warning "keyword 'do' defined as macro" }
+#define double 1                       // { dg-warning "keyword 'double' defined as macro" }
+#define else 1                         // { dg-warning "keyword 'else' defined as macro" }
+#define enum 1                         // { dg-warning "keyword 'enum' defined as macro" }
+#define extern 1                       // { dg-warning "keyword 'extern' defined as macro" }
+#define float 1                                // { dg-warning "keyword 'float' defined as macro" }
+#define for 1                          // { dg-warning "keyword 'for' defined as macro" }
+#define goto 1                         // { dg-warning "keyword 'goto' defined as macro" }
+#define if 1                           // { dg-warning "keyword 'if' defined as macro" }
+#define inline 1                       // { dg-warning "keyword 'inline' defined as macro" }
+#define int 1                          // { dg-warning "keyword 'int' defined as macro" }
+#define long 1                         // { dg-warning "keyword 'long' defined as macro" }
+#define register 1                     // { dg-warning "keyword 'register' defined as macro" }
+#define restrict 1                     // { dg-warning "keyword 'restrict' defined as macro" }
+#define return 1                       // { dg-warning "keyword 'return' defined as macro" }
+#define short 1                                // { dg-warning "keyword 'short' defined as macro" }
+#define signed 1                       // { dg-warning "keyword 'signed' defined as macro" }
+#define sizeof 1                       // { dg-warning "keyword 'sizeof' defined as macro" }
+#define static 1                       // { dg-warning "keyword 'static' defined as macro" }
+#define struct 1                       // { dg-warning "keyword 'struct' defined as macro" }
+#define switch 1                       // { dg-warning "keyword 'switch' defined as macro" }
+#define typedef 1                      // { dg-warning "keyword 'typedef' defined as macro" }
+#define union 1                                // { dg-warning "keyword 'union' defined as macro" }
+#define unsigned 1                     // { dg-warning "keyword 'unsigned' defined as macro" }
+#define void 1                         // { dg-warning "keyword 'void' defined as macro" }
+#define volatile 1                     // { dg-warning "keyword 'volatile' defined as macro" }
+#define while 1                                // { dg-warning "keyword 'while' defined as macro" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-6.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-6.c
new file mode 100644 (file)
index 0000000..760ece6
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c17" }
+
+#include "Wkeyword-macro-5.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-7.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-7.c
new file mode 100644 (file)
index 0000000..dc146d4
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c17" }
+
+#undef _Alignas                        // { dg-warning "undefining keyword '_Alignas'" }
+#undef _Alignof                        // { dg-warning "undefining keyword '_Alignof'" }
+#undef _Atomic                 // { dg-warning "undefining keyword '_Atomic'" }
+#undef _Bool                   // { dg-warning "undefining keyword '_Bool'" }
+#undef _Complex                        // { dg-warning "undefining keyword '_Complex'" }
+#undef _Generic                        // { dg-warning "undefining keyword '_Generic'" }
+#undef _Imaginary              // { dg-warning "undefining keyword '_Imaginary'" }
+#undef _Noreturn               // { dg-warning "undefining keyword '_Noreturn'" }
+#undef _Static_assert          // { dg-warning "undefining keyword '_Static_assert'" }
+#undef _Thread_local           // { dg-warning "undefining keyword '_Thread_local'" }
+#undef auto                    // { dg-warning "undefining keyword 'auto'" }
+#undef break                   // { dg-warning "undefining keyword 'break'" }
+#undef case                    // { dg-warning "undefining keyword 'case'" }
+#undef char                    // { dg-warning "undefining keyword 'char'" }
+#undef const                   // { dg-warning "undefining keyword 'const'" }
+#undef continue                        // { dg-warning "undefining keyword 'continue'" }
+#undef default                 // { dg-warning "undefining keyword 'default'" }
+#undef do                      // { dg-warning "undefining keyword 'do'" }
+#undef double                  // { dg-warning "undefining keyword 'double'" }
+#undef else                    // { dg-warning "undefining keyword 'else'" }
+#undef enum                    // { dg-warning "undefining keyword 'enum'" }
+#undef extern                  // { dg-warning "undefining keyword 'extern'" }
+#undef float                   // { dg-warning "undefining keyword 'float'" }
+#undef for                     // { dg-warning "undefining keyword 'for'" }
+#undef goto                    // { dg-warning "undefining keyword 'goto'" }
+#undef if                      // { dg-warning "undefining keyword 'if'" }
+#undef inline                  // { dg-warning "undefining keyword 'inline'" }
+#undef int                     // { dg-warning "undefining keyword 'int'" }
+#undef long                    // { dg-warning "undefining keyword 'long'" }
+#undef register                        // { dg-warning "undefining keyword 'register'" }
+#undef restrict                        // { dg-warning "undefining keyword 'restrict'" }
+#undef return                  // { dg-warning "undefining keyword 'return'" }
+#undef short                   // { dg-warning "undefining keyword 'short'" }
+#undef signed                  // { dg-warning "undefining keyword 'signed'" }
+#undef sizeof                  // { dg-warning "undefining keyword 'sizeof'" }
+#undef static                  // { dg-warning "undefining keyword 'static'" }
+#undef struct                  // { dg-warning "undefining keyword 'struct'" }
+#undef switch                  // { dg-warning "undefining keyword 'switch'" }
+#undef typedef                 // { dg-warning "undefining keyword 'typedef'" }
+#undef union                   // { dg-warning "undefining keyword 'union'" }
+#undef unsigned                        // { dg-warning "undefining keyword 'unsigned'" }
+#undef void                    // { dg-warning "undefining keyword 'void'" }
+#undef volatile                        // { dg-warning "undefining keyword 'volatile'" }
+#undef while                   // { dg-warning "undefining keyword 'while'" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-8.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-8.c
new file mode 100644 (file)
index 0000000..b209f40
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c17" }
+
+#include "Wkeyword-macro-7.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-9.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-9.c
new file mode 100644 (file)
index 0000000..5d6b650
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+
+#undef for                             // { dg-warning "undefining keyword 'for'" }
+#define for for                                // { dg-warning "keyword 'for' defined as macro" }
+#undef for                             // { dg-warning "undefining keyword 'for'" }
+#define while do                       // { dg-warning "keyword 'while' defined as macro" }
+#define while do                       // { dg-warning "keyword 'while' defined as macro" }
+#define while for                      // { dg-warning "keyword 'while' defined as macro" }
+                                       // { dg-warning "'while' redefined" "" { target *-*-* } .-1 }
+#undef while                           // { dg-warning "undefining keyword 'while'" }
+#define while while                    // { dg-warning "keyword 'while' defined as macro" }
+#define inline                         // { dg-warning "keyword 'inline' defined as macro" }
+#undef inline                          // { dg-warning "undefining keyword 'inline'" }
+#define inline __inline__ __attribute__((__always_inline__))   // { dg-warning "keyword 'inline' defined as macro" }
index 4d06caa9b5652a14e091a6b698e237aac67c095c..47fb8fbdd131bed4632373de357f887f7ecc64ca 100644 (file)
@@ -734,13 +734,30 @@ do_undef (cpp_reader *pfile)
       if (pfile->cb.undef)
        pfile->cb.undef (pfile, pfile->directive_line, node);
 
+      /* Handle -Wkeyword-macro registered identifiers.  */
+      bool diagnosed = false;
+      if (CPP_OPTION (pfile, cpp_warn_keyword_macro) && cpp_keyword_p (node))
+       {
+         if (CPP_OPTION (pfile, cpp_pedantic)
+             && CPP_OPTION (pfile, cplusplus)
+             && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)
+           cpp_pedwarning (pfile, CPP_W_KEYWORD_MACRO,
+                           "undefining keyword %qs", NODE_NAME (node));
+         else
+           cpp_warning (pfile, CPP_W_KEYWORD_MACRO,
+                        "undefining keyword %qs", NODE_NAME (node));
+         diagnosed = true;
+       }
       /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified
         identifier is not currently defined as a macro name.  */
       if (cpp_macro_p (node))
        {
          if (node->flags & NODE_WARN)
-           cpp_error (pfile, CPP_DL_WARNING,
-                      "undefining %qs", NODE_NAME (node));
+           {
+             if (!diagnosed)
+               cpp_error (pfile, CPP_DL_WARNING,
+                          "undefining %qs", NODE_NAME (node));
+           }
          else if (cpp_builtin_macro_p (node)
                   && CPP_OPTION (pfile, warn_builtin_macro_redefined))
            cpp_warning (pfile, CPP_W_BUILTIN_MACRO_REDEFINED,
index 75efdcd55d5a3b454914742957c39174925a5207..bbd88e56f585e432120766d007917de4a5861680 100644 (file)
@@ -620,6 +620,9 @@ struct cpp_options
   /* True if -finput-charset= option has been used explicitly.  */
   bool cpp_input_charset_explicit;
 
+  /* True if -Wkeyword-macro.  */
+  bool cpp_warn_keyword_macro;
+
   /* -Wleading-whitespace= value.  */
   unsigned char cpp_warn_leading_whitespace;
 
@@ -757,7 +760,8 @@ enum cpp_warning_reason {
   CPP_W_HEADER_GUARD,
   CPP_W_PRAGMA_ONCE_OUTSIDE_HEADER,
   CPP_W_LEADING_WHITESPACE,
-  CPP_W_TRAILING_WHITESPACE
+  CPP_W_TRAILING_WHITESPACE,
+  CPP_W_KEYWORD_MACRO
 };
 
 /* Callback for header lookup for HEADER, which is the name of a
@@ -1250,6 +1254,17 @@ inline bool cpp_fun_like_macro_p (cpp_hashnode *node)
   return cpp_user_macro_p (node) && node->value.macro->fun_like;
 }
 
+/* Return true for nodes marked for -Wkeyword-macro diagnostics.  */
+inline bool cpp_keyword_p (cpp_hashnode *node)
+{
+  /* As keywords are marked identifiers which don't start with underscore
+     or start with underscore followed by capital letter (except for
+     _Pragma).  */
+  return ((node->flags & NODE_WARN)
+         && (NODE_NAME (node)[0] != '_'
+             || (NODE_NAME (node)[1] != '_' && NODE_NAME (node)[1] != 'P')));
+}
+
 extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *);
 extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *,
                                                  const cpp_macro *);
index 158c8215e52261d59e9f67fb9f3955980b6028a9..a47e1feb82078cebf17c3ec5d621411e14f9f60e 100644 (file)
@@ -3411,7 +3411,11 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node,
 {
   /* Some redefinitions need to be warned about regardless.  */
   if (node->flags & NODE_WARN)
-    return true;
+    {
+      /* Ignore NODE_WARN on -Wkeyword-macro registered identifiers though.  */
+      if (!CPP_OPTION (pfile, cpp_warn_keyword_macro) || !cpp_keyword_p (node))
+       return true;
+    }
 
   /* Suppress warnings for builtins that lack the NODE_WARN flag,
      unless Wbuiltin-macro-redefined.  */
@@ -3949,6 +3953,25 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node,
   if (name_loc)
     macro->line = name_loc;
 
+  /* Handle -Wkeyword-macro registered identifiers.  */
+  if (CPP_OPTION (pfile, cpp_warn_keyword_macro) && cpp_keyword_p (node))
+    {
+      if (macro->fun_like
+         && CPP_OPTION (pfile, cplusplus)
+         && (strcmp ((const char *) NODE_NAME (node), "likely") == 0
+             || strcmp ((const char *) NODE_NAME (node), "unlikely") == 0))
+       /* likely and unlikely can be defined as function-like macros.  */;
+      else if (CPP_OPTION (pfile, cpp_pedantic)
+              && CPP_OPTION (pfile, cplusplus)
+              && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)
+       cpp_pedwarning_with_line (pfile, CPP_W_KEYWORD_MACRO, macro->line, 0,
+                                 "keyword %qs defined as macro",
+                                 NODE_NAME (node));
+      else
+       cpp_warning_with_line (pfile, CPP_W_KEYWORD_MACRO, macro->line, 0,
+                              "keyword %qs defined as macro",
+                              NODE_NAME (node));
+    }
   if (cpp_macro_p (node))
     {
       if (CPP_OPTION (pfile, warn_unused_macros))
@@ -3957,12 +3980,12 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node,
       if (warn_of_redefinition (pfile, node, macro))
        {
           const enum cpp_warning_reason reason
-           = (cpp_builtin_macro_p (node) && !(node->flags & NODE_WARN))
-           ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE;
+           = (cpp_builtin_macro_p (node) && !(node->flags & NODE_WARN)
+              ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE);
 
          bool warned
-           =  cpp_pedwarning_with_line (pfile, reason, macro->line, 0,
-                                        "%qs redefined", NODE_NAME (node));
+           = cpp_pedwarning_with_line (pfile, reason, macro->line, 0,
+                                       "%qs redefined", NODE_NAME (node));
 
          if (warned && cpp_user_macro_p (node))
            cpp_error_with_line (pfile, CPP_DL_NOTE, node->value.macro->line,