From: Richard Smith Date: Wed, 5 Mar 2014 23:32:50 +0000 (+0000) Subject: PR19010: Make sure we initialize (empty) indirect base class subobjects when X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=502fd5fd81693b223fa2550989be5eb383b3b577;p=clang PR19010: Make sure we initialize (empty) indirect base class subobjects when evaluating trivial default initialization of a literal class type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203025 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index e172c91478..92eef5e6fc 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -5117,16 +5117,15 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { if (!Result.isUninit()) return true; - if (ZeroInit) - return ZeroInitialization(E); - - const CXXRecordDecl *RD = FD->getParent(); - if (RD->isUnion()) - Result = APValue((FieldDecl*)0); - else - Result = APValue(APValue::UninitStruct(), RD->getNumBases(), - std::distance(RD->field_begin(), RD->field_end())); - return true; + // We can get here in two different ways: + // 1) We're performing value-initialization, and should zero-initialize + // the object, or + // 2) We're performing default-initialization of an object with a trivial + // constexpr default constructor, in which case we should start the + // lifetimes of all the base subobjects (there can be no data member + // subobjects in this case) per [basic.life]p1. + // Either way, ZeroInitialization is appropriate. + return ZeroInitialization(E); } const FunctionDecl *Definition = 0; @@ -5606,19 +5605,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, if (HadZeroInit) return true; - if (ZeroInit) { - ImplicitValueInitExpr VIE(Type); - return EvaluateInPlace(*Value, Info, Subobject, &VIE); - } - - const CXXRecordDecl *RD = FD->getParent(); - if (RD->isUnion()) - *Value = APValue((FieldDecl*)0); - else - *Value = - APValue(APValue::UninitStruct(), RD->getNumBases(), - std::distance(RD->field_begin(), RD->field_end())); - return true; + // See RecordExprEvaluator::VisitCXXConstructExpr for explanation. + ImplicitValueInitExpr VIE(Type); + return EvaluateInPlace(*Value, Info, Subobject, &VIE); } const FunctionDecl *Definition = 0; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 4e61777643..574e9b389f 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1863,3 +1863,13 @@ namespace BuiltinStrlen { constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} expected-note {{one-past-the-end}} } + +namespace PR19010 { + struct Empty {}; + struct Empty2 : Empty {}; + struct Test : Empty2 { + constexpr Test() {} + Empty2 array[2]; + }; + void test() { constexpr Test t; } +}