diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -80,6 +80,10 @@ InGroup, DefaultIgnore; def warn_cxx20_keyword : Warning<"'%0' is a keyword in C++20">, InGroup, DefaultIgnore; +def warn_c99_keyword : Warning<"'%0' is a keyword in C99">, + InGroup, DefaultIgnore; +def warn_c23_keyword : Warning<"'%0' is a keyword in C23">, + InGroup, DefaultIgnore; def ext_unterminated_char_or_string : ExtWarn< "missing terminating %select{'|'\"'}0 character">, InGroup; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -79,6 +79,12 @@ #ifndef PRAGMA_ANNOTATION #define PRAGMA_ANNOTATION(X) ANNOTATION(X) #endif +#ifndef C99_KEYWORD +#define C99_KEYWORD(X,Y) KEYWORD(X,KEYC99|(Y)) +#endif +#ifndef C23_KEYWORD +#define C23_KEYWORD(X,Y) KEYWORD(X,KEYC23|(Y)) +#endif //===----------------------------------------------------------------------===// // Preprocessor keywords. @@ -250,6 +256,7 @@ // always be treated as a keyword // KEYC99 - This is a keyword introduced to C in C99 // KEYC11 - This is a keyword introduced to C in C11 +// KEYC23 - This is a keyword introduced to C in C23 // KEYCXX - This is a C++ keyword, or a C++-specific keyword in the // implementation namespace // KEYNOCXX - This is a keyword in every non-C++ dialect. @@ -291,13 +298,11 @@ KEYWORD(for , KEYALL) KEYWORD(goto , KEYALL) KEYWORD(if , KEYALL) -KEYWORD(inline , KEYC99|KEYCXX|KEYGNU) KEYWORD(int , KEYALL) KEYWORD(_ExtInt , KEYALL) KEYWORD(_BitInt , KEYALL) KEYWORD(long , KEYALL) KEYWORD(register , KEYALL) -KEYWORD(restrict , KEYC99) KEYWORD(return , KEYALL) KEYWORD(short , KEYALL) KEYWORD(signed , KEYALL) @@ -328,7 +333,6 @@ // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) -KEYWORD(bool , BOOLSUPPORT) KEYWORD(catch , KEYCXX) KEYWORD(class , KEYCXX) KEYWORD(const_cast , KEYCXX) @@ -336,7 +340,6 @@ KEYWORD(dynamic_cast , KEYCXX) KEYWORD(explicit , KEYCXX) KEYWORD(export , KEYCXX) -KEYWORD(false , BOOLSUPPORT) KEYWORD(friend , KEYCXX) KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) @@ -350,7 +353,6 @@ KEYWORD(template , KEYCXX) KEYWORD(this , KEYCXX) KEYWORD(throw , KEYCXX) -KEYWORD(true , BOOLSUPPORT) KEYWORD(try , KEYCXX) KEYWORD(typename , KEYCXX) KEYWORD(typeid , KEYCXX) @@ -371,18 +373,28 @@ CXX_KEYWORD_OPERATOR(xor , caret) CXX_KEYWORD_OPERATOR(xor_eq , caretequal) +// C99 Keywords. +C99_KEYWORD(restrict , 0) +C99_KEYWORD(inline , KEYCXX|KEYGNU) + +// C23 Keywords. +C23_KEYWORD(bool , BOOLSUPPORT) +C23_KEYWORD(false , BOOLSUPPORT) +C23_KEYWORD(true , BOOLSUPPORT) +C23_KEYWORD(remove_quals , 0) + // C++11 keywords -CXX11_KEYWORD(alignas , 0) +CXX11_KEYWORD(alignas , KEYC23) // alignof and _Alignof return the required ABI alignment -CXX11_UNARY_EXPR_OR_TYPE_TRAIT(alignof, AlignOf, 0) +CXX11_UNARY_EXPR_OR_TYPE_TRAIT(alignof, AlignOf, KEYC23) CXX11_KEYWORD(char16_t , KEYNOMS18) CXX11_KEYWORD(char32_t , KEYNOMS18) CXX11_KEYWORD(constexpr , 0) CXX11_KEYWORD(decltype , 0) CXX11_KEYWORD(noexcept , 0) CXX11_KEYWORD(nullptr , 0) -CXX11_KEYWORD(static_assert , KEYMSCOMPAT) -CXX11_KEYWORD(thread_local , 0) +CXX11_KEYWORD(static_assert , KEYMSCOMPAT|KEYC23) +CXX11_KEYWORD(thread_local , KEYC23) // C++20 / coroutines TS keywords COROUTINES_KEYWORD(co_await) @@ -444,7 +456,7 @@ KEYWORD(__auto_type , KEYALL) // GNU Extensions (outside impl-reserved namespace) -KEYWORD(typeof , KEYGNU) +KEYWORD(typeof , KEYGNU|KEYC23) // MS Extensions KEYWORD(__FUNCDNAME__ , KEYMS) @@ -933,3 +945,5 @@ #undef KEYWORD #undef PUNCTUATOR #undef TOK +#undef C99_KEYWORD +#undef C23_KEYWORD diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -107,7 +107,8 @@ KEYOPENCLCXX = 0x200000, KEYMSCOMPAT = 0x400000, KEYSYCL = 0x800000, - KEYCUDA = 0x1000000, + KEYC23 = 0x1000000, + KEYCUDA = 0x2000000, KEYMAX = KEYCUDA, // The maximum key KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20, KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 & @@ -140,15 +141,17 @@ switch (Flag) { case KEYC99: - // FIXME: This should have KS_Future logic here, but that can only happen if - // getFutureCompatDiagKind ALSO gets updated. This is safe, since C mode is - // ALWAYS implied. - return LangOpts.C99 ? KS_Enabled : KS_Unknown; + if(LangOpts.C99) + return KS_Enabled; + return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown; case KEYC11: - // FIXME: This should have KS_Future logic here, but that can only happen if - // getFutureCompatDiagKind ALSO gets updated. This is safe, since C mode is - // ALWAYS implied. - return LangOpts.C11 ? KS_Enabled : KS_Unknown; + if(LangOpts.C11) + return KS_Enabled; + return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown; + case KEYC23: + if (LangOpts.C2x) + return KS_Enabled; + return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown; case KEYCXX: return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown; case KEYCXX11: diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -792,6 +792,14 @@ .Case("char8_t", diag::warn_cxx20_keyword) ; + if (!LangOpts.CPlusPlus) + return llvm::StringSwitch(II.getName()) +#define C99_KEYWORD(NAME, FLAGS) .Case(#NAME, diag::warn_c99_keyword) +#define C23_KEYWORD(NAME, FLAGS) .Case(#NAME, diag::warn_c23_keyword) +#define CXX11_KEYWORD(NAME, FLAGS) .Case(#NAME, diag::warn_c23_keyword) +#include "clang/Basic/TokenKinds.def" + .Case("typeof", diag::warn_c23_keyword); + llvm_unreachable( "Keyword not known to come from a newer Standard or proposed Standard"); }