[clang] eff57ef - [clang][CodeGen] Fix assertion failure with #embed in array new-expression initializers (#218262)

via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 9 09:48:59 PDT 2026


Author: Akash Manna
Date: 2026-09-09T16:48:54Z
New Revision: eff57ef78633c2eff5ae2cb7e4fa8e11e14d4b46

URL: https://github.com/llvm/llvm-project/commit/eff57ef78633c2eff5ae2cb7e4fa8e11e14d4b46
DIFF: https://github.com/llvm/llvm-project/commit/eff57ef78633c2eff5ae2cb7e4fa8e11e14d4b46.diff

LOG: [clang][CodeGen] Fix assertion failure with #embed in array new-expression initializers (#218262)

Fixes #128985

An `EmbedExpr` in a semantic initializer list can represent many array
elements at once, and every consumer of such lists has to expand it. The
array `new` emitter, `EmitNewArrayInitializer`, never did: it counted
the `EmbedExpr` as one element and emitted it through the scalar path,
hitting `assert(E->getDataElementCount() == 1)`. The undercount also
made the runtime minimum allocation check too lax and miscomputed the
trailing zero-fill size.

`Codegen` now emits one store per embed data element, converted to the
element type, and counts initializers with
`getNumInitsWithEmbedExpanded()` in both places. That helper also
learned to look through implicit casts, since Sema wraps a multi-element
`EmbedExpr` in a conversion when the element type isn't `int` — the
other embed consumers already strip casts before checking.

LLM tools were used for this contribution. I've reviewed, built, and
tested the change myself before pushing to GitHub.

Added: 
    clang/test/CodeGenCXX/GH128985.cpp
    clang/test/CodeGenCXX/Inputs/embed-data.txt
    clang/test/SemaCXX/GH128985.cpp

Modified: 
    clang/docs/ReleaseNotes.md
    clang/include/clang/AST/Expr.h
    clang/lib/CodeGen/CGExprCXX.cpp
    clang/lib/Sema/SemaInit.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 679a603d58ac0..4eb356997b8c1 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -553,6 +553,10 @@ features cannot lower the translation-unit ABI level;
 
 - Fixed an issue where `__typeof__` incorrectly rejected cv-qualified function types.
 
+- Fixed an assertion failure when `#embed` was used in the braced initializer
+  of an array new-expression, or of an array whose elements are of class type.
+  (#GH128985)
+
 - Fixed a bug where top-level CV qualifiers (such as ``const``) were dropped from pointers modified by Microsoft pointer attributes (like ``__ptr32`` and ``__ptr64``) and WebAssembly's ``__funcref``.
 
 - Fixed a bug where we accepted ``__super`` being qualified by a scope specifier, causing codegen to assertion fail elsewhere. (#GH212988)

diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 535086a6c2aa3..c03c88232e13d 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -5175,7 +5175,7 @@ struct EmbedDataStorage {
 ///  { {EE(9th and 10th element), { zeroinitializer }}}
 ///
 /// EmbedExpr inside of a semantic initializer list and referencing more than
-/// one element can only appear for arrays of scalars.
+/// one element can only appear for arrays of integer or floating-point type.
 class EmbedExpr final : public Expr {
   SourceLocation EmbedKeywordLoc;
   IntegerLiteral *FakeChildNode = nullptr;
@@ -5389,7 +5389,7 @@ class InitListExpr : public Expr {
   unsigned getNumInitsWithEmbedExpanded() const {
     unsigned Sum = InitExprs.size();
     for (auto *IE : InitExprs)
-      if (auto *EE = dyn_cast<EmbedExpr>(IE))
+      if (auto *EE = dyn_cast<EmbedExpr>(cast<Expr>(IE)->IgnoreParenImpCasts()))
         Sum += EE->getDataElementCount() - 1;
     return Sum;
   }

diff  --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index e400a5c5a49c5..97bfcd7bda4e8 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1103,7 +1103,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
 
     ArrayRef<const Expr *> InitExprs =
         ILE ? ILE->inits() : CPLIE->getInitExprs();
-    InitListElements = InitExprs.size();
+    InitListElements =
+        ILE ? ILE->getNumInitsWithEmbedExpanded() : InitExprs.size();
 
     // If this is a multi-dimensional array new, we will initialize multiple
     // elements with each init list element.
@@ -1138,6 +1139,14 @@ void CodeGenFunction::EmitNewArrayInitializer(
 
     CharUnits StartAlign = CurPtr.getAlignment();
     unsigned i = 0;
+    auto AdvanceToNextElement = [&]() {
+      CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(),
+                                                 CurPtr.emitRawPointer(*this),
+                                                 Builder.getSize(1),
+                                                 "array.exp.next"),
+                       CurPtr.getElementType(),
+                       StartAlign.alignmentAtOffset((++i) * ElementSize));
+    };
     for (const Expr *IE : InitExprs) {
       // Tell the cleanup that it needs to destroy up to this
       // element.  TODO: some of these stores can be trivially
@@ -1145,17 +1154,32 @@ void CodeGenFunction::EmitNewArrayInitializer(
       if (EndOfInit.isValid()) {
         Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit);
       }
+      // A multi-element EmbedExpr initializes several array elements at once.
+      // A single-element embed can be wrapped in a conversion to a non-scalar
+      // element type (e.g. _Complex) and is emitted like any other
+      // initializer.
+      const auto *EmbedS = dyn_cast<EmbedExpr>(IE->IgnoreParenImpCasts());
+      if (EmbedS && EmbedS->getDataElementCount() > 1) {
+        const StringLiteral *SL = EmbedS->getDataStringLiteral();
+        llvm::Type *DataTy = ConvertType(EmbedS->getType());
+        for (unsigned I = EmbedS->getStartingElementPos(),
+                      End = I + EmbedS->getDataElementCount();
+             I != End; ++I) {
+          llvm::Value *Val = EmitScalarConversion(
+              llvm::ConstantInt::get(DataTy, SL->getCodeUnit(I)),
+              EmbedS->getType(), ElementType, EmbedS->getLocation());
+          EmitStoreOfScalar(Val, MakeAddrLValue(CurPtr, ElementType),
+                            /*isInit=*/true);
+          AdvanceToNextElement();
+        }
+        continue;
+      }
       // FIXME: If the last initializer is an incomplete initializer list for
       // an array, and we have an array filler, we can fold together the two
       // initialization loops.
       StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr,
                               AggValueSlot::DoesNotOverlap);
-      CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(),
-                                                 CurPtr.emitRawPointer(*this),
-                                                 Builder.getSize(1),
-                                                 "array.exp.next"),
-                       CurPtr.getElementType(),
-                       StartAlign.alignmentAtOffset((++i) * ElementSize));
+      AdvanceToNextElement();
     }
 
     // The remaining elements are filled with the array filler expression.
@@ -1591,7 +1615,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
           cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe())
               ->getZExtSize();
     } else if (ILE || CPLIE) {
-      minElements = ILE ? ILE->getNumInits() : CPLIE->getInitExprs().size();
+      minElements = ILE ? ILE->getNumInitsWithEmbedExpanded()
+                        : CPLIE->getInitExprs().size();
     }
   }
 

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 48ce51863c2c0..1ff66e0d927df 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -562,7 +562,9 @@ class InitListChecker {
     // Reference just one if we're initializing a single scalar.
     uint64_t ElsCount = 1;
     // Otherwise try to fill whole array with embed data.
-    if (Entity.getKind() == InitializedEntity::EK_ArrayElement) {
+    if (Entity.getKind() == InitializedEntity::EK_ArrayElement &&
+        (Entity.getType()->isIntegerType() ||
+         Entity.getType()->isRealFloatingType())) {
       unsigned ArrIndex = Entity.getElementIndex();
       auto *AType =
           SemaRef.Context.getAsArrayType(Entity.getParent()->getType());

diff  --git a/clang/test/CodeGenCXX/GH128985.cpp b/clang/test/CodeGenCXX/GH128985.cpp
new file mode 100644
index 0000000000000..a1d813cc43dfd
--- /dev/null
+++ b/clang/test/CodeGenCXX/GH128985.cpp
@@ -0,0 +1,234 @@
+// RUN: %clang_cc1 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s
+
+// embed-data.txt contains "0123456789" (48 ... 57) without a trailing newline.
+
+struct S {
+  int a, b;
+};
+
+struct A {
+  A(char);
+};
+
+// CHECK-LABEL: define {{.*}}void @_Z2f1i(
+// CHECK: icmp ult i64 %{{.*}}, 4
+// CHECK: %[[A1:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 48, ptr %[[A1]]
+// CHECK: %[[F1E1:.*]] = getelementptr inbounds i32, ptr %[[A1]], i64 1
+// CHECK: store i32 49, ptr %[[F1E1]]
+// CHECK: %[[F1E2:.*]] = getelementptr inbounds i32, ptr %[[F1E1]], i64 1
+// CHECK: store i32 50, ptr %[[F1E2]]
+// CHECK: %[[F1E3:.*]] = getelementptr inbounds i32, ptr %[[F1E2]], i64 1
+// CHECK: store i32 51, ptr %[[F1E3]]
+// CHECK: %[[F1REST:.*]] = sub i64 %{{.*}}, 16
+// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F1REST]], i1 false)
+void f1(int x) {
+  int *p = new int[x]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z2f2i(
+// CHECK: icmp ult i64 %{{.*}}, 4
+// CHECK: %[[A2:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 500, ptr %[[A2]]
+// CHECK: %[[F2E1:.*]] = getelementptr inbounds i32, ptr %[[A2]], i64 1
+// CHECK: store i32 48, ptr %[[F2E1]]
+// CHECK: %[[F2E2:.*]] = getelementptr inbounds i32, ptr %[[F2E1]], i64 1
+// CHECK: store i32 49, ptr %[[F2E2]]
+// CHECK: %[[F2E3:.*]] = getelementptr inbounds i32, ptr %[[F2E2]], i64 1
+// CHECK: store i32 600, ptr %[[F2E3]]
+// CHECK: %[[F2REST:.*]] = sub i64 %{{.*}}, 16
+// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F2REST]], i1 false)
+void f2(int x) {
+  int *p = new int[x]{
+    500,
+#embed <embed-data.txt> limit(2) suffix(, 600)
+  };
+}
+
+// char arrays go through the string literal initialization path.
+// CHECK-LABEL: define {{.*}}void @_Z2f3i(
+// CHECK: icmp ult i64 %{{.*}}, 4
+// CHECK: %[[A3:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[A3]], ptr align 1 @{{.*}}, i64 4, i1 false)
+// CHECK: %[[F3END:.*]] = getelementptr inbounds i8, ptr %[[A3]], i64 4
+// CHECK: %[[F3REST:.*]] = sub i64 %{{.*}}, 4
+// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %[[F3END]], i8 0, i64 %[[F3REST]], i1 false)
+void f3(int x) {
+  char *p = new char[x]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z2f4i(
+// CHECK: icmp ult i64 %{{.*}}, 2
+// CHECK: %[[A4:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 900, ptr %[[A4]]
+// CHECK: %[[F4E1:.*]] = getelementptr inbounds i32, ptr %[[A4]], i64 1
+// CHECK: store i32 48, ptr %[[F4E1]]
+// CHECK: %[[F4REST:.*]] = sub i64 %{{.*}}, 8
+// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F4REST]], i1 false)
+void f4(int x) {
+  int *p = new int[x]{
+#embed <embed-data.txt> limit(1) prefix(900, )
+  };
+}
+
+// Constant size fully covered by the embed data: no trailing fill.
+// CHECK-LABEL: define {{.*}}void @_Z2f5v(
+// CHECK: %[[A5:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 48, ptr %[[A5]]
+// CHECK: %[[F5E1:.*]] = getelementptr inbounds i32, ptr %[[A5]], i64 1
+// CHECK: store i32 49, ptr %[[F5E1]]
+// CHECK: %[[F5E2:.*]] = getelementptr inbounds i32, ptr %[[F5E1]], i64 1
+// CHECK: store i32 50, ptr %[[F5E2]]
+// CHECK: %[[F5E3:.*]] = getelementptr inbounds i32, ptr %[[F5E2]], i64 1
+// CHECK: store i32 51, ptr %[[F5E3]]
+// CHECK-NOT: call void @llvm.memset
+// CHECK: ret void
+void f5() {
+  int *p = new int[4]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// Sema wraps the EmbedExpr in an implicit conversion to the element type.
+// CHECK-LABEL: define {{.*}}void @_Z2f6i(
+// CHECK: icmp ult i64 %{{.*}}, 4
+// CHECK: %[[A6:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i64 48, ptr %[[A6]]
+// CHECK: %[[F6E1:.*]] = getelementptr inbounds i64, ptr %[[A6]], i64 1
+// CHECK: store i64 49, ptr %[[F6E1]]
+// CHECK: %[[F6E2:.*]] = getelementptr inbounds i64, ptr %[[F6E1]], i64 1
+// CHECK: store i64 50, ptr %[[F6E2]]
+// CHECK: %[[F6E3:.*]] = getelementptr inbounds i64, ptr %[[F6E2]], i64 1
+// CHECK: store i64 51, ptr %[[F6E3]]
+// CHECK: %[[F6REST:.*]] = sub i64 %{{.*}}, 32
+// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %{{.*}}, i8 0, i64 %[[F6REST]], i1 false)
+void f6(int x) {
+  long long *p = new long long[x]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z2f7i(
+// CHECK: icmp ult i64 %{{.*}}, 2
+// CHECK: call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 48, ptr
+// CHECK: store i32 49, ptr
+// CHECK: store i32 50, ptr
+// CHECK: store i32 51, ptr
+// CHECK: %[[F7REST:.*]] = sub i64 %{{.*}}, 16
+// CHECK: call void @llvm.memset.p0.i64(ptr align {{[0-9]+}} %{{.*}}, i8 0, i64 %[[F7REST]], i1 false)
+void f7(int x) {
+  int (*p)[2] = new int[x][2]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z2f8i(
+// CHECK: icmp ult i64 %{{.*}}, 2
+// CHECK: call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 48, ptr
+// CHECK: store i32 49, ptr
+// CHECK: store i32 50, ptr
+// CHECK: store i32 51, ptr
+// CHECK: %[[F8REST:.*]] = sub i64 %{{.*}}, 16
+// CHECK: call void @llvm.memset.p0.i64(ptr align {{[0-9]+}} %{{.*}}, i8 0, i64 %[[F8REST]], i1 false)
+void f8(int x) {
+  S *p = new S[x]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z2f9i(
+// CHECK: icmp ult i64 %{{.*}}, 2
+// CHECK: call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store i32 48, ptr
+// CHECK: store i32 49, ptr
+// CHECK: store i32 50, ptr
+// CHECK: store i32 51, ptr
+// CHECK: store i32 52, ptr
+// CHECK: store i32 53, ptr
+// CHECK: store i32 54, ptr
+// CHECK: store i32 55, ptr
+// CHECK: %[[F9REST:.*]] = sub i64 %{{.*}}, 32
+// CHECK: call void @llvm.memset.p0.i64(ptr align {{[0-9]+}} %{{.*}}, i8 0, i64 %[[F9REST]], i1 false)
+void f9(int x) {
+  S (*p)[2] = new S[x][2]{
+#embed <embed-data.txt> limit(8)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z3f10v(
+// CHECK: %[[A10:.*]] = call {{.*}}ptr @_Znam(i64 noundef 16)
+// CHECK: store i32 48, ptr %[[A10]]
+// CHECK: %[[F10E1:.*]] = getelementptr inbounds i32, ptr %[[A10]], i64 1
+// CHECK: store i32 49, ptr %[[F10E1]]
+// CHECK: %[[F10E2:.*]] = getelementptr inbounds i32, ptr %[[F10E1]], i64 1
+// CHECK: store i32 50, ptr %[[F10E2]]
+// CHECK: %[[F10E3:.*]] = getelementptr inbounds i32, ptr %[[F10E2]], i64 1
+// CHECK: store i32 51, ptr %[[F10E3]]
+// CHECK-NOT: call void @llvm.memset
+// CHECK: ret void
+void f10() {
+  int *p = new int[]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z3f11i(
+// CHECK: icmp ult i64 %{{.*}}, 4
+// CHECK: %[[A11:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
+// CHECK: store float 4.800000e+01, ptr %[[A11]]
+// CHECK: %[[F11E1:.*]] = getelementptr inbounds float, ptr %[[A11]], i64 1
+// CHECK: store float 4.900000e+01, ptr %[[F11E1]]
+// CHECK: %[[F11E2:.*]] = getelementptr inbounds float, ptr %[[F11E1]], i64 1
+// CHECK: store float 5.000000e+01, ptr %[[F11E2]]
+// CHECK: %[[F11E3:.*]] = getelementptr inbounds float, ptr %[[F11E2]], i64 1
+// CHECK: store float 5.100000e+01, ptr %[[F11E3]]
+// CHECK: %[[F11REST:.*]] = sub i64 %{{.*}}, 16
+// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F11REST]], i1 false)
+void f11(int x) {
+  float *p = new float[x]{
+#embed <embed-data.txt> limit(4)
+  };
+}
+
+// Class elements are constructed from one data element each.
+// CHECK-LABEL: define {{.*}}void @_Z3f12v(
+// CHECK: %[[A12:.*]] = call {{.*}}ptr @_Znam(i64 noundef 2)
+// CHECK: call void @_ZN1AC1Ec(ptr {{.*}}%[[A12]], i8 noundef signext 48)
+// CHECK: %[[F12E1:.*]] = getelementptr inbounds %struct.A, ptr %[[A12]], i64 1
+// CHECK: call void @_ZN1AC1Ec(ptr {{.*}}%[[F12E1]], i8 noundef signext 49)
+void f12() {
+  A *p = new A[]{
+#embed <embed-data.txt> limit(2)
+  };
+}
+
+// Complex elements are not integer or floating-point type, so Sema slices
+// the embed into single-element EmbedExprs wrapped in an int-to-complex
+// conversion, one per element.
+// CHECK-LABEL: define {{.*}}void @_Z3f13v(
+// CHECK: call {{.*}}ptr @_Znam(i64 noundef 32)
+// CHECK: store double 4.800000e+01, ptr
+// CHECK: store double 0.000000e+00, ptr
+// CHECK: store double 4.900000e+01, ptr
+// CHECK: store double 0.000000e+00, ptr
+void f13() {
+  _Complex double *p = new _Complex double[]{
+#embed <embed-data.txt> limit(2)
+  };
+}
+
+// CHECK-LABEL: define {{.*}}void @_Z3f14v(
+// CHECK: %[[A14:.*]] = call {{.*}}ptr @_Znam(i64 noundef 16)
+// CHECK: store double 4.800000e+01, ptr
+// CHECK: store double 0.000000e+00, ptr
+void f14() {
+  _Complex double *p = new _Complex double[]{
+#embed <embed-data.txt> limit(1)
+  };
+}

diff  --git a/clang/test/CodeGenCXX/Inputs/embed-data.txt b/clang/test/CodeGenCXX/Inputs/embed-data.txt
new file mode 100644
index 0000000000000..ad471007bd7f5
--- /dev/null
+++ b/clang/test/CodeGenCXX/Inputs/embed-data.txt
@@ -0,0 +1 @@
+0123456789
\ No newline at end of file

diff  --git a/clang/test/SemaCXX/GH128985.cpp b/clang/test/SemaCXX/GH128985.cpp
new file mode 100644
index 0000000000000..0d51e3e53582f
--- /dev/null
+++ b/clang/test/SemaCXX/GH128985.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c23-extensions %s
+
+struct S {
+  int a, b;
+};
+
+struct A {
+  A(char);
+};
+
+void f(int x) {
+  int *a = new int[2]{
+#embed __FILE__ limit(4)
+  // expected-error at -1 {{excess elements in array initializer}}
+  };
+
+  int *b = new int[4]{
+#embed __FILE__ limit(4)
+  };
+
+  int *c = new int[8]{
+#embed __FILE__ limit(4)
+  };
+
+  int *d = new int[x]{
+#embed __FILE__ limit(4)
+  };
+
+  int (*e)[2] = new int[2][2]{
+#embed __FILE__ limit(5)
+  // expected-error at -1 {{excess elements in array initializer}}
+  };
+
+  S *s = new S[1]{
+#embed __FILE__ limit(3)
+  // expected-error at -1 {{excess elements in array initializer}}
+  };
+
+  S *t = new S[x]{
+#embed __FILE__ limit(3)
+  };
+
+  A *u = new A[]{1, 2, 3,
+#embed __FILE__ limit(10)
+  };
+
+  A v[] = {1, 2, 3,
+#embed __FILE__ limit(10)
+  };
+
+  _Complex double *w = new _Complex double[]{
+#embed __FILE__ limit(10)
+  };
+}


        


More information about the cfe-commits mailing list