Patch for implementation of C++'s object model. This is
work in progress.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73782 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a37929c..fd1cc04 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
   }