[cfe-commits] r76913 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp test/SemaCXX/constructor-initializer.cpp

Fariborz Jahanian fjahanian at apple.com
Thu Jul 23 16:33:20 PDT 2009


Author: fjahanian
Date: Thu Jul 23 18:32:59 2009
New Revision: 76913

URL: http://llvm.org/viewvc/llvm-project?rev=76913&view=rev
Log:
Diagnose when base classes and members to be intialized
with constructors don't have a matching constructor.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/constructor-initializer.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Jul 23 18:32:59 2009
@@ -736,7 +736,7 @@
   Expr **Args;
   unsigned NumArgs;
   
-  /// CtorToCall - For a base or mamber needing a constructor for their
+  /// CtorToCall - For a base or member needing a constructor for their
   /// initialization, this is the constructor to call.
   CXXConstructorDecl *CtorToCall;
   
@@ -923,8 +923,10 @@
   }
   
   void setBaseOrMemberInitializers(ASTContext &C,
-                                   CXXBaseOrMemberInitializer **Initializers,
-                                   unsigned NumInitializers);
+                              CXXBaseOrMemberInitializer **Initializers,
+                              unsigned NumInitializers,
+                              llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
+                              llvm::SmallVectorImpl<FieldDecl *>&Members);
   
   /// isDefaultConstructor - Whether this constructor is a default
   /// constructor (C++ [class.ctor]p5), which can be used to

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 23 18:32:59 2009
@@ -346,6 +346,9 @@
   "cannot initialize object parameter of type %0 with an expression "
   "of type %1">;
 
+def err_missing_default_constructor : Error<
+  "default constructor for %1 is missing in initialization of "
+  "%select{base class|mamber}0">;
 def err_illegal_union_member : Error<
   "union member %0 has a non-trivial %select{constructor|"
   "copy constructor|copy assignment operator|destructor}1">;

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=76913&r1=76912&r2=76913&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Jul 23 18:32:59 2009
@@ -564,9 +564,11 @@
 
 void
 CXXConstructorDecl::setBaseOrMemberInitializers(
-                                    ASTContext &C,
-                                    CXXBaseOrMemberInitializer **Initializers,
-                                    unsigned NumInitializers) {
+                                ASTContext &C,
+                                CXXBaseOrMemberInitializer **Initializers,
+                                unsigned NumInitializers,
+                                llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,          
+                                llvm::SmallVectorImpl<FieldDecl *>&Fields) {
   // We need to build the initializer AST according to order of construction
   // and not what user specified in the Initializers list.
   CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext());
@@ -594,7 +596,9 @@
       CXXRecordDecl *VBaseDecl = 
         cast<CXXRecordDecl>(VBase->getType()->getAsRecordType()->getDecl());
       assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null");
-      // FIXME. Issue error if default ctor is missing.
+      if (!VBaseDecl->getDefaultConstructor(C) && 
+          !VBase->getType()->isDependentType())
+        Bases.push_back(VBase);
       CXXBaseOrMemberInitializer *Member = 
         new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,
                                            VBaseDecl->getDefaultConstructor(C),
@@ -617,7 +621,9 @@
       CXXRecordDecl *BaseDecl = 
         cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
       assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null");
-      // FIXME. Issue error if default ctor is missing.
+      if (!BaseDecl->getDefaultConstructor(C) && 
+          !Base->getType()->isDependentType())
+        Bases.push_back(Base);
       CXXBaseOrMemberInitializer *Member = 
       new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0,
                                          BaseDecl->getDefaultConstructor(C),
@@ -643,7 +649,8 @@
       if (CXXRecordDecl *FieldClassDecl = 
             dyn_cast<CXXRecordDecl>(FieldType->getAsRecordType()->getDecl()))
         Ctor = FieldClassDecl->getDefaultConstructor(C);
-      // FIXME. Issue error if default ctor is missing.
+      if (!Ctor && !FieldType->isDependentType())
+        Fields.push_back(*Field);
       CXXBaseOrMemberInitializer *Member = 
         new (C) CXXBaseOrMemberInitializer((*Field), 0, 0,
                                            Ctor,

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jul 23 18:32:59 2009
@@ -1482,6 +1482,11 @@
                                const FunctionProtoType *Proto,
                                Expr **Args, unsigned NumArgs,
                                SourceLocation RParenLoc);
+  void BuildBaseOrMemberInitializers(ASTContext &C,
+                                 CXXConstructorDecl *Constructor,
+                                 CXXBaseOrMemberInitializer **Initializers,
+                                 unsigned NumInitializers
+                                 );
 
   /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
   /// This provides the location of the left/right parens and a list of comma

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jul 23 18:32:59 2009
@@ -810,6 +810,26 @@
                                                   NumArgs, C, IdLoc);
 }
 
+void
+Sema::BuildBaseOrMemberInitializers(ASTContext &C,
+                                 CXXConstructorDecl *Constructor,
+                                 CXXBaseOrMemberInitializer **Initializers,
+                                 unsigned NumInitializers
+                                 ) {
+  llvm::SmallVector<CXXBaseSpecifier *, 4>Bases;
+  llvm::SmallVector<FieldDecl *, 4>Members;
+  
+  Constructor->setBaseOrMemberInitializers(C, 
+                                           Initializers, NumInitializers,
+                                           Bases, Members);
+  for (unsigned int i = 0; i < Bases.size(); i++)
+    Diag(Bases[i]->getSourceRange().getBegin(), 
+         diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
+  for (unsigned int i = 0; i < Members.size(); i++)
+    Diag(Members[i]->getLocation(), diag::err_missing_default_constructor) 
+          << 1 << Members[i]->getType();
+}
+
 static void *GetKeyForTopLevelField(FieldDecl *Field) {
   // For anonymous unions, use the class declaration as the key.
   if (const RecordType *RT = Field->getType()->getAsRecordType()) {
@@ -872,11 +892,11 @@
       << 0;
     err = true;
   }
-  if (!err) {
-    Constructor->setBaseOrMemberInitializers(Context, 
-                    reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), 
-                    NumMemInits);
-  }
+  if (!err)
+    BuildBaseOrMemberInitializers(Context, Constructor,
+                      reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), 
+                      NumMemInits);
+  
   if (!err && (Diags.getDiagnosticLevel(diag::warn_base_initialized)
                != Diagnostic::Ignored ||
                Diags.getDiagnosticLevel(diag::warn_field_initialized)
@@ -960,8 +980,9 @@
   
   if (CXXConstructorDecl *Constructor 
       = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
-    Constructor->setBaseOrMemberInitializers(Context, 
-                                           (CXXBaseOrMemberInitializer **)0, 0);
+    BuildBaseOrMemberInitializers(Context,
+                                     Constructor,
+                                     (CXXBaseOrMemberInitializer **)0, 0);
 }
 
 namespace {

Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=76913&r1=76912&r2=76913&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Thu Jul 23 18:32:59 2009
@@ -96,3 +96,23 @@
                            INT::NonExisting()  {} // expected-error {{expected a class or namespace}} \
 						  // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}}
 };
+
+                        // FIXME. This is bad message!
+struct M { 		// expected-note {{candidate function}}	\
+                        // expected-note {{candidate function}}
+  M(int i, int j);	// expected-note {{candidate function}} \
+			// // expected-note {{candidate function}}
+};
+
+struct N : M  {
+  N() : M(1), 	// expected-error {{no matching constructor for initialization of 'M'}}
+        m1(100) {  } // expected-error {{no matching constructor for initialization of 'm1'}}
+  M m1;
+};
+
+struct P : M  { // expected-error {{default constructor for 'struct M' is missing in initialization of base class}}
+  P()  {  }
+  M m; // expected-error {{default constructor for 'struct M' is missing in initialization of mamber}}
+};
+
+





More information about the cfe-commits mailing list