summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-01-10 04:32:03 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-01-10 04:32:03 +0000
commit1bc5c2c7efe8652f5b0599d52ad5fa2b563dfc28 (patch)
tree91aea2bc7f27d0ffc08f212d95983c8980199428 /clang/lib/AST/ExprConstant.cpp
parentf714d3d7f217d06ebddd7ab6c0fc0019e59d5ea7 (diff)
downloadbcm5719-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.cpp18
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)))
OpenPOWER on IntegriCloud