From: Nicola Gigante Date: Fri, 16 Dec 2011 22:57:37 +0000 (+0000) Subject: Fix an inconsistency in the syntactic form of InitListExpr in case of initialization... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8a93d27a507d9c455eb802a29dc572aa8577393a;p=clang Fix an inconsistency in the syntactic form of InitListExpr in case of initialization that involves a ConstructorConversion git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146766 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7dbf830431..18fd3876e7 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -171,6 +171,9 @@ class InitListChecker { bool hadError; bool VerifyOnly; // no diagnostics, no structure building bool AllowBraceElision; + Expr *LastCheckedSubobject; + unsigned LastCheckedSubobjectIndex; + std::map SyntacticToSemantic; InitListExpr *FullyStructuredList; @@ -470,7 +473,8 @@ 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) { + : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision), + LastCheckedSubobject(0), LastCheckedSubobjectIndex(0) { hadError = false; unsigned newIndex = 0; @@ -792,13 +796,40 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, if (Seq) { if (!VerifyOnly) { - ExprResult Result = - Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1)); - if (Result.isInvalid()) - hadError = true; + // 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(); + } + + LastCheckedSubobject = ResultExpr; + LastCheckedSubobjectIndex = Index; + } + + // Update the syntactic list + IList->setInit(Index, ResultExpr); UpdateStructuredListElement(StructuredList, StructuredIndex, - Result.takeAs()); + ResultExpr); } ++Index; return;