summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/IdentifierTable.h9
-rw-r--r--clang/include/clang/Basic/TokenKinds.def2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp12
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp38
-rw-r--r--clang/test/SemaCXX/MicrosoftCompatibility.cpp15
5 files changed, 69 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
index af6ecf93c36..d672314f56e 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -62,7 +62,7 @@ class IdentifierInfo {
// partially) from an AST file.
bool ChangedAfterLoad : 1; // True if identifier has changed from the
// definition loaded from an AST file.
- bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
+ bool RevertedTokenID : 1; // True if revertTokenIDToIdentifier was
// called.
bool OutOfDate : 1; // True if there may be additional
// information about this identifier
@@ -152,7 +152,7 @@ public:
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
- /// \brief True if RevertTokenIDToIdentifier() was called.
+ /// \brief True if revertTokenIDToIdentifier() was called.
bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
/// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
@@ -166,6 +166,11 @@ public:
TokenID = tok::identifier;
RevertedTokenID = true;
}
+ void revertIdentifierToTokenID(tok::TokenKind TK) {
+ assert(TokenID == tok::identifier && "Should be at tok::identifier");
+ TokenID = TK;
+ RevertedTokenID = false;
+ }
/// \brief Return the preprocessor keyword ID for this identifier.
///
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 7a91c9f502b..2638e5e4612 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -280,7 +280,7 @@ KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Alignas , KEYALL)
KEYWORD(_Alignof , KEYALL)
-KEYWORD(_Atomic , KEYALL|KEYNOMS18|KEYNOOPENCL)
+KEYWORD(_Atomic , KEYALL|KEYNOOPENCL)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
KEYWORD(_Generic , KEYALL)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index acfe0ca0e82..40687d8f27b 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2647,6 +2647,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
const char *PrevSpec = nullptr;
unsigned DiagID = 0;
+ // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
+ // implementation for VS2013 uses _Atomic as an identifier for one of the
+ // classes in <atomic>.
+ //
+ // A typedef declaration containing _Atomic<...> is among the places where
+ // the class is used. If we are currently parsing such a declaration, treat
+ // the token as an identifier.
+ if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
+ DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef &&
+ !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less))
+ Tok.setKind(tok::identifier);
+
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79138900b83..88ffb25a388 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1308,6 +1308,35 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// allow libstdc++ 4.2 and libc++ to work properly.
TryKeywordIdentFallback(true);
+ struct PreserveAtomicIdentifierInfoRAII {
+ PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled)
+ : AtomicII(nullptr) {
+ if (!Enabled)
+ return;
+ assert(Tok.is(tok::kw__Atomic));
+ AtomicII = Tok.getIdentifierInfo();
+ AtomicII->revertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
+ }
+ ~PreserveAtomicIdentifierInfoRAII() {
+ if (!AtomicII)
+ return;
+ AtomicII->revertIdentifierToTokenID(tok::kw__Atomic);
+ }
+ IdentifierInfo *AtomicII;
+ };
+
+ // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
+ // implementation for VS2013 uses _Atomic as an identifier for one of the
+ // classes in <atomic>. When we are parsing 'struct _Atomic', don't consider
+ // '_Atomic' to be a keyword. We are careful to undo this so that clang can
+ // use '_Atomic' in its own header files.
+ bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat &&
+ Tok.is(tok::kw__Atomic) &&
+ TagType == DeclSpec::TST_struct;
+ PreserveAtomicIdentifierInfoRAII AtomicTokenGuard(
+ Tok, ShouldChangeAtomicToIdentifier);
+
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
@@ -1859,6 +1888,15 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
CheckMisplacedCXX11Attribute(Attributes, StartLoc);
// Parse the class-name.
+
+ // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
+ // implementation for VS2013 uses _Atomic as an identifier for one of the
+ // classes in <atomic>. Treat '_Atomic' to be an identifier when we are
+ // parsing the class-name for a base specifier.
+ if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
+ NextToken().is(tok::less))
+ Tok.setKind(tok::identifier);
+
SourceLocation EndLocation;
SourceLocation BaseLoc;
TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation);
diff --git a/clang/test/SemaCXX/MicrosoftCompatibility.cpp b/clang/test/SemaCXX/MicrosoftCompatibility.cpp
index 1536007a647..fe8e8f77acc 100644
--- a/clang/test/SemaCXX/MicrosoftCompatibility.cpp
+++ b/clang/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -9,11 +9,18 @@ typedef unsigned short char16_t;
typedef unsigned int char32_t;
#endif
-#if _MSC_VER >= 1900
_Atomic(int) z;
-#else
-struct _Atomic {};
-#endif
+template <typename T>
+struct _Atomic {
+ _Atomic() {}
+ ~_Atomic() {}
+};
+template <typename T>
+struct atomic : _Atomic<T> {
+ typedef _Atomic<T> TheBase;
+ TheBase field;
+};
+_Atomic(int) alpha;
typename decltype(3) a; // expected-warning {{expected a qualified name after 'typename'}}
OpenPOWER on IntegriCloud