bool hadError;
bool VerifyOnly; // no diagnostics, no structure building
bool AllowBraceElision;
- Expr *LastCheckedSubobject;
- unsigned LastCheckedSubobjectIndex;
-
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T,
bool VerifyOnly, bool AllowBraceElision)
- : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision),
- LastCheckedSubobject(0), LastCheckedSubobjectIndex(0) {
+ : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) {
hadError = false;
unsigned newIndex = 0;
if (Seq) {
if (!VerifyOnly) {
- // struct S {
- // S(int);
- // };
- //
- // S s[] = { [0 ... 2] = 3 };
- //
- // In code like this, we want to perform the initialization and then
- // update the syntactic list with the result. However, we reach this
- // point once for each subobject, but the update needs
- // to be done only once for each syntactic element. For this reason,
- // the initialization result and its syntactic Index are cached in
- // LastCheckedSubobject and LastCheckedSubobjectIndex and reused until
- // we move to the next Index.
- Expr *ResultExpr = LastCheckedSubobject;
-
- if (!ResultExpr || Index != LastCheckedSubobjectIndex) {
- ExprResult Result = Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
-
- if (Result.isInvalid()) {
- hadError = true;
- ResultExpr = 0;
- } else {
- ResultExpr = Result.takeAs<Expr>();
- }
-
- LastCheckedSubobject = ResultExpr;
- LastCheckedSubobjectIndex = Index;
- }
-
- // Update the syntactic list
- IList->setInit(Index, ResultExpr);
+ ExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+ if (Result.isInvalid())
+ hadError = true;
UpdateStructuredListElement(StructuredList, StructuredIndex,
- ResultExpr);
+ Result.takeAs<Expr>());
}
++Index;
return;
--- /dev/null
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s
+
+struct A {
+ A(const char *);
+};
+
+// CHECK: @arr = global [3 x %struct.S] zeroinitializer
+// CHECK: @.str = {{.*}}constant [6 x i8] c"hello\00"
+// CHECK: @.str1 = {{.*}}constant [6 x i8] c"world\00"
+// CHECK: @.str2 = {{.*}}constant [8 x i8] c"goodbye\00"
+
+struct S {
+ int n;
+ A s;
+} arr[] = {
+ { 0, "hello" },
+ { 1, "world" },
+ { 2, "goodbye" }
+};
+
+// CHECK: store i32 0, i32* getelementptr inbounds ([3 x %struct.S]* @arr, i64 0, i64 0, i32 0)
+// CHECK: call void @_ZN1AC1EPKc(%struct.A* getelementptr inbounds ([3 x %struct.S]* @arr, i64 0, i64 0, i32 1), i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0))
+// CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.S]* @arr, i64 0, i64 1, i32 0)
+// CHECK: call void @_ZN1AC1EPKc(%struct.A* getelementptr inbounds ([3 x %struct.S]* @arr, i64 0, i64 1, i32 1), i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0))
+// CHECK: store i32 2, i32* getelementptr inbounds ([3 x %struct.S]* @arr, i64 0, i64 2, i32 0)
+// CHECK: call void @_ZN1AC1EPKc(%struct.A* getelementptr inbounds ([3 x %struct.S]* @arr, i64 0, i64 2, i32 1), i8* getelementptr inbounds ([8 x i8]* @.str2, i32 0, i32 0))