When value-initializing a class with no user-defined constructors but
with a non-trivial default constructor, zero-initialize the storage
and then call the default constructor. Fixes PR5800.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91548 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index bca9ae9..3d03dfd 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1816,7 +1816,8 @@
   OwningExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc,
                                          QualType DeclInitType,
                                          CXXConstructorDecl *Constructor,
-                                         MultiExprArg Exprs);
+                                         MultiExprArg Exprs,
+                                         bool RequiresZeroInit = false);
 
   // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
   // the constructor can be elidable?
@@ -1824,7 +1825,8 @@
                                          QualType DeclInitType,
                                          CXXConstructorDecl *Constructor,
                                          bool Elidable,
-                                         MultiExprArg Exprs);
+                                         MultiExprArg Exprs,
+                                         bool RequiresZeroInit = false);
 
   OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
                                                QualType writtenTy,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 7eb1d9e..091c038 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3759,7 +3759,8 @@
 Sema::OwningExprResult
 Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                             CXXConstructorDecl *Constructor,
-                            MultiExprArg ExprArgs) {
+                            MultiExprArg ExprArgs,
+                            bool RequiresZeroInit) {
   bool Elidable = false;
 
   // C++ [class.copy]p15:
@@ -3785,7 +3786,7 @@
   }
 
   return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
-                               Elidable, move(ExprArgs));
+                               Elidable, move(ExprArgs), RequiresZeroInit);
 }
 
 /// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -3793,14 +3794,15 @@
 Sema::OwningExprResult
 Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                             CXXConstructorDecl *Constructor, bool Elidable,
-                            MultiExprArg ExprArgs) {
+                            MultiExprArg ExprArgs,
+                            bool RequiresZeroInit) {
   unsigned NumExprs = ExprArgs.size();
   Expr **Exprs = (Expr **)ExprArgs.release();
 
   MarkDeclarationReferenced(ConstructLoc, Constructor);
   return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
-                                        Constructor,
-                                        Elidable, Exprs, NumExprs));
+                                        Constructor, Elidable, Exprs, NumExprs, 
+                                        RequiresZeroInit));
 }
 
 Sema::OwningExprResult
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 20008a7..629ab9a 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -444,6 +444,9 @@
       if (Field->isUnnamedBitfield())
         continue;
 
+      if (hadError)
+        return;
+
       InitializedEntity MemberEntity 
         = InitializedEntity::InitializeMember(*Field, &Entity);
       if (Init >= NumInits || !ILE->getInit(Init)) {
@@ -477,7 +480,7 @@
           = InitSeq.Perform(SemaRef, MemberEntity, Kind, 
                             Sema::MultiExprArg(SemaRef, 0, 0));
         if (MemberInit.isInvalid()) {
-          hadError = 0;
+          hadError = true;
           return;
         }
 
@@ -529,6 +532,9 @@
 
   
   for (unsigned Init = 0; Init != NumElements; ++Init) {
+    if (hadError)
+      return;
+
     if (ElementEntity.getKind() == InitializedEntity::EK_ArrayOrVectorElement)
       ElementEntity.setElementIndex(Init);
 
@@ -546,7 +552,7 @@
         = InitSeq.Perform(SemaRef, ElementEntity, Kind, 
                           Sema::MultiExprArg(SemaRef, 0, 0));
       if (ElementInit.isInvalid()) {
-        hadError = 0;
+        hadError = true;
         return;
       }
 
@@ -585,7 +591,7 @@
   if (!hadError) {
     bool RequiresSecondPass = false;
     FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
-    if (RequiresSecondPass)
+    if (RequiresSecondPass && !hadError)
       FillInValueInitializations(Entity, FullyStructuredList, 
                                  RequiresSecondPass);
   }
@@ -2619,8 +2625,16 @@
       if (ClassDecl->hasUserDeclaredConstructor())
         return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
       
-      // FIXME: non-union class type w/ non-trivial default constructor gets
-      // zero-initialized, then constructor gets called.
+      // -- if T is a (possibly cv-qualified) non-union class type
+      //    without a user-provided constructor, then the object is
+      //    zero-initialized and, if T’s implicitly-declared default
+      //    constructor is non-trivial, that constructor is called.
+      if ((ClassDecl->getTagKind() == TagDecl::TK_class ||
+           ClassDecl->getTagKind() == TagDecl::TK_struct) &&
+          !ClassDecl->hasTrivialConstructor()) {
+        Sequence.AddZeroInitializationStep(Entity.getType().getType());
+        return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);        
+      }
     }
   }
 
@@ -3050,6 +3064,7 @@
     
   // Walk through the computed steps for the initialization sequence, 
   // performing the specified conversions along the way.
+  bool ConstructorInitRequiresZeroInit = false;
   for (step_iterator Step = step_begin(), StepEnd = step_end();
        Step != StepEnd; ++Step) {
     if (CurInit.isInvalid())
@@ -3216,7 +3231,8 @@
           
       // Build the an expression that constructs a temporary.
       CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, 
-                                        move_arg(ConstructorArgs));
+                                        move_arg(ConstructorArgs),
+                                        ConstructorInitRequiresZeroInit);
       if (CurInit.isInvalid())
         return S.ExprError();
           
@@ -3224,14 +3240,22 @@
     }
         
     case SK_ZeroInitialization: {
-      if (Kind.getKind() == InitializationKind::IK_Value &&
-          S.getLangOptions().CPlusPlus &&
-          !Kind.isImplicitValueInit())
+      step_iterator NextStep = Step;
+      ++NextStep;
+      if (NextStep != StepEnd && 
+          NextStep->Kind == SK_ConstructorInitialization) {
+        // The need for zero-initialization is recorded directly into
+        // the call to the object's constructor within the next step.
+        ConstructorInitRequiresZeroInit = true;
+      } else if (Kind.getKind() == InitializationKind::IK_Value &&
+                 S.getLangOptions().CPlusPlus &&
+                 !Kind.isImplicitValueInit()) {
         CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type,
                                                    Kind.getRange().getBegin(),
                                                     Kind.getRange().getEnd()));
-      else
+      } else {
         CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+      }
       break;
     }
     }