forked from OSchip/llvm-project
A non-trivial array-fill expression isn't necessarily a CXXConstructExpr. It
could be an InitListExpr that runs constructors in C++11 onwards. Fixes a recent regression (introduced in r210091). llvm-svn: 210954
This commit is contained in:
parent
a0cdc005dd
commit
8edda96296
|
@ -370,6 +370,29 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
|
|||
}
|
||||
}
|
||||
|
||||
/// \brief Determine if E is a trivial array filler, that is, one that is
|
||||
/// equivalent to zero-initialization.
|
||||
static bool isTrivialFiller(Expr *E) {
|
||||
if (!E)
|
||||
return true;
|
||||
|
||||
if (isa<ImplicitValueInitExpr>(E))
|
||||
return true;
|
||||
|
||||
if (auto *ILE = dyn_cast<InitListExpr>(E)) {
|
||||
if (ILE->getNumInits())
|
||||
return false;
|
||||
return isTrivialFiller(ILE->getArrayFiller());
|
||||
}
|
||||
|
||||
if (auto *Cons = dyn_cast_or_null<CXXConstructExpr>(E))
|
||||
return Cons->getConstructor()->isDefaultConstructor() &&
|
||||
Cons->getConstructor()->isTrivial();
|
||||
|
||||
// FIXME: Are there other cases where we can avoid emitting an initializer?
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Emit initialization of an array from an initializer list.
|
||||
void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
|
||||
QualType elementType, InitListExpr *E) {
|
||||
|
@ -435,13 +458,8 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
|
|||
}
|
||||
|
||||
// Check whether there's a non-trivial array-fill expression.
|
||||
// Note that this will be a CXXConstructExpr even if the element
|
||||
// type is an array (or array of array, etc.) of class type.
|
||||
Expr *filler = E->getArrayFiller();
|
||||
bool hasTrivialFiller = true;
|
||||
if (CXXConstructExpr *cons = dyn_cast_or_null<CXXConstructExpr>(filler))
|
||||
hasTrivialFiller = cons->getConstructor()->isDefaultConstructor() &&
|
||||
cons->getConstructor()->isTrivial();
|
||||
bool hasTrivialFiller = isTrivialFiller(filler);
|
||||
|
||||
// Any remaining elements need to be zero-initialized, possibly
|
||||
// using the filler expression. We can skip this if the we're
|
||||
|
|
|
@ -23,3 +23,22 @@ int &fn2(int &v) {
|
|||
// CHECK: call nonnull i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]])
|
||||
return B{v}.f();
|
||||
}
|
||||
|
||||
// CHECK: define {{.*}}@__cxx_global_var_init(
|
||||
//
|
||||
// CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev(
|
||||
// CHECK: getelementptr inbounds {{.*}}, i64 1
|
||||
// CHECK: br i1
|
||||
//
|
||||
// CHECK: getelementptr inbounds {{.*}}, i64 1
|
||||
// CHECK: icmp eq {{.*}}, i64 30
|
||||
// CHECK: br i1
|
||||
//
|
||||
// CHECK: call i32 @__cxa_atexit(
|
||||
namespace NonTrivialInit {
|
||||
struct A { A(); A(const A&) = delete; ~A(); };
|
||||
struct B { A a[20]; };
|
||||
// NB, this must be large enough to be worth memsetting for this test to be
|
||||
// meaningful.
|
||||
B b[30] = {};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue