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:
Richard Smith 2014-06-13 23:04:49 +00:00
parent a0cdc005dd
commit 8edda96296
2 changed files with 43 additions and 6 deletions

View File

@ -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

View File

@ -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] = {};
}