diff options
Diffstat (limited to 'clang/lib/Sema/TreeTransform.h')
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 143 |
1 files changed, 100 insertions, 43 deletions
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index f8b9b34ae7f..c653fb1d6e2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -450,8 +450,10 @@ public: /// TransformDefinition. However, in some cases (e.g., lambda expressions), /// the transformer itself has to transform the declarations. This routine /// can be overridden by a subclass that keeps track of such mappings. - void transformedLocalDecl(Decl *Old, Decl *New) { - TransformedLocalDecls[Old] = New; + void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> New) { + assert(New.size() == 1 && + "must override transformedLocalDecl if performing pack expansion"); + TransformedLocalDecls[Old] = New.front(); } /// Transform the definition of the given declaration. @@ -7122,7 +7124,7 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation()); if (!Promise) return StmtError(); - getDerived().transformedLocalDecl(S->getPromiseDecl(), Promise); + getDerived().transformedLocalDecl(S->getPromiseDecl(), {Promise}); ScopeInfo->CoroutinePromise = Promise; // Transform the implicit coroutine statements we built during the initial @@ -11176,33 +11178,80 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Transform any init-capture expressions before entering the scope of the // lambda body, because they are not semantically within that scope. typedef std::pair<ExprResult, QualType> InitCaptureInfoTy; - SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes; - InitCaptureExprsAndTypes.resize(E->explicit_capture_end() - - E->explicit_capture_begin()); + struct TransformedInitCapture { + // The location of the ... if the result is retaining a pack expansion. + SourceLocation EllipsisLoc; + // Zero or more expansions of the init-capture. + SmallVector<InitCaptureInfoTy, 4> Expansions; + }; + SmallVector<TransformedInitCapture, 4> InitCaptures; + InitCaptures.resize(E->explicit_capture_end() - E->explicit_capture_begin()); for (LambdaExpr::capture_iterator C = E->capture_begin(), CEnd = E->capture_end(); C != CEnd; ++C) { if (!E->isInitCapture(C)) continue; - EnterExpressionEvaluationContext EEEC( - getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - ExprResult NewExprInitResult = getDerived().TransformInitializer( - C->getCapturedVar()->getInit(), - C->getCapturedVar()->getInitStyle() == VarDecl::CallInit); - - if (NewExprInitResult.isInvalid()) - return ExprError(); - Expr *NewExprInit = NewExprInitResult.get(); + TransformedInitCapture &Result = InitCaptures[C - E->capture_begin()]; VarDecl *OldVD = C->getCapturedVar(); - QualType NewInitCaptureType = - getSema().buildLambdaInitCaptureInitialization( - C->getLocation(), OldVD->getType()->isReferenceType(), - OldVD->getIdentifier(), - C->getCapturedVar()->getInitStyle() != VarDecl::CInit, NewExprInit); - NewExprInitResult = NewExprInit; - InitCaptureExprsAndTypes[C - E->capture_begin()] = - std::make_pair(NewExprInitResult, NewInitCaptureType); + + auto SubstInitCapture = [&](SourceLocation EllipsisLoc, + Optional<unsigned> NumExpansions) { + EnterExpressionEvaluationContext EEEC( + getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + ExprResult NewExprInitResult = getDerived().TransformInitializer( + OldVD->getInit(), OldVD->getInitStyle() == VarDecl::CallInit); + + if (NewExprInitResult.isInvalid()) { + Result.Expansions.push_back(InitCaptureInfoTy(ExprError(), QualType())); + return; + } + Expr *NewExprInit = NewExprInitResult.get(); + + QualType NewInitCaptureType = + getSema().buildLambdaInitCaptureInitialization( + C->getLocation(), OldVD->getType()->isReferenceType(), + EllipsisLoc, NumExpansions, OldVD->getIdentifier(), + C->getCapturedVar()->getInitStyle() != VarDecl::CInit, + NewExprInit); + Result.Expansions.push_back( + InitCaptureInfoTy(NewExprInit, NewInitCaptureType)); + }; + + // If this is an init-capture pack, consider expanding the pack now. + if (OldVD->isParameterPack()) { + PackExpansionTypeLoc ExpansionTL = OldVD->getTypeSourceInfo() + ->getTypeLoc() + .castAs<PackExpansionTypeLoc>(); + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(OldVD->getInit(), Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + Optional<unsigned> OrigNumExpansions = + ExpansionTL.getTypePtr()->getNumExpansions(); + Optional<unsigned> NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks( + ExpansionTL.getEllipsisLoc(), + OldVD->getInit()->getSourceRange(), Unexpanded, Expand, + RetainExpansion, NumExpansions)) + return ExprError(); + if (Expand) { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + SubstInitCapture(SourceLocation(), None); + } + } + if (!Expand || RetainExpansion) { + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions); + Result.EllipsisLoc = ExpansionTL.getEllipsisLoc(); + } + } else { + SubstInitCapture(SourceLocation(), None); + } } // Transform the template parameters, and add them to the current @@ -11245,7 +11294,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { NewCallOpTSI, /*KnownDependent=*/false, E->getCaptureDefault()); - getDerived().transformedLocalDecl(E->getLambdaClass(), Class); + getDerived().transformedLocalDecl(E->getLambdaClass(), {Class}); // Build the call operator. CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition( @@ -11270,7 +11319,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); - getDerived().transformedLocalDecl(E->getCallOperator(), NewCallOperator); + getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator}); // Introduce the context of the call operator. Sema::ContextRAII SavedContext(getSema(), NewCallOperator, @@ -11313,24 +11362,33 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Rebuild init-captures, including the implied field declaration. if (E->isInitCapture(C)) { - InitCaptureInfoTy InitExprTypePair = - InitCaptureExprsAndTypes[C - E->capture_begin()]; - ExprResult Init = InitExprTypePair.first; - QualType InitQualType = InitExprTypePair.second; - if (Init.isInvalid() || InitQualType.isNull()) { - Invalid = true; - continue; - } + TransformedInitCapture &NewC = InitCaptures[C - E->capture_begin()]; + VarDecl *OldVD = C->getCapturedVar(); - VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl( - OldVD->getLocation(), InitExprTypePair.second, OldVD->getIdentifier(), - OldVD->getInitStyle(), Init.get()); - if (!NewVD) - Invalid = true; - else { - getDerived().transformedLocalDecl(OldVD, NewVD); + llvm::SmallVector<Decl*, 4> NewVDs; + + for (InitCaptureInfoTy &Info : NewC.Expansions) { + ExprResult Init = Info.first; + QualType InitQualType = Info.second; + if (Init.isInvalid() || InitQualType.isNull()) { + Invalid = true; + break; + } + VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl( + OldVD->getLocation(), InitQualType, NewC.EllipsisLoc, + OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get()); + if (!NewVD) { + Invalid = true; + break; + } + NewVDs.push_back(NewVD); + getSema().buildInitCaptureField(LSI, NewVD); } - getSema().buildInitCaptureField(LSI, NewVD); + + if (Invalid) + break; + + getDerived().transformedLocalDecl(OldVD, NewVDs); continue; } @@ -12471,8 +12529,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { VarDecl *oldCapture = I.getVariable(); // Ignore parameter packs. - if (isa<ParmVarDecl>(oldCapture) && - cast<ParmVarDecl>(oldCapture)->isParameterPack()) + if (oldCapture->isParameterPack()) continue; VarDecl *newCapture = |