From: Richard Smith Date: Thu, 14 May 2015 04:00:59 +0000 (+0000) Subject: Generalize future keyword compat diagnostics. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58123c9b060c461f17956d6dc0b0c9bc9fc90af0;p=clang Generalize future keyword compat diagnostics. This, in preparation for the introduction of more new keywords in the implementation of the C++ language, generalizes the support for future keyword compat diagnostics (e.g., diag::warn_cxx11_keyword) by extending the applicability of the relevant property in IdentifierTable with appropriate renaming. Patch by Hubert Tong! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237332 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index dc9983dd3c..bc586e41f8 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -53,7 +53,8 @@ class IdentifierInfo { bool HasMacro : 1; // True if there is a #define for this. bool HadMacro : 1; // True if there was a #define for this. bool IsExtension : 1; // True if identifier is a lang extension. - bool IsCXX11CompatKeyword : 1; // True if identifier is a keyword in C++11. + bool IsFutureCompatKeyword : 1; // True if identifier is a keyword in a + // newer Standard or proposed Standard. bool IsPoisoned : 1; // True if identifier is poisoned. bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". @@ -213,13 +214,14 @@ public: RecomputeNeedsHandleIdentifier(); } - /// is/setIsCXX11CompatKeyword - Initialize information about whether or not - /// this language token is a keyword in C++11. This controls compatibility - /// warnings, and is only true when not parsing C++11. Once a compatibility - /// problem has been diagnosed with this keyword, the flag will be cleared. - bool isCXX11CompatKeyword() const { return IsCXX11CompatKeyword; } - void setIsCXX11CompatKeyword(bool Val) { - IsCXX11CompatKeyword = Val; + /// is/setIsFutureCompatKeyword - Initialize information about whether or not + /// this language token is a keyword in a newer or proposed Standard. This + /// controls compatibility warnings, and is only true when not parsing the + /// corresponding Standard. Once a compatibility problem has been diagnosed + /// with this keyword, the flag will be cleared. + bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; } + void setIsFutureCompatKeyword(bool Val) { + IsFutureCompatKeyword = Val; if (Val) NeedsHandleIdentifier = 1; else @@ -325,7 +327,7 @@ private: void RecomputeNeedsHandleIdentifier() { NeedsHandleIdentifier = (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() | - isExtensionToken() | isCXX11CompatKeyword() || isOutOfDate() || + isExtensionToken() | isFutureCompatKeyword() || isOutOfDate() || isModulesImport()); } }; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index f33561ba42..45809b88ef 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -10,7 +10,7 @@ // This file defines the TokenKind database. This includes normal tokens like // tok::ampamp (corresponding to the && token) as well as keywords for various // languages. Users of this file must optionally #define the TOK, KEYWORD, -// ALIAS, or PPKEYWORD macros to make use of this file. +// CXX11_KEYWORD, ALIAS, or PPKEYWORD macros to make use of this file. // //===----------------------------------------------------------------------===// @@ -23,6 +23,9 @@ #ifndef KEYWORD #define KEYWORD(X,Y) TOK(kw_ ## X) #endif +#ifndef CXX11_KEYWORD +#define CXX11_KEYWORD(X,Y) KEYWORD(X,KEYCXX11|(Y)) +#endif #ifndef TYPE_TRAIT #define TYPE_TRAIT(N,I,K) KEYWORD(I,K) #endif @@ -330,16 +333,16 @@ CXX_KEYWORD_OPERATOR(xor , caret) CXX_KEYWORD_OPERATOR(xor_eq , caretequal) // C++11 keywords -KEYWORD(alignas , KEYCXX11) -KEYWORD(alignof , KEYCXX11) -KEYWORD(char16_t , KEYCXX11|KEYNOMS18) -KEYWORD(char32_t , KEYCXX11|KEYNOMS18) -KEYWORD(constexpr , KEYCXX11) -KEYWORD(decltype , KEYCXX11) -KEYWORD(noexcept , KEYCXX11) -KEYWORD(nullptr , KEYCXX11) -KEYWORD(static_assert , KEYCXX11) -KEYWORD(thread_local , KEYCXX11) +CXX11_KEYWORD(alignas , 0) +CXX11_KEYWORD(alignof , 0) +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 , 0) +CXX11_KEYWORD(thread_local , 0) // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) @@ -735,6 +738,7 @@ ANNOTATION(module_end) #undef TYPE_TRAIT_2 #undef TYPE_TRAIT_1 #undef TYPE_TRAIT +#undef CXX11_KEYWORD #undef KEYWORD #undef PUNCTUATOR #undef TOK diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 0a27c6a889..629b236eee 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -35,7 +35,7 @@ IdentifierInfo::IdentifierInfo() { HasMacro = false; HadMacro = false; IsExtension = false; - IsCXX11CompatKeyword = false; + IsFutureCompatKeyword = false; IsPoisoned = false; IsCPPOperatorKeyword = false; NeedsHandleIdentifier = false; @@ -170,7 +170,7 @@ static void AddKeyword(StringRef Keyword, IdentifierInfo &Info = Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode); Info.setIsExtensionToken(AddResult == KS_Extension); - Info.setIsCXX11CompatKeyword(AddResult == KS_Future); + Info.setIsFutureCompatKeyword(AddResult == KS_Future); } /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 87e6b5251c..9e89497597 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -584,6 +584,23 @@ void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) { Diag(Identifier,it->second) << Identifier.getIdentifierInfo(); } +/// \brief 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(II.getName()) +#define CXX11_KEYWORD(NAME, FLAGS) \ + .Case(#NAME, diag::warn_cxx11_keyword) +#include "clang/Basic/TokenKinds.def" + ; + + llvm_unreachable( + "Keyword not known to come from a newer Standard or proposed Standard"); +} + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or /// potentially macro expands it or turns it into a named token (like 'for'). @@ -642,15 +659,16 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { } } - // If this identifier is a keyword in C++11, produce a warning. Don't warn if - // we're not considering macro expansion, since this identifier might be the - // name of a macro. + // If this identifier is a keyword in a newer Standard or proposed Standard, + // produce a warning. Don't warn if we're not considering macro expansion, + // since this identifier might be the name of a macro. // FIXME: This warning is disabled in cases where it shouldn't be, like // "#define constexpr constexpr", "int constexpr;" - if (II.isCXX11CompatKeyword() && !DisableMacroExpansion) { - Diag(Identifier, diag::warn_cxx11_keyword) << II.getName(); + if (II.isFutureCompatKeyword() && !DisableMacroExpansion) { + Diag(Identifier, getFutureCompatDiagKind(II, getLangOpts())) + << II.getName(); // Don't diagnose this keyword again in this translation unit. - II.setIsCXX11CompatKeyword(false); + II.setIsFutureCompatKeyword(false); } // C++ 2.11p2: If this is an alternative representation of a C++ operator,