Patch to build AST for ctor's initializer list according to
semantics of order of construction [class.init].



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75649 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index cba3dea..b88ea17 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -1232,6 +1232,8 @@
                                     SourceLocation ColonLoc,
                                     MemInitTy **MemInits, unsigned NumMemInits){
   }
+ 
+ virtual void ActOnDefaultInitializers(DeclPtrTy ConstructorDecl) {}
 
   /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators
   /// are parsed but *before* parsing of inline method definitions.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 3ffeb57..607c4aa 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -482,12 +482,81 @@
                                     ASTContext &C,
                                     CXXBaseOrMemberInitializer **Initializers,
                                     unsigned NumInitializers) {
+  // We need to build the initializer AST according to order of construction
+  // and not what user specified in the Initializers list.
+  // FIXME. We probably don't need this. But it is cleaner.
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext());
+  llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
+  // Push virtual bases before others.
+  for (CXXRecordDecl::base_class_iterator VBase =
+       ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+    const Type * T = VBase->getType()->getAsRecordType();
+    unsigned int i = 0;
+    for (i = 0; i < NumInitializers; i++) {
+      CXXBaseOrMemberInitializer *Member = Initializers[i];
+      if (Member->isBaseInitializer() &&
+          Member->getBaseClass() == T) {
+        AllToInit.push_back(Member);
+        break;
+      }
+    }
+    if (i == NumInitializers) {
+      CXXBaseOrMemberInitializer *Member = 
+        new CXXBaseOrMemberInitializer(VBase->getType(), 0, 0,SourceLocation());
+      AllToInit.push_back(Member);
+    }
+  }
+  for (CXXRecordDecl::base_class_iterator Base =
+       ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Virtuals are in the virtual base list and already constructed.
+    if (Base->isVirtual())
+      continue;
+    const Type * T = Base->getType()->getAsRecordType();
+    unsigned int i = 0;
+    for (i = 0; i < NumInitializers; i++) {
+      CXXBaseOrMemberInitializer *Member = Initializers[i];
+      if (Member->isBaseInitializer() && Member->getBaseClass() == T) {
+        AllToInit.push_back(Member);
+        break;
+      }
+    }
+    if (i == NumInitializers) {
+      CXXBaseOrMemberInitializer *Member = 
+        new CXXBaseOrMemberInitializer(Base->getType(), 0, 0, SourceLocation());
+      AllToInit.push_back(Member);
+    }
+  }
+  // non-static data members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    unsigned int i = 0;
+    for (i = 0; i < NumInitializers; i++) {
+      CXXBaseOrMemberInitializer *Member = Initializers[i];
+      if (Member->isMemberInitializer() && Member->getMember() == (*Field)) {
+        AllToInit.push_back(Member);
+        break;
+      }
+    }
+    if (i == NumInitializers) {
+      // FIXME. What do we do with arrays?
+      QualType FieldType = C.getCanonicalType((*Field)->getType());
+      if (FieldType->getAsRecordType()) {
+        CXXBaseOrMemberInitializer *Member = 
+          new CXXBaseOrMemberInitializer((*Field), 0, 0, SourceLocation());
+          AllToInit.push_back(Member);
+      }      
+    }
+  }
+  
+  NumInitializers = AllToInit.size();
   if (NumInitializers > 0) {
     NumBaseOrMemberInitializers = NumInitializers;
     BaseOrMemberInitializers = 
       new (C) CXXBaseOrMemberInitializer*[NumInitializers]; 
     for (unsigned Idx = 0; Idx < NumInitializers; ++Idx)
-      BaseOrMemberInitializers[Idx] = Initializers[Idx];
+      BaseOrMemberInitializers[Idx] = AllToInit[Idx];
   }
 }
 
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index af6fab7..a2324ab 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -171,6 +171,10 @@
     }
     if (Tok.is(tok::colon))
       ParseConstructorInitializer(LM.D);
+    else {
+      Actions.ActOnDefaultInitializers(LM.D);
+    }
+
     // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
     ParseFunctionStatementBody(LM.D);
   }
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 4344fde..e01bf23 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1468,6 +1468,7 @@
                                                     SourceLocation MemberLoc,
                                                     IdentifierInfo &Member,
                                                     DeclPtrTy ImplDecl);
+  virtual void ActOnDefaultInitializers(DeclPtrTy ConstructorDecl);
   bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
                                FunctionDecl *FDecl,
                                const FunctionProtoType *Proto,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 17726c6..7d039dc 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -902,6 +902,17 @@
   }
 }
 
+void Sema::ActOnDefaultInitializers(DeclPtrTy ConstructorDecl) {
+  if (!ConstructorDecl)
+    return;
+  
+  if (CXXConstructorDecl *Constructor 
+      = dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>()))
+    Constructor->setBaseOrMemberInitializers(Context, 
+                                           (CXXBaseOrMemberInitializer **)0, 0);
+                                           
+}
+
 namespace {
   /// PureVirtualMethodCollector - traverses a class and its superclasses
   /// and determines if it has any pure virtual methods.