diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-01-10 04:32:03 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-01-10 04:32:03 +0000 |
commit | 610a60c0e68e34db5a5247d6102e58f37510fef8 (patch) | |
tree | 291a098fbe45cc5feee92c9705a65cc57b577dd4 /lib/AST/ExprConstant.cpp | |
parent | 15e17aed79163d0d40ed7914f7fe992c400d93dd (diff) |
PR11724: Implement evaluation for constexpr defaulted trivial union copy/move
constructors. These are a special case whose behavior cannot be modeled as a
user-written constructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147839 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 1ad17ea376..5fd710d90e 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1854,8 +1854,22 @@ static bool HandleConstructorCall(const Expr *CallExpr, const LValue &This, return EvaluateConstantExpression(Result, Info, This, (*I)->getInit()); } - // Reserve space for the struct members. + // For a trivial copy or move constructor, perform an APValue copy. This is + // essential for unions, where the operations performed by the constructor + // cannot be represented by ctor-initializers. const CXXRecordDecl *RD = Definition->getParent(); + if (Definition->isDefaulted() && + ((Definition->isCopyConstructor() && RD->hasTrivialCopyConstructor()) || + (Definition->isMoveConstructor() && RD->hasTrivialMoveConstructor()))) { + LValue RHS; + RHS.setFrom(ArgValues[0]); + CCValue Value; + return HandleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), + RHS, Value) && + CheckConstantExpression(Info, CallExpr, Value, Result); + } + + // Reserve space for the struct members. if (!RD->isUnion() && Result.isUninit()) Result = APValue(APValue::UninitStruct(), RD->getNumBases(), std::distance(RD->field_begin(), RD->field_end())); @@ -3073,7 +3087,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) return false; - // FIXME: Elide the copy/move construction wherever we can. + // Avoid materializing a temporary for an elidable copy/move constructor. if (E->isElidable() && !ZeroInit) if (const MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0))) |