]> granicus.if.org Git - clang/commitdiff
Fix the bug that Eli noticed where we wouldn't look at function decls outside the...
authorAnders Carlsson <andersca@mac.com>
Tue, 24 Mar 2009 17:23:42 +0000 (17:23 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 24 Mar 2009 17:23:42 +0000 (17:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67627 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/abstract.cpp

index 4110fda673fab496a04fdd86658416d456af1f7a..90ef1367855fd70629ad5dcd16615b1ed3abbd6d 100644 (file)
@@ -1647,7 +1647,8 @@ public:
   };
   
   bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, 
-                              AbstractDiagSelID SelID = AbstractNone);
+                              AbstractDiagSelID SelID = AbstractNone,
+                              const CXXRecordDecl *CurrentRD = 0);
 
   //===--------------------------------------------------------------------===//
   // C++ Overloaded Operators [C++ 13.5]
index f21a462e66ee16f5585735a1076b6ca1a334eee0..af71e71ec878094a13424d2e1b3376c62eb3b607 100644 (file)
@@ -785,13 +785,15 @@ namespace {
 }
 
 bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, 
-                                  unsigned DiagID, AbstractDiagSelID SelID) {
+                                  unsigned DiagID, AbstractDiagSelID SelID,
+                                  const CXXRecordDecl *CurrentRD) {
   
   if (!getLangOptions().CPlusPlus)
     return false;
   
   if (const ArrayType *AT = Context.getAsArrayType(T))
-    return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID);
+    return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID,
+                                  CurrentRD);
   
   if (const PointerType *PT = T->getAsPointerType()) {
     // Find the innermost pointer type.
@@ -799,7 +801,8 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
       PT = T;
     
     if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
-      return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID);
+      return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID,
+                                    CurrentRD);
   }
   
   const RecordType *RT = T->getAsRecordType();
@@ -810,6 +813,9 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
   if (!RD)
     return false;
 
+  if (CurrentRD && CurrentRD != RD)
+    return false;
+  
   if (!RD->isAbstract())
     return false;
   
@@ -843,40 +849,58 @@ namespace {
     Sema &SemaRef;
     CXXRecordDecl *AbstractClass;
   
-  public:
-    AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
-      : SemaRef(SemaRef), AbstractClass(ac) {}
-      
-    bool VisitCXXRecordDecl(const CXXRecordDecl *RD) {
+    bool VisitDeclContext(const DeclContext *DC) {
       bool Invalid = false;
 
-      for (CXXRecordDecl::decl_iterator I = RD->decls_begin(),
-           E = RD->decls_end(); I != E; ++I)
+      for (CXXRecordDecl::decl_iterator I = DC->decls_begin(),
+           E = DC->decls_end(); I != E; ++I)
         Invalid |= Visit(*I);
-              
+
       return Invalid;
     }
-    
-    bool VisitCXXMethodDecl(const CXXMethodDecl *MD) {
+      
+  public:
+    AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
+      : SemaRef(SemaRef), AbstractClass(ac) {
+        Visit(SemaRef.Context.getTranslationUnitDecl());
+    }
+
+    bool VisitFunctionDecl(const FunctionDecl *FD) {
+      if (FD->isThisDeclarationADefinition()) {
+        // No need to do the check if we're in a definition, because it requires
+        // that the return/param types are complete.
+        // because that requires 
+        return VisitDeclContext(FD);
+      }
+      
       // Check the return type.
-      QualType RTy = MD->getType()->getAsFunctionType()->getResultType();
+      QualType RTy = FD->getType()->getAsFunctionType()->getResultType();
       bool Invalid = 
-        SemaRef.RequireNonAbstractType(MD->getLocation(), RTy,
+        SemaRef.RequireNonAbstractType(FD->getLocation(), RTy,
                                        diag::err_abstract_type_in_decl,
-                                       Sema::AbstractReturnType);
+                                       Sema::AbstractReturnType,
+                                       AbstractClass);
 
-      for (CXXMethodDecl::param_const_iterator I = MD->param_begin(), 
-           E = MD->param_end(); I != E; ++I) {
+      for (FunctionDecl::param_const_iterator I = FD->param_begin(), 
+           E = FD->param_end(); I != E; ++I) {
         const ParmVarDecl *VD = *I;
         Invalid |= 
           SemaRef.RequireNonAbstractType(VD->getLocation(),
                                          VD->getOriginalType(), 
                                          diag::err_abstract_type_in_decl, 
-                                         Sema::AbstractParamType);
+                                         Sema::AbstractParamType,
+                                         AbstractClass);
       }
 
       return Invalid;
     }
+    
+    bool VisitDecl(const Decl* D) {
+      if (const DeclContext *DC = dyn_cast<DeclContext>(D))
+        return VisitDeclContext(DC);
+      
+      return false;
+    }
   };
 }
 
@@ -898,8 +922,8 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
       RD->setAbstract(true);
   }
   
-  if (RD->isAbstract())
-    AbstractClassUsageDiagnoser(*this, RD).Visit(RD);
+  if (RD->isAbstract()) 
+    AbstractClassUsageDiagnoser(*this, RD);
     
   if (!Template)
     AddImplicitlyDeclaredMembersToClass(RD);
index 023058813941c3ee0f72cfe626338e7dc76e25ba..20b35da83dbef1be1608b036105d10be5270c060 100644 (file)
@@ -66,3 +66,19 @@ class F {
     
     virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
 };
+
+class Abstract;
+
+void t7(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}}
+
+void t8() {
+    void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}}
+}
+
+namespace N {
+    void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}}
+}
+
+class Abstract {
+ virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
+};