summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorMatheus Izvekov <mizvekov@gmail.com>2021-09-15 01:46:30 +0200
committerTom Stellard <tstellar@redhat.com>2021-09-24 09:18:10 -0700
commitd7b669b3a30345cfcdb2fde2af6f48aa4b94845d (patch)
treea12dc3351fad673c0c38c047efd9b3627629c1ae /clang/lib/AST/ExprConstant.cpp
parentee6913cc8317c08b603daed64b07a17a95ec926a (diff)
downloadllvmorg-13.0.0-rc4.tar.gz
[clang] don't mark as Elidable CXXConstruct expressions used in NRVOllvmorg-13.0.0-rc4llvmorg-13.0.0
See PR51862. The consumers of the Elidable flag in CXXConstructExpr assume that an elidable construction just goes through a single copy/move construction, so that the source object is immediately passed as an argument and is the same type as the parameter itself. With the implementation of P2266 and after some adjustments to the implementation of P1825, we started (correctly, as per standard) allowing more cases where the copy initialization goes through user defined conversions. With this patch we stop using this flag in NRVO contexts, to preserve code that relies on that assumption. This causes no known functional changes, we just stop firing some asserts in a cople of included test cases. Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D109800 (cherry picked from commit d9308aa39b236064a680ca57178af3c731e13e49)
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp15
1 files changed, 12 insertions, 3 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 01c0168d61a4..8fe0061a9025 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9931,10 +9931,19 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
return false;
// Avoid materializing a temporary for an elidable copy/move constructor.
- if (E->isElidable() && !ZeroInit)
- if (const MaterializeTemporaryExpr *ME
- = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
+ if (E->isElidable() && !ZeroInit) {
+ // FIXME: This only handles the simplest case, where the source object
+ // is passed directly as the first argument to the constructor.
+ // This should also handle stepping though implicit casts and
+ // and conversion sequences which involve two steps, with a
+ // conversion operator followed by a converting constructor.
+ const Expr *SrcObj = E->getArg(0);
+ assert(SrcObj->isTemporaryObject(Info.Ctx, FD->getParent()));
+ assert(Info.Ctx.hasSameUnqualifiedType(E->getType(), SrcObj->getType()));
+ if (const MaterializeTemporaryExpr *ME =
+ dyn_cast<MaterializeTemporaryExpr>(SrcObj))
return Visit(ME->getSubExpr());
+ }
if (ZeroInit && !ZeroInitialization(E, T))
return false;