Codesbyusman updated this revision to Diff 455607.
Codesbyusman added a comment.
updated
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D131683/new/
https://reviews.llvm.org/D131683
Files:
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticLexKinds.td
clang/include/clang/Basic/IdentifierTable.h
clang/include/clang/Basic/TokenKinds.def
clang/lib/Basic/IdentifierTable.cpp
clang/lib/Lex/Preprocessor.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/test/Lexer/keywords_test.c
clang/test/Lexer/keywords_test.cpp
clang/test/Parser/static_assert.c
Index: clang/test/Parser/static_assert.c
===================================================================
--- clang/test/Parser/static_assert.c
+++ clang/test/Parser/static_assert.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c2x -DTEST_SPELLING -verify=c2x %s
-// RUN: %clang_cc1 -fsyntax-only -std=c2x -DTEST_SPELLING -fms-compatibility -verify=c2x-ms %s
+// RUN: %clang_cc1 -fsyntax-only -std=c17 -DTEST_SPELLING -Wc2x-compat -verify=c17 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c17 -DTEST_SPELLING -fms-compatibility -verify=c17-ms %s
// RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x-compat %s
// RUN: %clang_cc1 -fsyntax-only -std=c99 -verify=c99 %s
// RUN: %clang_cc1 -fsyntax-only -std=c99 -pedantic -verify=c99-pedantic %s
@@ -15,11 +15,13 @@
// Only test the C++ spelling in C mode in some of the tests, to reduce the
// amount of diagnostics to have to check. This spelling is allowed in MS-
// compatibility mode in C, but otherwise produces errors.
-static_assert(1, ""); // c2x-error {{expected parameter declarator}} \
- // c2x-error {{expected ')'}} \
- // c2x-note {{to match this '('}} \
- // c2x-error {{a type specifier is required for all declarations}} \
- // c2x-ms-warning {{use of 'static_assert' without inclusion of <assert.h> is a Microsoft extension}}
+static_assert(1, ""); // c17-warning {{'static_assert' is a keyword in C2x}} \
+ // c17-error {{expected parameter declarator}} \
+ // c17-error {{expected ')'}} \
+ // c17-note {{to match this '('}} \
+ // c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \
+ // c17-ms-warning {{use of 'static_assert' without inclusion of <assert.h> is a Microsoft extension}}
+
#endif
// We support _Static_assert as an extension in older C modes and in all C++
@@ -42,4 +44,7 @@
// cxx17-compat-warning {{'static_assert' with no message is incompatible with C++ standards before C++17}} \
// c99-pedantic-warning {{'_Static_assert' is a C11 extension}} \
// cxx17-pedantic-warning {{'_Static_assert' is a C11 extension}} \
- // cxx98-pedantic-warning {{'_Static_assert' is a C11 extension}}
+ // cxx98-pedantic-warning {{'_Static_assert' is a C11 extension}} \
+ // c17-warning {{'_Static_assert' with no message is a C2x extension}} \
+ // c17-ms-warning {{'_Static_assert' with no message is a C2x extension}}
+
Index: clang/test/Lexer/keywords_test.cpp
===================================================================
--- clang/test/Lexer/keywords_test.cpp
+++ clang/test/Lexer/keywords_test.cpp
@@ -15,6 +15,8 @@
// RUN: %clang -std=c++03 -target i686-windows-msvc -DMS -fno-declspec -fsyntax-only %s
// RUN: %clang -std=c++03 -target x86_64-scei-ps4 -fno-declspec -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++98 -DFutureKeyword -fsyntax-only -Wc++11-compat -Wc++20-compat -verify=cxx98 %s
+
#define IS_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
#define NOT_KEYWORD(NAME) _Static_assert(__is_identifier(NAME), #NAME)
#define IS_TYPE(NAME) void is_##NAME##_type() { int f(NAME); }
@@ -50,17 +52,24 @@
CXX11_TYPE(char32_t);
CXX11_KEYWORD(constexpr);
CXX11_KEYWORD(noexcept);
+
#ifndef MS
CXX11_KEYWORD(static_assert);
#else
// MS compiler recognizes static_assert in all modes. So should we.
IS_KEYWORD(static_assert);
#endif
+
CXX11_KEYWORD(thread_local);
// Concepts keywords
CXX20_KEYWORD(concept);
CXX20_KEYWORD(requires);
+CXX20_KEYWORD(consteval);
+CXX20_KEYWORD(constinit);
+CXX20_KEYWORD(co_await);
+CXX20_KEYWORD(co_return);
+CXX20_KEYWORD(co_yield);
// __declspec extension
DECLSPEC_KEYWORD(__declspec);
@@ -70,3 +79,26 @@
IS_TYPE(__char16_t);
IS_KEYWORD(__char32_t);
IS_TYPE(__char32_t);
+
+#ifdef FutureKeyword
+
+int nullptr; // cxx98-warning {{'nullptr' is a keyword in C++11}}
+int decltype; // cxx98-warning {{'decltype' is a keyword in C++11}}
+int alignof; // cxx98-warning {{'alignof' is a keyword in C++11}}
+int alignas; // cxx98-warning {{'alignas' is a keyword in C++11}}
+int char16_t; // cxx98-warning {{'char16_t' is a keyword in C++11}}
+int char32_t; // cxx98-warning {{'char32_t' is a keyword in C++11}}
+int constexpr; // cxx98-warning {{'constexpr' is a keyword in C++11}}
+int noexcept; // cxx98-warning {{'noexcept' is a keyword in C++11}}
+int static_assert; // cxx98-warning {{'static_assert' is a keyword in C++11}}
+char thread_local; // cxx98-warning {{'thread_local' is a keyword in C++11}}
+
+int co_await; // cxx98-warning {{'co_await' is a keyword in C++20}}
+char co_return; // cxx98-warning {{'co_return' is a keyword in C++20}}
+char co_yield; // cxx98-warning {{'co_yield' is a keyword in C++20}}
+int constinit; // cxx98-warning {{'constinit' is a keyword in C++20}}
+int consteval; // cxx98-warning {{'consteval' is a keyword in C++20}}
+int requires; // cxx98-warning {{'requires' is a keyword in C++20}}
+int concept; // cxx98-warning {{'concept' is a keyword in C++20}}
+
+#endif
Index: clang/test/Lexer/keywords_test.c
===================================================================
--- clang/test/Lexer/keywords_test.c
+++ clang/test/Lexer/keywords_test.c
@@ -14,6 +14,40 @@
// RUN: %clang_cc1 -std=c99 -fms-extensions -fno-declspec -E %s -o - \
// RUN: | FileCheck --check-prefix=CHECK-MS-KEYWORDS-WITHOUT-DECLSPEC %s
+// RUN: %clang_cc1 -std=c99 -DC99 -fsyntax-only %s
+// RUN: %clang_cc1 -std=c2x -DC99 -DC2x -fsyntax-only %s
+
+// RUN: %clang_cc1 -fsyntax-only -std=c89 -DFutureKeyword -Wc2x-compat -Wc99-compat -verify=c89 %s
+
+#define IS_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
+#define NOT_KEYWORD(NAME) _Static_assert(__is_identifier(NAME), #NAME)
+
+#if defined(C99)
+#define C99_KEYWORD(NAME) IS_KEYWORD(NAME)
+#else
+#define C99_KEYWORD(NAME) NOT_KEYWORD(NAME)
+#endif
+
+#if defined(C2x)
+#define C2x_KEYWORD(NAME) IS_KEYWORD(NAME)
+#else
+#define C2x_KEYWORD(NAME) NOT_KEYWORD(NAME)
+#endif
+
+// C99 Keywords.
+C99_KEYWORD(restrict);
+C99_KEYWORD(inline);
+
+// C2x Keywords.
+C2x_KEYWORD(bool);
+C2x_KEYWORD(true);
+C2x_KEYWORD(false);
+C2x_KEYWORD(static_assert);
+C2x_KEYWORD(typeof);
+C2x_KEYWORD(thread_local);
+C2x_KEYWORD(alignas);
+C2x_KEYWORD(alignof);
+
void f() {
// CHECK-NONE: int asm
// CHECK-GNU-KEYWORDS: asm ("ret" : :)
@@ -52,3 +86,18 @@
#else
void has_static_assert();
#endif
+
+#ifdef FutureKeyword
+
+ int restrict; // c89-warning {{'restrict' is a keyword in C99}}
+ int inline; // c89-warning {{'inline' is a keyword in C99}}
+
+ int bool; // c89-warning {{'bool' is a keyword in C2x}}
+ char true; // c89-warning {{'true' is a keyword in C2x}}
+ char false; // c89-warning {{'false' is a keyword in C2x}}
+ float alignof; // c89-warning {{'alignof' is a keyword in C2x}}
+ int typeof; // c89-warning {{'typeof' is a keyword in C2x}}
+ int alignas; // c89-warning {{'alignas' is a keyword in C2x}}
+ int static_assert; // c89-warning {{'static_assert' is a keyword in C2x}}
+
+#endif
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -934,10 +934,11 @@
if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
if (Tok.is(tok::kw_static_assert)) {
- if (!getLangOpts().CPlusPlus)
- Diag(Tok, diag::ext_ms_static_assert)
- << FixItHint::CreateReplacement(Tok.getLocation(), "_Static_assert");
- else
+ if (!getLangOpts().CPlusPlus) {
+ if (!getLangOpts().C2x)
+ Diag(Tok, diag::ext_ms_static_assert) << FixItHint::CreateReplacement(
+ Tok.getLocation(), "_Static_assert");
+ } else
Diag(Tok, diag::warn_cxx98_compat_static_assert);
}
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -773,29 +773,6 @@
Diag(Identifier,it->second) << Identifier.getIdentifierInfo();
}
-/// Returns a diagnostic message kind for reporting a future keyword as
-/// appropriate for the identifier and specified language.
-static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
- const LangOptions &LangOpts) {
- assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
-
- if (LangOpts.CPlusPlus)
- return llvm::StringSwitch<diag::kind>(II.getName())
-#define CXX11_KEYWORD(NAME, FLAGS) \
- .Case(#NAME, diag::warn_cxx11_keyword)
-#define CXX20_KEYWORD(NAME, FLAGS) \
- .Case(#NAME, diag::warn_cxx20_keyword)
-#include "clang/Basic/TokenKinds.def"
- // char8_t is not modeled as a CXX20_KEYWORD because it's not
- // unconditionally enabled in C++20 mode. (It can be disabled
- // by -fno-char8_t.)
- .Case("char8_t", diag::warn_cxx20_keyword)
- ;
-
- llvm_unreachable(
- "Keyword not known to come from a newer Standard or proposed Standard");
-}
-
void Preprocessor::updateOutOfDateIdentifier(IdentifierInfo &II) const {
assert(II.isOutOfDate() && "not out of date");
getExternalSource()->updateOutOfDateIdentifier(II);
@@ -867,7 +844,7 @@
// FIXME: This warning is disabled in cases where it shouldn't be, like
// "#define constexpr constexpr", "int constexpr;"
if (II.isFutureCompatKeyword() && !DisableMacroExpansion) {
- Diag(Identifier, getFutureCompatDiagKind(II, getLangOpts()))
+ Diag(Identifier, getIdentifierTable().getFutureCompatDiagKind(II, getLangOpts()))
<< II.getName();
// Don't diagnose this keyword again in this translation unit.
II.setIsFutureCompatKeyword(false);
Index: clang/lib/Basic/IdentifierTable.cpp
===================================================================
--- clang/lib/Basic/IdentifierTable.cpp
+++ clang/lib/Basic/IdentifierTable.cpp
@@ -93,7 +93,7 @@
KEYNOCXX = 0x80,
KEYBORLAND = 0x100,
KEYOPENCLC = 0x200,
- KEYC11 = 0x400,
+ KEYC2X = 0x400,
KEYNOMS18 = 0x800,
KEYNOOPENCL = 0x1000,
WCHARSUPPORT = 0x2000,
@@ -140,15 +140,13 @@
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;
- 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.C99)
+ return KS_Enabled;
+ return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
+ case KEYC2X:
+ if (LangOpts.C2x)
+ return KS_Enabled;
+ return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
case KEYCXX:
return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
case KEYCXX11:
@@ -845,3 +843,35 @@
}
llvm_unreachable("Unknown nullability kind.");
}
+
+diag::kind
+IdentifierTable::getFutureCompatDiagKind(const IdentifierInfo &II,
+ const LangOptions &LangOpts) {
+ assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
+
+ unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())
+#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
+#include "clang/Basic/TokenKinds.def"
+#undef KEYWORD
+ ;
+
+ if (LangOpts.CPlusPlus) {
+ if ((Flags & KEYCXX11) == KEYCXX11)
+ return diag::warn_cxx11_keyword;
+
+ // char8_t is not modeled as a CXX20_KEYWORD because it's not
+ // unconditionally enabled in C++20 mode. (It can be disabled
+ // by -fno-char8_t.)
+ if (((Flags & KEYCXX20) == KEYCXX20) ||
+ ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
+ return diag::warn_cxx20_keyword;
+ } else {
+ if ((Flags & KEYC99) == KEYC99)
+ return diag::warn_c99_keyword;
+ if ((Flags & KEYC2X) == KEYC2X)
+ return diag::warn_c2x_keyword;
+ }
+
+ llvm_unreachable(
+ "Keyword not known to come from a newer Standard or proposed Standard");
+}
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -28,6 +28,12 @@
#ifndef CXX20_KEYWORD
#define CXX20_KEYWORD(X,Y) KEYWORD(X,KEYCXX20|(Y))
#endif
+#ifndef C99_KEYWORD
+#define C99_KEYWORD(X,Y) KEYWORD(X,KEYC99|(Y))
+#endif
+#ifndef C2X_KEYWORD
+#define C2X_KEYWORD(X,Y) KEYWORD(X,KEYC2X|(Y))
+#endif
#ifndef COROUTINES_KEYWORD
#define COROUTINES_KEYWORD(X) CXX20_KEYWORD(X,KEYCOROUTINES)
#endif
@@ -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
+// KEYC2X - This is a keyword introduced to C in C2x
// 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,27 @@
CXX_KEYWORD_OPERATOR(xor , caret)
CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
+// C99 Keywords.
+C99_KEYWORD(restrict , 0)
+C99_KEYWORD(inline , KEYCXX|KEYGNU)
+
+// C23 Keywords.
+C2X_KEYWORD(bool , BOOLSUPPORT)
+C2X_KEYWORD(false , BOOLSUPPORT)
+C2X_KEYWORD(true , BOOLSUPPORT)
+
// C++11 keywords
-CXX11_KEYWORD(alignas , 0)
+CXX11_KEYWORD(alignas , KEYC2X)
// 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, KEYC2X)
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|KEYC2X)
+CXX11_KEYWORD(thread_local , KEYC2X)
// C++20 / coroutines TS keywords
COROUTINES_KEYWORD(co_await)
@@ -444,7 +455,7 @@
KEYWORD(__auto_type , KEYALL)
// GNU Extensions (outside impl-reserved namespace)
-KEYWORD(typeof , KEYGNU)
+KEYWORD(typeof , KEYGNU|KEYC2X)
// MS Extensions
KEYWORD(__FUNCDNAME__ , KEYMS)
@@ -933,3 +944,5 @@
#undef KEYWORD
#undef PUNCTUATOR
#undef TOK
+#undef C99_KEYWORD
+#undef C2X_KEYWORD
Index: clang/include/clang/Basic/IdentifierTable.h
===================================================================
--- clang/include/clang/Basic/IdentifierTable.h
+++ clang/include/clang/Basic/IdentifierTable.h
@@ -17,6 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TokenKinds.h"
+#include "clang/Lex/LexDiagnostic.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
@@ -668,6 +669,12 @@
/// Populate the identifier table with info about the language keywords
/// for the language specified by \p LangOpts.
void AddKeywords(const LangOptions &LangOpts);
+
+ /// Returns the correct diagnostic to issue for a future-compat diagnostic
+ /// warning. Note, this function assumes the identifier passed has already
+ /// been determined to be a future compatible keyword.
+ diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
+ const LangOptions &LangOpts);
};
/// A family of Objective-C methods.
Index: clang/include/clang/Basic/DiagnosticLexKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticLexKinds.td
+++ clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -80,6 +80,10 @@
InGroup<CXX11Compat>, DefaultIgnore;
def warn_cxx20_keyword : Warning<"'%0' is a keyword in C++20">,
InGroup<CXX20Compat>, DefaultIgnore;
+def warn_c99_keyword : Warning<"'%0' is a keyword in C99">,
+ InGroup<C99Compat>, DefaultIgnore;
+def warn_c2x_keyword : Warning<"'%0' is a keyword in C2x">,
+ InGroup<C2xCompat>, DefaultIgnore;
def ext_unterminated_char_or_string : ExtWarn<
"missing terminating %select{'|'\"'}0 character">, InGroup<InvalidPPToken>;
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -139,6 +139,7 @@
def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
def C99Compat : DiagGroup<"c99-compat">;
+def C2xCompat : DiagGroup<"c2x-compat">;
def CXXCompat: DiagGroup<"c++-compat">;
def ExternCCompat : DiagGroup<"extern-c-compat">;
def KeywordCompat : DiagGroup<"keyword-compat">;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits