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 | 1bc5c2c7efe8652f5b0599d52ad5fa2b563dfc28 (patch) | |
tree | 91aea2bc7f27d0ffc08f212d95983c8980199428 /clang/lib/AST/ExprConstant.cpp | |
parent | f714d3d7f217d06ebddd7ab6c0fc0019e59d5ea7 (diff) | |
download | bcm5719-llvm-1bc5c2c7efe8652f5b0599d52ad5fa2b563dfc28.tar.gz bcm5719-llvm-1bc5c2c7efe8652f5b0599d52ad5fa2b563dfc28.zip |
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.
llvm-svn: 147839
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1ad17ea376e..5fd710d90ec 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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))) |