зеркало из https://github.com/microsoft/clang.git
Add a -Wc++0x-compat warning for C++11 keywords used as identifiers when in
C++98 mode. Only the first occurrence of each keyword will produce a warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141700 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
2492c89882
Коммит
98d86b98b3
|
@ -46,6 +46,9 @@ def charize_microsoft_ext : Extension<"@# is a microsoft extension">;
|
|||
def ext_token_used : Extension<"extension used">,
|
||||
InGroup<DiagGroup<"language-extension-token">>;
|
||||
|
||||
def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
|
||||
InGroup<CXX0xCompat>;
|
||||
|
||||
def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">;
|
||||
def warn_unterminated_char : ExtWarn<"missing terminating ' character">;
|
||||
def err_empty_character : Error<"empty character constant">;
|
||||
|
|
|
@ -58,6 +58,7 @@ class IdentifierInfo {
|
|||
unsigned ObjCOrBuiltinID :11;
|
||||
bool HasMacro : 1; // True if there is 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 IsPoisoned : 1; // True if identifier is poisoned.
|
||||
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
|
||||
bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
|
||||
|
@ -199,6 +200,19 @@ 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;
|
||||
if (Val)
|
||||
NeedsHandleIdentifier = 1;
|
||||
else
|
||||
RecomputeNeedsHandleIdentifier();
|
||||
}
|
||||
|
||||
/// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the
|
||||
/// Preprocessor will emit an error every time this token is used.
|
||||
void setIsPoisoned(bool Value = true) {
|
||||
|
@ -252,7 +266,8 @@ private:
|
|||
void RecomputeNeedsHandleIdentifier() {
|
||||
NeedsHandleIdentifier =
|
||||
(isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
|
||||
isExtensionToken() || (getTokenID() == tok::kw___import_module__));
|
||||
isExtensionToken() | isCXX11CompatKeyword() ||
|
||||
(getTokenID() == tok::kw___import_module__));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -752,11 +752,11 @@ public:
|
|||
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at
|
||||
/// the specified Token's location, translating the token's start
|
||||
/// position in the current buffer into a SourcePosition object for rendering.
|
||||
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
|
||||
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const {
|
||||
return Diags->Report(Loc, DiagID);
|
||||
}
|
||||
|
||||
DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) {
|
||||
DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) const {
|
||||
return Diags->Report(Tok.getLocation(), DiagID);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ IdentifierInfo::IdentifierInfo() {
|
|||
ObjCOrBuiltinID = 0;
|
||||
HasMacro = false;
|
||||
IsExtension = false;
|
||||
IsCXX11CompatKeyword = false;
|
||||
IsPoisoned = false;
|
||||
IsCPPOperatorKeyword = false;
|
||||
NeedsHandleIdentifier = false;
|
||||
|
@ -102,10 +103,10 @@ namespace {
|
|||
/// identifiers because they are language keywords. This causes the lexer to
|
||||
/// automatically map matching identifiers to specialized token codes.
|
||||
///
|
||||
/// The C90/C99/CPP/CPP0x flags are set to 2 if the token should be
|
||||
/// enabled in the specified langauge, set to 1 if it is an extension
|
||||
/// in the specified language, and set to 0 if disabled in the
|
||||
/// specified language.
|
||||
/// The C90/C99/CPP/CPP0x flags are set to 3 if the token is a keyword in a
|
||||
/// future language standard, set to 2 if the token should be enabled in the
|
||||
/// specified langauge, set to 1 if it is an extension in the specified
|
||||
/// language, and set to 0 if disabled in the specified language.
|
||||
static void AddKeyword(StringRef Keyword,
|
||||
tok::TokenKind TokenCode, unsigned Flags,
|
||||
const LangOptions &LangOpts, IdentifierTable &Table) {
|
||||
|
@ -123,12 +124,15 @@ static void AddKeyword(StringRef Keyword,
|
|||
else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2;
|
||||
else if (LangOpts.C1X && (Flags & KEYC1X)) AddResult = 2;
|
||||
else if (LangOpts.ObjCAutoRefCount && (Flags & KEYARC)) AddResult = 2;
|
||||
|
||||
else if (LangOpts.CPlusPlus && (Flags & KEYCXX0X)) AddResult = 3;
|
||||
|
||||
// Don't add this keyword if disabled in this language.
|
||||
if (AddResult == 0) return;
|
||||
|
||||
IdentifierInfo &Info = Table.get(Keyword, TokenCode);
|
||||
IdentifierInfo &Info =
|
||||
Table.get(Keyword, AddResult == 3 ? tok::identifier : TokenCode);
|
||||
Info.setIsExtensionToken(AddResult == 1);
|
||||
Info.setIsCXX11CompatKeyword(AddResult == 3);
|
||||
}
|
||||
|
||||
/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
|
||||
|
@ -493,4 +497,3 @@ const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -513,6 +513,17 @@ void 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.
|
||||
// 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();
|
||||
// Don't diagnose this keyword again in this translation unit.
|
||||
II.setIsCXX11CompatKeyword(false);
|
||||
}
|
||||
|
||||
// C++ 2.11p2: If this is an alternative representation of a C++ operator,
|
||||
// then we act as if it is the actual operator and not the textual
|
||||
// representation of it.
|
||||
|
|
|
@ -1,3 +1,36 @@
|
|||
// RUN: %clang_cc1 %s -verify -fsyntax-only
|
||||
int static_assert;
|
||||
int char16_t;
|
||||
|
||||
#define thread_local __thread
|
||||
thread_local int x;
|
||||
#undef thread_local
|
||||
|
||||
namespace lib {
|
||||
struct nullptr_t;
|
||||
typedef nullptr_t nullptr; // expected-warning {{'nullptr' is a keyword in C++11}}
|
||||
}
|
||||
|
||||
#define CONCAT(X,Y) CONCAT2(X,Y)
|
||||
#define CONCAT2(X,Y) X ## Y
|
||||
int CONCAT(constexpr,ession);
|
||||
|
||||
#define ID(X) X
|
||||
extern int ID(decltype); // expected-warning {{'decltype' is a keyword in C++11}}
|
||||
|
||||
extern int CONCAT(align,of); // expected-warning {{'alignof' is a keyword in C++11}}
|
||||
|
||||
#define static_assert(b, s) int CONCAT(check, __LINE__)[(b) ? 1 : 0];
|
||||
static_assert(1 > 0, "hello"); // ok
|
||||
|
||||
#define IF_CXX11(CXX11, CXX03) CXX03
|
||||
typedef IF_CXX11(char16_t, wchar_t) my_wide_char_t; // ok
|
||||
|
||||
int alignas; // expected-warning {{'alignas' is a keyword in C++11}}
|
||||
int alignof; // already diagnosed in this TU
|
||||
int char16_t; // expected-warning {{'char16_t' is a keyword in C++11}}
|
||||
int char32_t; // expected-warning {{'char32_t' is a keyword in C++11}}
|
||||
int constexpr; // expected-warning {{'constexpr' is a keyword in C++11}}
|
||||
int decltype; // already diagnosed in this TU
|
||||
int noexcept; // expected-warning {{'noexcept' is a keyword in C++11}}
|
||||
int nullptr; // already diagnosed in this TU
|
||||
int static_assert; // expected-warning {{'static_assert' is a keyword in C++11}}
|
||||
int thread_local; // expected-warning {{'thread_local' is a keyword in C++11}}
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
int& a();
|
||||
|
||||
void f() {
|
||||
decltype(a()) c; // expected-error {{use of undeclared identifier 'decltype'}}
|
||||
decltype(a()) c; // expected-warning {{'decltype' is a keyword in C++11}} expected-error {{use of undeclared identifier 'decltype'}}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче