[cfe-commits] r67594 - in /cfe/trunk: include/clang/AST/DeclVisitor.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/abstract.cpp

Anders Carlsson andersca at mac.com
Mon Mar 23 18:19:16 PDT 2009


Author: andersca
Date: Mon Mar 23 20:19:16 2009
New Revision: 67594

URL: http://llvm.org/viewvc/llvm-project?rev=67594&view=rev
Log:
More work on diagnosing abstract classes. We can now handle cases like

class C {
  void g(C c);

  virtual void f() = 0;
};

In this case, C is not known to be abstract when doing semantic analysis on g. This is done by recursively traversing the abstract class and checking the types of member functions. 


Modified:
    cfe/trunk/include/clang/AST/DeclVisitor.h
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/abstract.cpp

Modified: cfe/trunk/include/clang/AST/DeclVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclVisitor.h?rev=67594&r1=67593&r2=67594&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DeclVisitor.h Mon Mar 23 20:19:16 2009
@@ -13,6 +13,8 @@
 #ifndef LLVM_CLANG_AST_DECLVISITOR_H
 #define LLVM_CLANG_AST_DECLVISITOR_H
 
+#include "clang/AST/DeclTemplate.h"
+
 namespace clang {
 
 #define DISPATCH(NAME, CLASS) \

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Mar 23 20:19:16 2009
@@ -1638,8 +1638,16 @@
                                     SourceLocation Loc, SourceRange Range);
   std::string getAmbiguousPathsDisplayString(BasePaths &Paths);
 
-  bool RequireNonAbstractType(SourceLocation Loc, QualType T, 
-                              unsigned DiagID, unsigned SelID);
+  enum AbstractDiagSelID {
+    AbstractNone = -1,
+    AbstractReturnType,
+    AbstractParamType,
+    AbstractVariableType,
+    AbstractFieldType
+  };
+  
+  bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, 
+                              AbstractDiagSelID SelID = AbstractNone);
 
   //===--------------------------------------------------------------------===//
   // C++ Overloaded Operators [C++ 13.5]

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Mar 23 20:19:16 2009
@@ -1643,7 +1643,7 @@
   // The variable can not have an abstract class type.
   if (RequireNonAbstractType(D.getIdentifierLoc(), R, 
                              diag::err_abstract_type_in_decl, 
-                             2 /* variable type */))
+                             AbstractVariableType))
     InvalidDecl = true;
     
   // The variable can not 
@@ -1815,11 +1815,14 @@
   bool isExplicit = D.getDeclSpec().isExplicitSpecified();
 
   // Check that the return type is not an abstract class type.
-  if (RequireNonAbstractType(D.getIdentifierLoc(), 
+  // For record types, this is done by the AbstractClassUsageDiagnoser once
+  // the class has been completely parsed. 
+  if (!DC->isRecord() &&
+      RequireNonAbstractType(D.getIdentifierLoc(), 
                              R->getAsFunctionType()->getResultType(),
                              diag::err_abstract_type_in_decl, 
-                             0 /* return type */))
-    InvalidDecl = true;
+                             AbstractReturnType))
+        InvalidDecl = true;
   
   bool isVirtualOkay = false;
   FunctionDecl *NewFD;
@@ -2609,9 +2612,12 @@
   }
 
   // Parameters can not be abstract class types.
-  if (RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType, 
+  // For record types, this is done by the AbstractClassUsageDiagnoser once
+  // the class has been completely parsed. 
+  if (!CurContext->isRecord() && 
+      RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType, 
                              diag::err_abstract_type_in_decl,
-                             1 /* parameter type */)) 
+                             AbstractParamType))
     D.setInvalidType(true);
 
   QualType T = adjustParameterType(parmDeclType);
@@ -3544,7 +3550,7 @@
   
   // Fields can not have abstract class types
   if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl, 
-                             3 /* field type */))
+                             AbstractFieldType))
     InvalidDecl = true;
   
   // If this is declared as a bit-field, check the bit-field.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Mar 23 20:19:16 2009
@@ -15,6 +15,7 @@
 #include "SemaInherit.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
 #include "clang/AST/TypeOrdering.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Lex/Preprocessor.h"
@@ -784,7 +785,7 @@
 }
 
 bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, 
-                                  unsigned DiagID, unsigned SelID) {
+                                  unsigned DiagID, AbstractDiagSelID SelID) {
   
   if (!getLangOptions().CPlusPlus)
     return false;
@@ -827,6 +828,49 @@
   return true;
 }
 
+namespace {
+  class VISIBILITY_HIDDEN AbstractClassUsageDiagnoser 
+    : public DeclVisitor<AbstractClassUsageDiagnoser, bool> {
+    Sema &SemaRef;
+    CXXRecordDecl *AbstractClass;
+  
+  public:
+    AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
+      : SemaRef(SemaRef), AbstractClass(ac) {}
+      
+    bool VisitCXXRecordDecl(const CXXRecordDecl *RD) {
+      bool Invalid = false;
+
+      for (CXXRecordDecl::decl_iterator I = RD->decls_begin(),
+           E = RD->decls_end(); I != E; ++I)
+        Invalid |= Visit(*I);
+              
+      return Invalid;
+    }
+    
+    bool VisitCXXMethodDecl(const CXXMethodDecl *MD) {
+      // Check the return type.
+      QualType RTy = MD->getType()->getAsFunctionType()->getResultType();
+      bool Invalid = 
+        SemaRef.RequireNonAbstractType(MD->getLocation(), RTy,
+                                       diag::err_abstract_type_in_decl,
+                                       Sema::AbstractReturnType);
+
+      for (CXXMethodDecl::param_const_iterator I = MD->param_begin(), 
+           E = MD->param_end(); I != E; ++I) {
+        const ParmVarDecl *VD = *I;
+        Invalid |= 
+          SemaRef.RequireNonAbstractType(VD->getLocation(),
+                                         VD->getOriginalType(), 
+                                         diag::err_abstract_type_in_decl, 
+                                         Sema::AbstractParamType);
+      }
+
+      return Invalid;
+    }
+  };
+}
+
 void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                              DeclTy *TagDecl,
                                              SourceLocation LBrac,
@@ -845,6 +889,9 @@
       RD->setAbstract(true);
   }
   
+  if (RD->isAbstract())
+    AbstractClassUsageDiagnoser(*this, RD).Visit(RD);
+    
   if (!Template)
     AddImplicitlyDeclaredMembersToClass(RD);
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Mar 23 20:19:16 2009
@@ -197,8 +197,8 @@
                           diag::err_invalid_incomplete_type_use, FullRange))
     return ExprError();
 
-  if (RequireNonAbstractType(TyBeginLoc, Ty, 
-                             diag::err_allocation_of_abstract_type, 0))
+  if (RequireNonAbstractType(TyBeginLoc, Ty,
+                             diag::err_allocation_of_abstract_type))
     return ExprError();
   
   exprs.release();
@@ -243,7 +243,7 @@
     return ExprError();
 
   if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
-                             diag::err_allocation_of_abstract_type, 0))
+                             diag::err_allocation_of_abstract_type))
     return ExprError();
   
   QualType ResultType = AllocType->isDependentType()

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Mar 23 20:19:16 2009
@@ -357,7 +357,7 @@
       else if (SemaRef.RequireNonAbstractType(PInst->getLocation(), 
                                               PInst->getType(),
                                               diag::err_abstract_type_in_decl,
-                                              1 /* parameter type */))
+                                              Sema::AbstractParamType))
         PInst->setInvalidDecl();
 
       Params.push_back(PInst);

Modified: cfe/trunk/test/SemaCXX/abstract.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/abstract.cpp?rev=67594&r1=67593&r2=67594&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/abstract.cpp (original)
+++ cfe/trunk/test/SemaCXX/abstract.cpp Mon Mar 23 20:19:16 2009
@@ -51,4 +51,16 @@
 typedef void (*Func)(C); // expected-error {{parameter type 'C' is an abstract class}}
 void t6(Func);
 
+class F {
+    F a() { } // expected-error {{return type 'F' is an abstract class}}
+    
+    class D {
+        void f(F c); // expected-error {{parameter type 'F' is an abstract class}}
+    };
 
+    union U {
+        void u(F c); // expected-error {{parameter type 'F' is an abstract class}}
+    };
+    
+    virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
+};





More information about the cfe-commits mailing list