Author: Mikhail Goncharov Date: 2021-05-31T15:34:20+02:00 New Revision: c36ff6424f249d3e2005fb0589337452cd7ddad3
URL: https://github.com/llvm/llvm-project/commit/c36ff6424f249d3e2005fb0589337452cd7ddad3 DIFF: https://github.com/llvm/llvm-project/commit/c36ff6424f249d3e2005fb0589337452cd7ddad3.diff LOG: Revert "[clang] Add support for the "abstract" contextual keyword of MSVC" This reverts commit 818338add77411f5e9713247ea66142f332ef350. Tests fail under sanitizer: https://lab.llvm.org/buildbot/#/builders/5/builds/8150 Added: Modified: clang/include/clang/AST/DeclCXX.h clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticParseKinds.td clang/include/clang/Parse/Parser.h clang/include/clang/Sema/DeclSpec.h clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Sema/DeclSpec.cpp clang/lib/Sema/SemaDecl.cpp clang/test/SemaCXX/MicrosoftExtensions.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index c9efc4b454968..07c4eb261aac1 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1786,7 +1786,6 @@ class CXXRecordDecl : public RecordDecl { static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; } - void markAbstract() { data().Abstract = true; } }; /// Store information needed for an explicit specifier. diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 8544607673c3e..f6a4fbb1e04c8 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1086,7 +1086,6 @@ def MicrosoftInclude : DiagGroup<"microsoft-include">; def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">; def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">; def MicrosoftSealed : DiagGroup<"microsoft-sealed">; -def MicrosoftAbstract : DiagGroup<"microsoft-abstract">; def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">; def MicrosoftExceptionSpec : DiagGroup<"microsoft-exception-spec">; def MicrosoftUsingDecl : DiagGroup<"microsoft-using-decl">; @@ -1124,7 +1123,7 @@ def : DiagGroup<"msvc-include", [MicrosoftInclude]>; // Warnings group for warnings about Microsoft extensions. def Microsoft : DiagGroup<"microsoft", [MicrosoftCharize, MicrosoftDrectveSection, MicrosoftInclude, - MicrosoftCppMacro, MicrosoftFixedEnum, MicrosoftSealed, MicrosoftAbstract, + MicrosoftCppMacro, MicrosoftFixedEnum, MicrosoftSealed, MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec, MicrosoftUsingDecl, MicrosoftMutableReference, MicrosoftPureDefinition, MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index b13c382c16ebc..97cb7020f3452 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -922,16 +922,10 @@ def err_override_control_interface : Error< def ext_ms_sealed_keyword : ExtWarn< "'sealed' keyword is a Microsoft extension">, InGroup<MicrosoftSealed>; -def ext_ms_abstract_keyword : ExtWarn< - "'abstract' keyword is a Microsoft extension">, - InGroup<MicrosoftAbstract>; def err_access_specifier_interface : Error< "interface types cannot specify '%select{private|protected}0' access">; -def err_duplicate_class_virt_specifier : Error< - "class already marked '%0'">; - def err_duplicate_virt_specifier : Error< "class member already marked '%0'">; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index c32ae6d2cf406..e3e6509b025e5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -114,7 +114,6 @@ class Parser : public CodeCompletionHandler { /// Contextual keywords for Microsoft extensions. IdentifierInfo *Ident__except; mutable IdentifierInfo *Ident_sealed; - mutable IdentifierInfo *Ident_abstract; /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. @@ -2914,7 +2913,6 @@ class Parser : public CodeCompletionHandler { SourceLocation FriendLoc); bool isCXX11FinalKeyword() const; - bool isClassCompatibleKeyword() const; /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 423f4f4ee7b7c..3b16295941e48 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -2620,8 +2620,7 @@ class VirtSpecifiers { VS_Final = 2, VS_Sealed = 4, // Represents the __final keyword, which is legal for gcc in pre-C++11 mode. - VS_GNU_Final = 8, - VS_Abstract = 16 + VS_GNU_Final = 8 }; VirtSpecifiers() : Specifiers(0), LastSpecifier(VS_None) { } @@ -2637,7 +2636,6 @@ class VirtSpecifiers { bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed | VS_GNU_Final); } bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; } SourceLocation getFinalLoc() const { return VS_finalLoc; } - SourceLocation getAbstractLoc() const { return VS_abstractLoc; } void clear() { Specifiers = 0; } @@ -2651,7 +2649,7 @@ class VirtSpecifiers { unsigned Specifiers; Specifier LastSpecifier; - SourceLocation VS_overrideLoc, VS_finalLoc, VS_abstractLoc; + SourceLocation VS_overrideLoc, VS_finalLoc; SourceLocation FirstLocation; SourceLocation LastLocation; }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 65469418936cb..07518b37eb98a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3147,7 +3147,6 @@ class Sema final { void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl, SourceLocation FinalLoc, bool IsFinalSpelledSealed, - bool IsAbstract, SourceLocation LBraceLoc); /// ActOnTagFinishDefinition - Invoked once we have finished parsing diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5f508dc30240b..af3d0df53e91b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1710,7 +1710,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TUK = Sema::TUK_Reference; else if (Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || - (isClassCompatibleKeyword() && + (isCXX11FinalKeyword() && (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) { if (DS.isFriendSpecified()) { // C++ [class.friend]p2: @@ -1726,18 +1726,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Okay, this is a class definition. TUK = Sema::TUK_Definition; } - } else if (isClassCompatibleKeyword() && - (NextToken().is(tok::l_square) || - NextToken().is(tok::kw_alignas) || - isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None)) { + } else if (isCXX11FinalKeyword() && (NextToken().is(tok::l_square) || + NextToken().is(tok::kw_alignas))) { // We can't tell if this is a definition or reference // until we skipped the 'final' and C++11 attribute specifiers. TentativeParsingAction PA(*this); - // Skip the 'final', abstract'... keywords. - while (isClassCompatibleKeyword()) { - ConsumeToken(); - } + // Skip the 'final' keyword. + ConsumeToken(); // Skip C++11 attribute specifiers. while (true) { @@ -1986,7 +1982,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TUK == Sema::TUK_Definition) { assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || - isClassCompatibleKeyword()); + isCXX11FinalKeyword()); if (SkipBody.ShouldSkip) SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, TagOrTempResult.get()); @@ -2253,10 +2249,8 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { Ident_final = &PP.getIdentifierTable().get("final"); if (getLangOpts().GNUKeywords) Ident_GNU_final = &PP.getIdentifierTable().get("__final"); - if (getLangOpts().MicrosoftExt) { + if (getLangOpts().MicrosoftExt) Ident_sealed = &PP.getIdentifierTable().get("sealed"); - Ident_abstract = &PP.getIdentifierTable().get("abstract"); - } Ident_override = &PP.getIdentifierTable().get("override"); } @@ -2266,9 +2260,6 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { if (II == Ident_sealed) return VirtSpecifiers::VS_Sealed; - if (II == Ident_abstract) - return VirtSpecifiers::VS_Abstract; - if (II == Ident_final) return VirtSpecifiers::VS_Final; @@ -2314,8 +2305,6 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, << VirtSpecifiers::getSpecifierName(Specifier); } else if (Specifier == VirtSpecifiers::VS_Sealed) { Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword); - } else if (Specifier == VirtSpecifiers::VS_Abstract) { - Diag(Tok.getLocation(), diag::ext_ms_abstract_keyword); } else if (Specifier == VirtSpecifiers::VS_GNU_Final) { Diag(Tok.getLocation(), diag::ext_warn_gnu_final); } else { @@ -2338,16 +2327,6 @@ bool Parser::isCXX11FinalKeyword() const { Specifier == VirtSpecifiers::VS_Sealed; } -/// isClassCompatibleKeyword - Determine whether the next token is a C++11 -/// 'final' or Microsoft 'sealed' or 'abstract' contextual keywords. -bool Parser::isClassCompatibleKeyword() const { - VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); - return Specifier == VirtSpecifiers::VS_Final || - Specifier == VirtSpecifiers::VS_GNU_Final || - Specifier == VirtSpecifiers::VS_Sealed || - Specifier == VirtSpecifiers::VS_Abstract; -} - /// Parse a C++ member-declarator up to, but not including, the optional /// brace-or-equal-initializer or pure-specifier. bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( @@ -2914,13 +2893,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, HasStaticInitializer = true; } - if (PureSpecLoc.isValid() && VS.getAbstractLoc().isValid()) { - Diag(PureSpecLoc, diag::err_duplicate_virt_specifier) << "abstract"; - } if (ThisDecl && PureSpecLoc.isValid()) Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc); - else if (ThisDecl && VS.getAbstractLoc().isValid()) - Actions.ActOnPureSpecifier(ThisDecl, VS.getAbstractLoc()); // Handle the initializer. if (HasInClassInit != ICIS_NoInit) { @@ -3305,53 +3279,30 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); SourceLocation FinalLoc; - SourceLocation AbstractLoc; bool IsFinalSpelledSealed = false; - bool IsAbstract = false; // Parse the optional 'final' keyword. if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { - while (true) { - VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok); - if (Specifier == VirtSpecifiers::VS_None) - break; - if (isCXX11FinalKeyword()) { - if (FinalLoc.isValid()) { - auto Skipped = ConsumeToken(); - Diag(Skipped, diag::err_duplicate_class_virt_specifier) - << VirtSpecifiers::getSpecifierName(Specifier); - } else { - FinalLoc = ConsumeToken(); - if (Specifier == VirtSpecifiers::VS_Sealed) - IsFinalSpelledSealed = true; - } - } else { - if (AbstractLoc.isValid()) { - auto Skipped = ConsumeToken(); - Diag(Skipped, diag::err_duplicate_class_virt_specifier) - << VirtSpecifiers::getSpecifierName(Specifier); - } else { - AbstractLoc = ConsumeToken(); - IsAbstract = true; - } - } - if (TagType == DeclSpec::TST_interface) - Diag(FinalLoc, diag::err_override_control_interface) - << VirtSpecifiers::getSpecifierName(Specifier); - else if (Specifier == VirtSpecifiers::VS_Final) - Diag(FinalLoc, getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_override_control_keyword - : diag::ext_override_control_keyword) - << VirtSpecifiers::getSpecifierName(Specifier); - else if (Specifier == VirtSpecifiers::VS_Sealed) - Diag(FinalLoc, diag::ext_ms_sealed_keyword); - else if (Specifier == VirtSpecifiers::VS_Abstract) - Diag(AbstractLoc, diag::ext_ms_abstract_keyword); - else if (Specifier == VirtSpecifiers::VS_GNU_Final) - Diag(FinalLoc, diag::ext_warn_gnu_final); - } - assert((FinalLoc.isValid() || AbstractLoc.isValid()) && + VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok); + assert((Specifier == VirtSpecifiers::VS_Final || + Specifier == VirtSpecifiers::VS_GNU_Final || + Specifier == VirtSpecifiers::VS_Sealed) && "not a class definition"); + FinalLoc = ConsumeToken(); + IsFinalSpelledSealed = Specifier == VirtSpecifiers::VS_Sealed; + + if (TagType == DeclSpec::TST_interface) + Diag(FinalLoc, diag::err_override_control_interface) + << VirtSpecifiers::getSpecifierName(Specifier); + else if (Specifier == VirtSpecifiers::VS_Final) + Diag(FinalLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_override_control_keyword + : diag::ext_override_control_keyword) + << VirtSpecifiers::getSpecifierName(Specifier); + else if (Specifier == VirtSpecifiers::VS_Sealed) + Diag(FinalLoc, diag::ext_ms_sealed_keyword); + else if (Specifier == VirtSpecifiers::VS_GNU_Final) + Diag(FinalLoc, diag::ext_warn_gnu_final); // Parse any C++11 attributes after 'final' keyword. // These attributes are not allowed to appear here, @@ -3424,7 +3375,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc, - IsFinalSpelledSealed, IsAbstract, + IsFinalSpelledSealed, T.getOpenLocation()); // C++ 11p3: Members of a class defined with the keyword class are private diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 72d9ea6dd3bf3..a2b55c0fec294 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1475,7 +1475,6 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, case VS_GNU_Final: case VS_Sealed: case VS_Final: VS_finalLoc = Loc; break; - case VS_Abstract: VS_abstractLoc = Loc; break; } return false; @@ -1488,6 +1487,5 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) { case VS_Final: return "final"; case VS_GNU_Final: return "__final"; case VS_Sealed: return "sealed"; - case VS_Abstract: return "abstract"; } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5e0faacf0fdb0..e08e8d8346c03 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16456,7 +16456,6 @@ Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, bool IsFinalSpelledSealed, - bool IsAbstract, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD); @@ -16466,14 +16465,11 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, if (!Record->getIdentifier()) return; - if (IsAbstract) - Record->markAbstract(); - - if (FinalLoc.isValid()) { + if (FinalLoc.isValid()) Record->addAttr(FinalAttr::Create( Context, FinalLoc, AttributeCommonInfo::AS_Keyword, static_cast<FinalAttr::Spelling>(IsFinalSpelledSealed))); - } + // C++ [class]p2: // [...] The class-name is also inserted into the scope of the // class itself; this is known as the injected-class-name. For diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp index 5dfadae3682a5..b1f8cd96d5052 100644 --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -462,77 +462,6 @@ class SealedDestructor { // expected-note {{mark 'SealedDestructor' as 'sealed' virtual ~SealedDestructor() sealed; // expected-warning {{class with destructor marked 'sealed' cannot be inherited from}} }; -// expected-warning@+1 {{'abstract' keyword is a Microsoft extension}} -class AbstractClass abstract { - int i; -}; - -// expected-error@+1 {{variable type 'AbstractClass' is an abstract class}} -AbstractClass abstractInstance; - -// expected-warning@+4 {{abstract class is marked 'sealed'}} -// expected-note@+3 {{'AbstractAndSealedClass' declared here}} -// expected-warning@+2 {{'abstract' keyword is a Microsoft extension}} -// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}} -class AbstractAndSealedClass abstract sealed {}; // Does no really make sense, but allowed - -// expected-error@+1 {{variable type 'AbstractAndSealedClass' is an abstract class}} -AbstractAndSealedClass abstractAndSealedInstance; -// expected-error@+1 {{base 'AbstractAndSealedClass' is marked 'sealed'}} -class InheritFromAbstractAndSealed : AbstractAndSealedClass {}; - -#if __cplusplus <= 199711L -// expected-warning@+4 {{'final' keyword is a C++11 extension}} -// expected-warning@+3 {{'final' keyword is a C++11 extension}} -#endif -// expected-error@+1 {{class already marked 'final'}} -class TooManyVirtSpecifiers1 final final {}; -#if __cplusplus <= 199711L -// expected-warning@+4 {{'final' keyword is a C++11 extension}} -#endif -// expected-warning@+2 {{'sealed' keyword is a Microsoft extension}} -// expected-error@+1 {{class already marked 'sealed'}} -class TooManyVirtSpecifiers2 final sealed {}; -#if __cplusplus <= 199711L -// expected-warning@+6 {{'final' keyword is a C++11 extension}} -// expected-warning@+5 {{'final' keyword is a C++11 extension}} -#endif -// expected-warning@+3 {{abstract class is marked 'final'}} -// expected-warning@+2 {{'abstract' keyword is a Microsoft extension}} -// expected-error@+1 {{class already marked 'final'}} -class TooManyVirtSpecifiers3 final abstract final {}; -#if __cplusplus <= 199711L -// expected-warning@+6 {{'final' keyword is a C++11 extension}} -#endif -// expected-warning@+4 {{abstract class is marked 'final'}} -// expected-warning@+3 {{'abstract' keyword is a Microsoft extension}} -// expected-warning@+2 {{'abstract' keyword is a Microsoft extension}} -// expected-error@+1 {{class already marked 'abstract'}} -class TooManyVirtSpecifiers4 abstract final abstract {}; - -class Base { - virtual void i(); -}; -class AbstractFunctionInClass : public Base { - // expected-note@+2 {{unimplemented pure virtual method 'f' in 'AbstractFunctionInClass'}} - // expected-warning@+1 {{'abstract' keyword is a Microsoft extension}} - virtual void f() abstract; - // expected-warning@+1 {{'abstract' keyword is a Microsoft extension}} - void g() abstract; // expected-error {{'g' is not virtual and cannot be declared pure}} - // expected-note@+2 {{unimplemented pure virtual method 'h' in 'AbstractFunctionInClass'}} - // expected-warning@+1 {{'abstract' keyword is a Microsoft extension}} - virtual void h() abstract = 0; // expected-error {{class member already marked 'abstract'}} -#if __cplusplus <= 199711L - // expected-warning@+4 {{'override' keyword is a C++11 extension}} -#endif - // expected-note@+2 {{unimplemented pure virtual method 'i' in 'AbstractFunctionInClass'}} - // expected-warning@+1 {{'abstract' keyword is a Microsoft extension}} - virtual void i() abstract override; -}; - -// expected-error@+1 {{variable type 'AbstractFunctionInClass' is an abstract class}} -AbstractFunctionInClass abstractFunctionInClassInstance; - void AfterClassBody() { // expected-warning@+1 {{attribute 'deprecated' is ignored, place it after "struct" to apply attribute to type declaration}} struct D {} __declspec(deprecated); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits