Fix miscompile when performing template instantiation of non-dependent

doubly-nested implicit CXXConstructExprs.

Ensure that we transform the parameter initializer using
TransformInitializer rather than TransformExpr so that we properly strip
down and rebuild the initialization, including any necessary
CXXBindTemporaryExprs. Otherwise we can end up forgetting to destroy
temporary objects used to construct a constructor parameter.
This commit is contained in:
Richard Smith 2021-02-03 23:31:51 -08:00
parent 1029c82c1e
commit cde8d2fddb
2 changed files with 31 additions and 1 deletions

View File

@ -12241,7 +12241,8 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
(E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) &&
(!getDerived().DropCallArgument(E->getArg(0))) &&
!E->isListInitialization()))
return getDerived().TransformExpr(E->getArg(0));
return getDerived().TransformInitializer(E->getArg(0),
/*DirectInit*/ false);
TemporaryBase Rebase(*this, /*FIXME*/ E->getBeginLoc(), DeclarationName());

View File

@ -0,0 +1,29 @@
// RUN: %clang_cc1 -std=c++14 %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -std=c++17 %s -emit-llvm -o - | FileCheck %s
namespace std {
template<typename T> class initializer_list {
const T *data;
__SIZE_TYPE__ size;
public:
initializer_list();
};
}
namespace ParenBraceInitList {
struct Vector {
Vector(std::initializer_list<int>);
~Vector();
};
struct Base { Base(Vector) {} };
// CHECK: define {{.*}}18ParenBraceInitList1fILi0EE
template<int> void f() {
// CHECK: call {{.*}}18ParenBraceInitList6VectorC1
// CHECK: call {{.*}}18ParenBraceInitList6VectorD1
Base({0});
}
template void f<0>();
}