Revert r146766, and add a testcase for which it introduced a wrong-code bug.

llvm-svn: 146961
This commit is contained in:
Richard Smith 2011-12-20 04:00:21 +00:00
parent a379b18173
commit 0f8ede1654
2 changed files with 32 additions and 37 deletions

View File

@ -171,9 +171,6 @@ class InitListChecker {
bool hadError;
bool VerifyOnly; // no diagnostics, no structure building
bool AllowBraceElision;
Expr *LastCheckedSubobject;
unsigned LastCheckedSubobjectIndex;
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
@ -473,8 +470,7 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
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;
@ -796,40 +792,13 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
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;

View File

@ -0,0 +1,26 @@
// 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))