[cfe-commits] r73782 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/default-contructor-initializers.cpp

Fariborz Jahanian fjahanian at apple.com
Fri Jun 19 12:55:32 PDT 2009


Author: fjahanian
Date: Fri Jun 19 14:55:27 2009
New Revision: 73782

URL: http://llvm.org/viewvc/llvm-project?rev=73782&view=rev
Log:
Patch for implementation of C++'s object model. This is
work in progress.

Added:
    cfe/trunk/test/SemaCXX/default-contructor-initializers.cpp
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/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jun 19 14:55:27 2009
@@ -439,6 +439,9 @@
     TemplateOrInstantiation = Template;
   }
 
+  /// getDefaultConstructor - Returns the default constructor for this class
+  CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
+  
   /// getDestructor - Returns the destructor decl for this class.
   const CXXDestructorDecl *getDestructor(ASTContext &Context);
   
@@ -638,6 +641,10 @@
   /// explicitly defaulted (i.e., defined with " = default") will have
   /// @c !Implicit && ImplicitlyDefined.
   bool ImplicitlyDefined : 1;
+  
+  /// ImplicitMustBeDefined - Implicit constructor was used to create an 
+  /// object of its class type. It must be defined.
+  bool ImplicitMustBeDefined : 1;
 
   /// FIXME: Add support for base and member initializers.
 
@@ -645,7 +652,8 @@
                      DeclarationName N, QualType T,
                      bool isExplicit, bool isInline, bool isImplicitlyDeclared)
     : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
-      Explicit(isExplicit), ImplicitlyDefined(false) { 
+      Explicit(isExplicit), ImplicitlyDefined(false),  
+      ImplicitMustBeDefined(false) { 
     setImplicit(isImplicitlyDeclared);
   }
 
@@ -676,6 +684,17 @@
     ImplicitlyDefined = ID; 
   }
 
+  /// isImplicitMustBeDefined - Whether a definition must be synthesized for
+  /// the implicit constructor.
+  bool isImplicitMustBeDefined() const {
+    return isImplicit() && ImplicitMustBeDefined;
+  }
+  
+  /// setImplicitMustBeDefined - constructor must be implicitly defined.
+  void setImplicitMustBeDefined() {
+    ImplicitMustBeDefined = true;
+  }
+  
   /// isDefaultConstructor - Whether this constructor is a default
   /// constructor (C++ [class.ctor]p5), which can be used to
   /// default-initialize a class of this type.

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 19 14:55:27 2009
@@ -573,6 +573,14 @@
 def err_param_default_argument_nonfunc : Error<
   "default arguments can only be specified for parameters in a function "
   "declaration">;
+def err_defining_default_ctor : Error<
+  "cannot define the default constructor for %0, because %1 does not "
+  "have any default constructor">;
+def not_previous_class_decl : Note<
+  "class %0 declared here">;
+def err_unintialized_member : Error<
+  "cannot define the default constructor for %0, because of "
+  "unintialized %select{reference|const}1 member">;
 
 def err_use_of_default_argument_to_function_declared_later : Error<
   "use of default argument to function %0 that is declared later in class %1">;

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jun 19 14:55:27 2009
@@ -184,10 +184,28 @@
   Conversions.addOverload(ConvDecl);
 }
 
+
+CXXConstructorDecl *
+CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
+  QualType ClassType = Context.getTypeDeclType(this);
+  DeclarationName ConstructorName
+    = Context.DeclarationNames.getCXXConstructorName(
+                      Context.getCanonicalType(ClassType.getUnqualifiedType()));
+  
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName);
+       Con != ConEnd; ++Con) {
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+    if (Constructor->isDefaultConstructor())
+      return Constructor;
+  }
+  return 0;
+}
+
 const CXXDestructorDecl *
 CXXRecordDecl::getDestructor(ASTContext &Context) {
   QualType ClassType = Context.getTypeDeclType(this);
-
+  
   DeclarationName Name 
     = Context.DeclarationNames.getCXXDestructorName(ClassType);
 

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Jun 19 14:55:27 2009
@@ -1533,6 +1533,11 @@
                                     CXXConstructorDecl *Constructor,
                                     QualType DeclInitType, 
                                     Expr **Exprs, unsigned NumExprs);
+  
+  /// DefineImplicitDefaultConstructor - Checks for feasibilityt of 
+  /// defining this constructor as the default constructor.
+  void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                        CXXConstructorDecl *Constructor);
 
   /// MaybeBindToTemporary - If the passed in expression has a record type with
   /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 19 14:55:27 2009
@@ -2732,8 +2732,12 @@
                                                  IK_Default);
         if (!Constructor)
           Var->setInvalidDecl();
-        else if (!RD->hasTrivialConstructor()) 
-          InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+        else  { 
+          if (!RD->hasTrivialConstructor())
+            InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+            // Check for valid construction.
+            DefineImplicitDefaultConstructor(Var->getLocation(), Constructor);
+        }
       }
     }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jun 19 14:55:27 2009
@@ -1793,7 +1793,7 @@
     return DeclPtrTy();
   }
   
-  NamespaceAliasDecl *AliasDecl = 
+  NamespaceAliasDecl *AliasDecl =
     NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, 
                                Alias, SS.getRange(), 
                                (NestedNameSpecifier *)SS.getScopeRep(),
@@ -1803,6 +1803,80 @@
   return DeclPtrTy::make(AliasDecl);
 }
 
+void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                            CXXConstructorDecl *Constructor) {
+  if (!Constructor->isDefaultConstructor() ||
+      !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined())
+    return;
+  
+  CXXRecordDecl *ClassDecl
+    = cast<CXXRecordDecl>(Constructor->getDeclContext());
+  assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
+  // Before the implicitly-declared default constructor for a class is 
+  // implicitly defined, all the implicitly-declared default constructors
+  // for its base class and its non-static data members shall have been
+  // implicitly defined.
+  bool err = false;
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+       Base != ClassDecl->bases_end(); ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+    if (!BaseClassDecl->hasTrivialConstructor()) {
+      if (CXXConstructorDecl *BaseCtor = 
+            BaseClassDecl->getDefaultConstructor(Context)) {
+        if (BaseCtor->isImplicit())
+          BaseCtor->setImplicitMustBeDefined();
+      }
+      else {
+        Diag(CurrentLocation, diag::err_defining_default_ctor) 
+          << ClassDecl->getNameAsCString() << BaseClassDecl->getNameAsCString();
+        Diag(BaseClassDecl->getLocation(), diag::not_previous_class_decl) 
+              << BaseClassDecl->getNameAsCString();
+        err = true;
+      }
+    }
+  }
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+       Field != ClassDecl->field_end(Context);
+       ++Field) {
+    QualType FieldType = Context.getCanonicalType((*Field)->getType());
+    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+      FieldType = Array->getElementType();
+    if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+      CXXRecordDecl *FieldClassDecl
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (!FieldClassDecl->hasTrivialConstructor())
+        if (CXXConstructorDecl *FieldCtor = 
+            FieldClassDecl->getDefaultConstructor(Context)) {
+          if (FieldCtor->isImplicit())
+            FieldCtor->setImplicitMustBeDefined();
+        }
+        else {
+          Diag(CurrentLocation, diag::err_defining_default_ctor) 
+          << ClassDecl->getNameAsCString() << 
+              FieldClassDecl->getNameAsCString();
+          Diag(FieldClassDecl->getLocation(), diag::not_previous_class_decl) 
+          << FieldClassDecl->getNameAsCString();
+          err = true;
+        }
+      }
+    else if (FieldType->isReferenceType()) {
+      Diag(CurrentLocation, diag::err_unintialized_member) 
+        << ClassDecl->getNameAsCString() << 0;
+      Diag((*Field)->getLocation(), diag::note_declared_at);
+      err = true;
+    }
+    else if (FieldType.isConstQualified()) {
+      Diag(CurrentLocation, diag::err_unintialized_member) 
+        << ClassDecl->getNameAsCString() << 1;
+       Diag((*Field)->getLocation(), diag::note_declared_at);
+      err = true;
+    }
+  }
+  if (!err)
+    Constructor->setImplicitMustBeDefined();  
+}
+
 void Sema::InitializeVarWithConstructor(VarDecl *VD, 
                                         CXXConstructorDecl *Constructor,
                                         QualType DeclInitType, 
@@ -1878,6 +1952,9 @@
       VDecl->setCXXDirectInitializer(true);
       InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, 
                                    (Expr**)Exprs.release(), NumExprs);
+      // An implicitly-declared default constructor for a class is implicitly
+      // defined when it is used to creat an object of its class type.
+      DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor);
     }
     return;
   }

Added: cfe/trunk/test/SemaCXX/default-contructor-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default-contructor-initializers.cpp?rev=73782&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/default-contructor-initializers.cpp (added)
+++ cfe/trunk/test/SemaCXX/default-contructor-initializers.cpp Fri Jun 19 14:55:27 2009
@@ -0,0 +1,56 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct X1 { // has no implicit default constructor
+   X1(int);
+};
+
+struct X2  : X1 {  // expected-note {{class X2 declared here}} \
+                  //  expected-note {{class X2 declared here}}
+   X2(int);
+};
+
+struct X3 : public X2 {
+};
+X3 x3;  // expected-error {{cannot define the default constructor for X3, because X2 does not have any default constructor}}
+
+
+struct X4 {
+  X2 x2; 
+  X2 & rx2; // expected-note {{declared at}}
+};
+
+X4 x4; // expected-error {{cannot define the default constructor for X4, because X2 does not have any default constructor}} \
+       // expected-error {{cannot define the default constructor for X4, because of unintialized reference member}}
+
+
+struct Y1 { // has no implicit default constructor
+   Y1(int);
+};
+
+struct Y2  : Y1 { 
+   Y2(int);
+   Y2();
+};
+
+struct Y3 : public Y2 {
+};
+Y3 y3; 
+
+struct Y4 {
+  Y2 y2; 
+};
+
+Y4 y4;
+
+// More tests
+
+
+struct Z1 {
+        int& z; // expected-note {{declared at}}
+  	const int c1; // expected-note {{declared at}}
+  	volatile int v1;
+};
+
+Z1 z1;  // expected-error {{cannot define the default constructor for Z1, because of unintialized const member}} \
+        // expected-error {{cannot define the default constructor for Z1, because of unintialized reference member}}
+





More information about the cfe-commits mailing list