r210954 - A non-trivial array-fill expression isn't necessarily a CXXConstructExpr. It
Richard Smith
richard-llvm at metafoo.co.uk
Fri Jun 13 16:04:50 PDT 2014
Author: rsmith
Date: Fri Jun 13 18:04:49 2014
New Revision: 210954
URL: http://llvm.org/viewvc/llvm-project?rev=210954&view=rev
Log:
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).
Modified:
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=210954&r1=210953&r2=210954&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Fri Jun 13 18:04:49 2014
@@ -370,6 +370,29 @@ AggExprEmitter::VisitCXXStdInitializerLi
}
}
+/// \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:
}
// 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
Modified: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp?rev=210954&r1=210953&r2=210954&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Fri Jun 13 18:04:49 2014
@@ -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] = {};
+}
More information about the cfe-commits
mailing list