]> granicus.if.org Git - clang/commitdiff
A non-trivial array-fill expression isn't necessarily a CXXConstructExpr. It
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 13 Jun 2014 23:04:49 +0000 (23:04 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 13 Jun 2014 23:04:49 +0000 (23:04 +0000)
could be an InitListExpr that runs constructors in C++11 onwards. Fixes a
recent regression (introduced in r210091).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210954 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprAgg.cpp
test/CodeGenCXX/cxx11-initializer-aggregate.cpp

index 4cb81b54cd59166ba2f08ebce2059a5692d7254f..b1406cdd7ccab50519c9e3a89c46520c1fd35c8a 100644 (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
index 99994bd9ffaae620d44b1d50e66b1687941ff123..94f305855b418158e08cfe2429c5bcedd2584fce 100644 (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] = {};
+}