diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2014-03-19 20:38:17 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2014-03-19 20:38:17 +0000 |
commit | ff1805df9d4ed5b79ff9d1fef01ed1b485f605bb (patch) | |
tree | f38192e1a76c5fb198d59f1c9882b5207f652d9f | |
parent | 36642863577684ea1d4d6d615e85f2c8c20ded82 (diff) | |
download | llvm-ff1805df9d4ed5b79ff9d1fef01ed1b485f605bb.zip llvm-ff1805df9d4ed5b79ff9d1fef01ed1b485f605bb.tar.gz llvm-ff1805df9d4ed5b79ff9d1fef01ed1b485f605bb.tar.bz2 |
Merging r203025:
------------------------------------------------------------------------
r203025 | richard-llvm | 2014-03-05 15:32:50 -0800 (Wed, 05 Mar 2014) |
3 lines
PR19010: Make sure we initialize (empty) indirect base class subobjects
when
evaluating trivial default initialization of a literal class type.
llvm-svn: 204263
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 35 | ||||
-rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx11.cpp | 10 |
2 files changed, 22 insertions, 23 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 390cfe9..4cac4fa 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5089,16 +5089,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; @@ -5578,19 +5577,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/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 6724be7..d73ee45 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/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; } +} |