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