From: Jakub Jelinek Date: Thu, 7 Aug 2025 06:47:44 +0000 (+0200) Subject: c++, c: Introduce -Wkeyword-macro warning/pedwarn - part of C++26 P2843R3 [PR120778] X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=64859dc6e2948616439b500b5d9ffb2635b45ae8;p=thirdparty%2Fgcc.git c++, c: Introduce -Wkeyword-macro warning/pedwarn - part of C++26 P2843R3 [PR120778] 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 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. --- diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 7c7e21d2d0e..009c8ef65a6 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -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 diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index c652e82a8c7..3fb12b984f2 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -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. */ diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 12877eb0e17..0ee2c302c0f 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -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. diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls index 5c97593d703..6eb117848b4 100644 --- a/gcc/c-family/c.opt.urls +++ b/gcc/c-family/c.opt.urls @@ -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) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7850365f35c..8e8bac6c32b 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -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 diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc index 08a634830f5..b7d2ac62b17 100644 --- a/gcc/cp/lex.cc +++ b/gcc/cp/lex.cc @@ -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; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 00468a72ada..33ae98c40af 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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)} diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-3.C b/gcc/testsuite/g++.dg/modules/atom-preamble-3.C index 74dba7d23a6..915fa743a48 100644 --- a/gcc/testsuite/g++.dg/modules/atom-preamble-3.C +++ b/gcc/testsuite/g++.dg/modules/atom-preamble-3.C @@ -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 } diff --git a/gcc/testsuite/g++.dg/opt/pr82577.C b/gcc/testsuite/g++.dg/opt/pr82577.C index 1a06897a403..8a4f36d37ea 100644 --- a/gcc/testsuite/g++.dg/opt/pr82577.C +++ b/gcc/testsuite/g++.dg/opt/pr82577.C @@ -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); diff --git a/gcc/testsuite/g++.dg/template/sfinae17.C b/gcc/testsuite/g++.dg/template/sfinae17.C index eb043cbddfb..8628726c192 100644 --- a/gcc/testsuite/g++.dg/template/sfinae17.C +++ b/gcc/testsuite/g++.dg/template/sfinae17.C @@ -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 int main() { - static_assert(sizeof f(0) == sizeof(two), ""); - static_assert(sizeof f(0) == sizeof(two), ""); + my_static_assert(sizeof f(0) == sizeof(two), ""); + my_static_assert(sizeof f(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 index 00000000000..f47de7af26a --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C @@ -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 index 00000000000..e6fafcd1a30 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C @@ -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 index 00000000000..b1a9aa2cd6a --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C @@ -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 index 00000000000..8576b649fc1 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C @@ -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 index 00000000000..9ff974dfc1e --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C @@ -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 index 00000000000..657797b5603 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C @@ -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 index 00000000000..881df8b3075 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C @@ -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 index 00000000000..30a2c8d50e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C @@ -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 index 00000000000..7dcc37716d8 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C @@ -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 index 00000000000..741cdee6840 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C @@ -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 index 00000000000..0b2d78ff84f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-1.c @@ -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 index 00000000000..329a55ab967 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-2.c @@ -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 index 00000000000..f631b8ef38b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-3.c @@ -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 index 00000000000..796d654245e --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-4.c @@ -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 index 00000000000..c61a1ce355b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-5.c @@ -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 index 00000000000..760ece6be85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-6.c @@ -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 index 00000000000..dc146d4a7f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-7.c @@ -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 index 00000000000..b209f402d1b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-8.c @@ -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 index 00000000000..5d6b650cd8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-9.c @@ -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" } diff --git a/libcpp/directives.cc b/libcpp/directives.cc index 4d06caa9b56..47fb8fbdd13 100644 --- a/libcpp/directives.cc +++ b/libcpp/directives.cc @@ -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, diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 75efdcd55d5..bbd88e56f58 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -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 *); diff --git a/libcpp/macro.cc b/libcpp/macro.cc index 158c8215e52..a47e1feb820 100644 --- a/libcpp/macro.cc +++ b/libcpp/macro.cc @@ -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,