Index: include/clang/Basic/IdentifierTable.h =================================================================== --- include/clang/Basic/IdentifierTable.h +++ include/clang/Basic/IdentifierTable.h @@ -166,6 +166,11 @@ 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. /// Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -280,7 +280,7 @@ 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) Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -137,6 +137,9 @@ mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; + /// \brief Identifier for "_Atomic". + IdentifierInfo *Ident__Atomic; + // C++ type trait keywords that can be reverted to identifiers and still be // used as type traits. llvm::SmallDenseMap RevertibleTypeTraits; Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -1307,6 +1307,37 @@ // allow libstdc++ 4.2 and libc++ to work properly. TryKeywordIdentFallback(true); + struct PreserveIdentifierInfoRAII { + void set(IdentifierInfo *ToPreserve) { + II = ToPreserve; + TK = II->getTokenID(); + } + ~PreserveIdentifierInfoRAII() { + if (II) { + if (TK == tok::identifier && II->getTokenID() != tok::identifier) + II->RevertTokenIDToIdentifier(); + else if (TK != tok::identifier && II->getTokenID() == tok::identifier) + II->RevertIdentifierToTokenID(TK); + } + } + IdentifierInfo *II = nullptr; + tok::TokenKind TK; + }; + + PreserveIdentifierInfoRAII AtomicTokenGuard; + if (getLangOpts().MSVCCompat) { + if (!Ident__Atomic) + Ident__Atomic = &PP.getIdentifierTable().get("_Atomic"); + AtomicTokenGuard.set(Ident__Atomic); + } + + if (getLangOpts().MSVCCompat && TagType == DeclSpec::TST_struct && + Tok.isNot(tok::identifier) && !Tok.isAnnotation() && + Tok.getIdentifierInfo() && Tok.is(tok::kw__Atomic)) { + Ident__Atomic->RevertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + } + // Parse the (optional) nested-name-specifier. CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLangOpts().CPlusPlus) { @@ -1858,6 +1889,12 @@ CheckMisplacedCXX11Attribute(Attributes, StartLoc); // Parse the class-name. + if (getLangOpts().MSVCCompat && Tok.isNot(tok::identifier) && + !Tok.isAnnotation() && Tok.getIdentifierInfo() && + Tok.is(tok::kw__Atomic)) { + Ident__Atomic->RevertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + } SourceLocation EndLocation; SourceLocation BaseLoc; TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation); Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -517,6 +517,8 @@ PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); } + Ident__Atomic = nullptr; + Actions.Initialize(); // Prime the lexer look-ahead. Index: test/SemaCXX/MicrosoftCompatibility.cpp =================================================================== --- test/SemaCXX/MicrosoftCompatibility.cpp +++ test/SemaCXX/MicrosoftCompatibility.cpp @@ -9,11 +9,8 @@ typedef unsigned int char32_t; #endif -#if _MSC_VER >= 1900 _Atomic(int) z; -#else struct _Atomic {}; -#endif typename decltype(3) a; // expected-warning {{expected a qualified name after 'typename'}}