[clang] c36ff64 - Revert "[clang] Add support for the "abstract" contextual keyword of MSVC"

Mikhail Goncharov via cfe-commits cfe-commits at lists.llvm.org
Mon May 31 06:34:39 PDT 2021


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 at +1 {{'abstract' keyword is a Microsoft extension}}
-class AbstractClass abstract {
-  int i;
-};
-
-// expected-error at +1 {{variable type 'AbstractClass' is an abstract class}}
-AbstractClass abstractInstance;
-
-// expected-warning at +4 {{abstract class is marked 'sealed'}}
-// expected-note at +3 {{'AbstractAndSealedClass' declared here}}
-// expected-warning at +2 {{'abstract' keyword is a Microsoft extension}}
-// expected-warning at +1 {{'sealed' keyword is a Microsoft extension}}
-class AbstractAndSealedClass abstract sealed {}; // Does no really make sense, but allowed
-
-// expected-error at +1 {{variable type 'AbstractAndSealedClass' is an abstract class}}
-AbstractAndSealedClass abstractAndSealedInstance;
-// expected-error at +1 {{base 'AbstractAndSealedClass' is marked 'sealed'}}
-class InheritFromAbstractAndSealed : AbstractAndSealedClass {};
-
-#if __cplusplus <= 199711L
-// expected-warning at +4 {{'final' keyword is a C++11 extension}}
-// expected-warning at +3 {{'final' keyword is a C++11 extension}}
-#endif
-// expected-error at +1 {{class already marked 'final'}}
-class TooManyVirtSpecifiers1 final final {};
-#if __cplusplus <= 199711L
-// expected-warning at +4 {{'final' keyword is a C++11 extension}}
-#endif
-// expected-warning at +2 {{'sealed' keyword is a Microsoft extension}}
-// expected-error at +1 {{class already marked 'sealed'}}
-class TooManyVirtSpecifiers2 final sealed {};
-#if __cplusplus <= 199711L
-// expected-warning at +6 {{'final' keyword is a C++11 extension}}
-// expected-warning at +5 {{'final' keyword is a C++11 extension}}
-#endif
-// expected-warning at +3 {{abstract class is marked 'final'}}
-// expected-warning at +2 {{'abstract' keyword is a Microsoft extension}}
-// expected-error at +1 {{class already marked 'final'}}
-class TooManyVirtSpecifiers3 final abstract final {};
-#if __cplusplus <= 199711L
-// expected-warning at +6 {{'final' keyword is a C++11 extension}}
-#endif
-// expected-warning at +4 {{abstract class is marked 'final'}}
-// expected-warning at +3 {{'abstract' keyword is a Microsoft extension}}
-// expected-warning at +2 {{'abstract' keyword is a Microsoft extension}}
-// expected-error at +1 {{class already marked 'abstract'}}
-class TooManyVirtSpecifiers4 abstract final abstract {};
-
-class Base {
-  virtual void i();
-};
-class AbstractFunctionInClass : public Base {
-  // expected-note at +2 {{unimplemented pure virtual method 'f' in 'AbstractFunctionInClass'}}
-  // expected-warning at +1 {{'abstract' keyword is a Microsoft extension}}
-  virtual void f() abstract;
-  // expected-warning at +1 {{'abstract' keyword is a Microsoft extension}}
-  void g() abstract; // expected-error {{'g' is not virtual and cannot be declared pure}}
-  // expected-note at +2 {{unimplemented pure virtual method 'h' in 'AbstractFunctionInClass'}}
-  // expected-warning at +1 {{'abstract' keyword is a Microsoft extension}}
-  virtual void h() abstract = 0; // expected-error {{class member already marked 'abstract'}}
-#if __cplusplus <= 199711L
-  // expected-warning at +4 {{'override' keyword is a C++11 extension}}
-#endif
-  // expected-note at +2 {{unimplemented pure virtual method 'i' in 'AbstractFunctionInClass'}}
-  // expected-warning at +1 {{'abstract' keyword is a Microsoft extension}}
-  virtual void i() abstract override;
-};
-
-// expected-error at +1 {{variable type 'AbstractFunctionInClass' is an abstract class}}
-AbstractFunctionInClass abstractFunctionInClassInstance;
-
 void AfterClassBody() {
   // expected-warning at +1 {{attribute 'deprecated' is ignored, place it after "struct" to apply attribute to type declaration}}
   struct D {} __declspec(deprecated);


        


More information about the cfe-commits mailing list