aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorMuhammad Usman Shahid <codesbyusman@gmail.com>2022-08-26 09:17:14 -0400
committerAaron Ballman <aaron@aaronballman.com>2022-08-26 09:20:05 -0400
commit41667a8b9b624e282e7c08fadf7091223728d1c1 (patch)
treefd845d5f127d655f70888e733fe832ad70e77534 /clang/lib
parent5af06ba7dc26f614989a9a9e16e69f6ecc811519 (diff)
downloadllvm-41667a8b9b624e282e7c08fadf7091223728d1c1.zip
llvm-41667a8b9b624e282e7c08fadf7091223728d1c1.tar.gz
llvm-41667a8b9b624e282e7c08fadf7091223728d1c1.tar.bz2
Diagnosing the Future Keywords
The patch diagnoses an identifier as a future keyword if it exists in a future language mode, such as: int restrict; in C modes earlier than C99. We now give a warning to the user that such an identifier is a future keyword. Handles keywords from C as well as C++. Differential Revision: https://reviews.llvm.org/D131683
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/IdentifierTable.cpp89
-rw-r--r--clang/lib/Lex/Preprocessor.cpp25
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp9
3 files changed, 64 insertions, 59 deletions
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index 06f0850..5d413a8 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -88,26 +88,25 @@ namespace {
KEYCXX11 = 0x4,
KEYGNU = 0x8,
KEYMS = 0x10,
- BOOLSUPPORT = 0x20,
- KEYALTIVEC = 0x40,
- KEYNOCXX = 0x80,
- KEYBORLAND = 0x100,
- KEYOPENCLC = 0x200,
- KEYC11 = 0x400,
- KEYNOMS18 = 0x800,
- KEYNOOPENCL = 0x1000,
- WCHARSUPPORT = 0x2000,
- HALFSUPPORT = 0x4000,
- CHAR8SUPPORT = 0x8000,
- KEYOBJC = 0x10000,
- KEYZVECTOR = 0x20000,
- KEYCOROUTINES = 0x40000,
- KEYMODULES = 0x80000,
- KEYCXX20 = 0x100000,
- KEYOPENCLCXX = 0x200000,
- KEYMSCOMPAT = 0x400000,
- KEYSYCL = 0x800000,
- KEYCUDA = 0x1000000,
+ KEYALTIVEC = 0x20,
+ KEYNOCXX = 0x40,
+ KEYBORLAND = 0x80,
+ KEYOPENCLC = 0x100,
+ KEYC2X = 0x200,
+ KEYNOMS18 = 0x400,
+ KEYNOOPENCL = 0x800,
+ WCHARSUPPORT = 0x1000,
+ HALFSUPPORT = 0x2000,
+ CHAR8SUPPORT = 0x4000,
+ KEYOBJC = 0x8000,
+ KEYZVECTOR = 0x10000,
+ KEYCOROUTINES = 0x20000,
+ KEYMODULES = 0x40000,
+ KEYCXX20 = 0x80000,
+ KEYOPENCLCXX = 0x100000,
+ KEYMSCOMPAT = 0x200000,
+ KEYSYCL = 0x400000,
+ KEYCUDA = 0x800000,
KEYMAX = KEYCUDA, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
@@ -140,15 +139,13 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
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:
@@ -163,8 +160,6 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
case KEYMS:
return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
- case BOOLSUPPORT:
- return LangOpts.Bool ? KS_Enabled : KS_Unknown;
case KEYALTIVEC:
return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
case KEYBORLAND:
@@ -845,3 +840,35 @@ StringRef clang::getNullabilitySpelling(NullabilityKind kind,
}
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");
+}
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 8c4859d..6af415a 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -773,29 +773,6 @@ void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) {
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 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
// 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);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 4510ff8..d0bf897 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -935,10 +935,11 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
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);
}