[cfe-commits] r90467 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaCXX/virtual-override.cpp

Douglas Gregor dgregor at apple.com
Thu Dec 3 10:33:45 PST 2009


Author: dgregor
Date: Thu Dec  3 12:33:45 2009
New Revision: 90467

URL: http://llvm.org/viewvc/llvm-project?rev=90467&view=rev
Log:
Unify the end-of-class code paths used by the parser and template
instantiation, to ensure that we mark class template specilizations as
abstract when we need to and perform checking of abstract classes.

Also, move the checking that determines whether we are creating a
variable of abstract class type *after* we check whether the type is
complete. Otherwise, we won't see when we have an abstract class
template specialization that is implicitly instantiated by this
declaration. This is the "something else" that Sebastian had noted
earlier.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaCXX/virtual-override.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90467&r1=90466&r2=90467&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Dec  3 12:33:45 2009
@@ -2148,6 +2148,7 @@
                                     SourceLocation ColonLoc,
                                     MemInitTy **MemInits, unsigned NumMemInits);
 
+  void CheckCompletedCXXClass(CXXRecordDecl *Record);
   virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                                  DeclPtrTy TagDecl,
                                                  SourceLocation LBrac,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=90467&r1=90466&r2=90467&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Dec  3 12:33:45 2009
@@ -2444,12 +2444,6 @@
     return NewVD->setInvalidDecl();
   }
 
-  // The variable can not have an abstract class type.
-  if (RequireNonAbstractType(NewVD->getLocation(), T,
-                             diag::err_abstract_type_in_decl,
-                             AbstractVariableType))
-    return NewVD->setInvalidDecl();
-
   // Emit an error if an address space was applied to decl with local storage.
   // This includes arrays of objects with address space qualifiers, but not
   // automatic variables that point to other address spaces.
@@ -3431,6 +3425,12 @@
     return;
   }
 
+  // The variable can not have an abstract class type.
+  if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType))
+    VDecl->setInvalidDecl();
+
   const VarDecl *Def = 0;
   if (VDecl->getDefinition(Def)) {
     Diag(VDecl->getLocation(), diag::err_redefinition)
@@ -3663,6 +3663,12 @@
           Var->setInvalidDecl();
         }
       }
+
+      // The variable can not have an abstract class type.
+      if (RequireNonAbstractType(Var->getLocation(), Type,
+                                 diag::err_abstract_type_in_decl,
+                                 AbstractVariableType))
+        Var->setInvalidDecl();
     }
 
 #if 0

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=90467&r1=90466&r2=90467&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Dec  3 12:33:45 2009
@@ -1957,6 +1957,28 @@
   };
 }
 
+/// \brief Perform semantic checks on a class definition that has been
+/// completing, introducing implicitly-declared members, checking for
+/// abstract types, etc.
+void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
+  if (!Record || Record->isInvalidDecl())
+    return;
+
+  if (!Record->isAbstract()) {
+    // Collect all the pure virtual methods and see if this is an abstract
+    // class after all.
+    PureVirtualMethodCollector Collector(Context, Record);
+    if (!Collector.empty())
+      Record->setAbstract(true);
+  }
+
+  if (Record->isAbstract())
+    (void)AbstractClassUsageDiagnoser(*this, Record);
+
+  if (!Record->isDependentType() && !Record->isInvalidDecl())
+    AddImplicitlyDeclaredMembersToClass(Record);
+}
+
 void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                              DeclPtrTy TagDecl,
                                              SourceLocation LBrac,
@@ -1965,24 +1987,13 @@
     return;
 
   AdjustDeclIfTemplate(TagDecl);
+
   ActOnFields(S, RLoc, TagDecl,
               (DeclPtrTy*)FieldCollector->getCurFields(),
               FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
 
-  CXXRecordDecl *RD = cast<CXXRecordDecl>(TagDecl.getAs<Decl>());
-  if (!RD->isAbstract()) {
-    // Collect all the pure virtual methods and see if this is an abstract
-    // class after all.
-    PureVirtualMethodCollector Collector(Context, RD);
-    if (!Collector.empty())
-      RD->setAbstract(true);
-  }
-
-  if (RD->isAbstract())
-    (void)AbstractClassUsageDiagnoser(*this, RD);
-
-  if (!RD->isDependentType() && !RD->isInvalidDecl())
-    AddImplicitlyDeclaredMembersToClass(RD);
+  CheckCompletedCXXClass(
+                      dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>()));
 }
 
 /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=90467&r1=90466&r2=90467&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Dec  3 12:33:45 2009
@@ -1077,13 +1077,10 @@
   ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
               Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
               0);
+  CheckCompletedCXXClass(Instantiation);
   if (Instantiation->isInvalidDecl())
     Invalid = true;
   
-  // Add any implicitly-declared members that we might need.
-  if (!Invalid)
-    AddImplicitlyDeclaredMembersToClass(Instantiation);
-
   // Exit the scope of this instantiation.
   CurContext = PreviousContext;
 

Modified: cfe/trunk/test/SemaCXX/virtual-override.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/virtual-override.cpp?rev=90467&r1=90466&r2=90467&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/virtual-override.cpp (original)
+++ cfe/trunk/test/SemaCXX/virtual-override.cpp Thu Dec  3 12:33:45 2009
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -faccess-control -verify %s
-
 namespace T1 {
 
 class A {
@@ -122,8 +121,8 @@
 struct Base2 { };
 
 void test() {
-  Foo<Base1> f1;
-  Foo<Base2> f2; // expected-note{{instantiation}}
+  (void)sizeof(Foo<Base1>);
+  (void)sizeof(Foo<Base2>); // expected-note{{instantiation}}
 }
 
 template<typename Base>
@@ -137,3 +136,17 @@
   f1.f(17);
   f2.f(17);
 };
+
+struct Foo3 {
+  virtual void f(int) = 0; // expected-note{{pure virtual function}}
+};
+
+template<typename T>
+struct Bar3 : Foo3 {
+  void f(T);
+};
+
+void test3() {
+  Bar3<int> b3i; // okay
+  Bar3<float> b3f; // expected-error{{is an abstract class}}
+}





More information about the cfe-commits mailing list