[cfe-commits] r67476 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/abstract.cpp

Anders Carlsson andersca at mac.com
Sun Mar 22 13:18:18 PDT 2009


Author: andersca
Date: Sun Mar 22 15:18:17 2009
New Revision: 67476

URL: http://llvm.org/viewvc/llvm-project?rev=67476&view=rev
Log:
Disallow abstract types where appropriate.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/abstract.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=67476&r1=67475&r2=67476&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Mar 22 15:18:17 2009
@@ -219,6 +219,12 @@
   "static_assert expression is not an integral constant expression">;
 def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
 
+def err_abstract_type_in_decl : Error<
+  "%select{return|parameter|variable|field}0 type %1 is an abstract class">;
+  
+def note_pure_virtual_function : Note<
+  "pure virtual function %0">;
+  
 // C++ name lookup
 def err_incomplete_nested_name_spec : Error<
   "incomplete type %0 named in nested name specifier">;

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Mar 22 15:18:17 2009
@@ -151,6 +151,13 @@
   /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
   llvm::OwningPtr<CXXFieldCollector> FieldCollector;
 
+  typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
+  
+  /// PureVirtualClassDiagSet - a set of class declarations which we have 
+  /// emitted a list of pure virtual functions. Used to prevent emitting the
+  /// same list more than once.
+  llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+  
   /// \brief A mapping from external names to the most recent
   /// locally-scoped external declaration with that name.
   ///
@@ -1627,6 +1634,8 @@
                                     SourceLocation Loc, SourceRange Range);
   std::string getAmbiguousPathsDisplayString(BasePaths &Paths);
 
+  bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned SelID);
+
   //===--------------------------------------------------------------------===//
   // 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=67476&r1=67475&r2=67476&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Mar 22 15:18:17 2009
@@ -1637,6 +1637,12 @@
     } else if (SC == VarDecl::None)
       SC = VarDecl::Static;
   }
+
+  // The variable can not have an abstract class type.
+  if (RequireNonAbstractType(D.getIdentifierLoc(), R, 2 /* variable type */))
+    InvalidDecl = true;
+    
+  // The variable can not 
   NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), 
                           II, R, SC, 
                           // FIXME: Move to DeclGroup...
@@ -1804,6 +1810,12 @@
   bool isVirtual = D.getDeclSpec().isVirtualSpecified();
   bool isExplicit = D.getDeclSpec().isExplicitSpecified();
 
+  // Check that the return type is not an abstract class type.
+  if (RequireNonAbstractType(D.getIdentifierLoc(), 
+                             R->getAsFunctionType()->getResultType(),
+                             0 /* return type */))
+    InvalidDecl = true;
+  
   bool isVirtualOkay = false;
   FunctionDecl *NewFD;
   if (D.getKind() == Declarator::DK_Constructor) {
@@ -1977,8 +1989,15 @@
         Diag(Param->getLocation(), diag::ext_param_typedef_of_void);
       }
     } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
-      for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
-        Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
+      for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+        ParmVarDecl *PVD = (ParmVarDecl *)FTI.ArgInfo[i].Param;
+        
+        // Function parameters cannot have abstract class types.
+        if (RequireNonAbstractType(PVD->getLocation(), PVD->getType(),
+                                   1 /* parameter type */))
+            InvalidDecl = true;
+        Params.push_back(PVD);
+      }
     }
   
     NewFD->setParams(Context, &Params[0], Params.size());
@@ -3512,6 +3531,10 @@
     }
   }
   
+  // Fields can not have abstract class types
+  if (RequireNonAbstractType(Loc, T, 3 /* field type */))
+    InvalidDecl = true;
+  
   // If this is declared as a bit-field, check the bit-field.
   if (BitWidth && VerifyBitField(Loc, II, T, BitWidth)) {
     InvalidDecl = true;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Mar 22 15:18:17 2009
@@ -731,7 +731,10 @@
       }          
     }
     
-    bool empty() const { return Methods.empty(); }    
+    bool empty() const { return Methods.empty(); }
+    
+    MethodList::const_iterator methods_begin() { return Methods.begin(); }
+    MethodList::const_iterator methods_end() { return Methods.end(); }
   };
   
   void PureVirtualMethodCollector::Collect(const CXXRecordDecl* RD, 
@@ -777,6 +780,47 @@
   }
 }
 
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, 
+                                  unsigned SelID) {
+  
+  if (!getLangOptions().CPlusPlus)
+    return false;
+    
+  const RecordType *RT = T->getAsRecordType();
+  if (!RT)
+    return false;
+  
+  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+  if (!RD)
+    return false;
+
+  if (!RD->isAbstract())
+    return false;
+  
+  Diag(Loc, diag::err_abstract_type_in_decl) << SelID << RD->getDeclName();
+  
+  // Check if we've already emitted the list of pure virtual functions for this
+  // class.
+  if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
+    return true;
+  
+  PureVirtualMethodCollector Collector(Context, RD);
+  
+  for (PureVirtualMethodCollector::MethodList::const_iterator I = 
+       Collector.methods_begin(), E = Collector.methods_end(); I != E; ++I) {
+    const CXXMethodDecl *MD = *I;
+    
+    Diag(MD->getLocation(), diag::note_pure_virtual_function) << 
+      MD->getDeclName();
+  }
+
+  if (!PureVirtualClassDiagSet)
+    PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
+  PureVirtualClassDiagSet->insert(RD);
+  
+  return true;
+}
+
 void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                              DeclTy *TagDecl,
                                              SourceLocation LBrac,

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

==============================================================================
--- cfe/trunk/test/SemaCXX/abstract.cpp (original)
+++ cfe/trunk/test/SemaCXX/abstract.cpp Sun Mar 22 15:18:17 2009
@@ -9,7 +9,7 @@
 #endif
 
 class C {
-    virtual void f() = 0;
+    virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
 };
 
 static_assert(__is_abstract(C), "C has a pure virtual function");
@@ -24,3 +24,11 @@
 };
 
 static_assert(!__is_abstract(E), "E inherits from an abstract class but implements f");
+
+C c; // expected-error {{variable type 'C' is an abstract class}}
+void t1(C c); // expected-error {{parameter type 'C' is an abstract class}}
+void t2(C); // expected-error {{parameter type 'C' is an abstract class}}
+
+struct S {
+  C c; // expected-error {{field type 'C' is an abstract class}}
+};





More information about the cfe-commits mailing list