diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-04 17:17:20 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-04 17:17:20 +0000 |
commit | 7bf8f6fa8ab123fe97ccd82d9a0ddff85505ee5f (patch) | |
tree | c5eb10d1d4e1f82ebd3925ca1bde79d1145d73e3 /clang/lib/Sema/SemaExpr.cpp | |
parent | f4302ad35e340f01529bf32919410b2577f899bd (diff) | |
download | bcm5719-llvm-7bf8f6fa8ab123fe97ccd82d9a0ddff85505ee5f.tar.gz bcm5719-llvm-7bf8f6fa8ab123fe97ccd82d9a0ddff85505ee5f.zip |
PR42104: Support instantiations of lambdas that implicitly capture
packs.
Two changes:
* Track odr-use via FunctionParmPackExprs to properly handle dependent
odr-uses of packs in generic lambdas.
* Do not instantiate implicit captures; instead, regenerate them by
instantiating the body of the lambda. This is necessary to
distinguish between cases where only one element of a pack is
captured and cases where the entire pack is captured.
This reinstates r362358 (reverted in r362375) with a fix for an
uninitialized variable use in UpdateMarkingForLValueToRValue.
llvm-svn: 362531
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 72b61b8e584..1e9164bc3ac 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14610,7 +14610,9 @@ namespace { // context so never needs to be transformed. // FIXME: Ideally we wouldn't transform the closure type either, and would // just recreate the capture expressions and lambda expression. - StmtResult TransformLambdaBody(Stmt *Body) { return Body; } + StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) { + return SkipLambdaBody(E, Body); + } }; } @@ -15054,7 +15056,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, /// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack. static void MarkVarDeclODRUsed(VarDecl *Var, SourceLocation Loc, Sema &SemaRef, - const unsigned *const FunctionScopeIndexToStopAt) { + const unsigned *const FunctionScopeIndexToStopAt = nullptr) { // Keep track of used but undefined variables. // FIXME: We shouldn't suppress this warning for static data members. if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && @@ -15735,14 +15737,21 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) { // variable. if (LambdaScopeInfo *LSI = getCurLambda()) { Expr *SansParensExpr = E->IgnoreParens(); - VarDecl *Var = nullptr; + VarDecl *Var; + ArrayRef<VarDecl *> Vars(&Var, &Var + 1); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr)) Var = dyn_cast<VarDecl>(DRE->getFoundDecl()); else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr)) Var = dyn_cast<VarDecl>(ME->getMemberDecl()); + else if (auto *FPPE = dyn_cast<FunctionParmPackExpr>(SansParensExpr)) + Vars = llvm::makeArrayRef(FPPE->begin(), FPPE->end()); + else + Vars = None; - if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context)) - LSI->markVariableExprAsNonODRUsed(SansParensExpr); + for (VarDecl *VD : Vars) { + if (VD && IsVariableNonDependentAndAConstantExpression(VD, Context)) + LSI->markVariableExprAsNonODRUsed(SansParensExpr); + } } } @@ -15767,20 +15776,18 @@ void Sema::CleanupVarDeclMarking() { std::swap(LocalMaybeODRUseExprs, MaybeODRUseExprs); for (Expr *E : LocalMaybeODRUseExprs) { - VarDecl *Var; - SourceLocation Loc; - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { - Var = cast<VarDecl>(DRE->getDecl()); - Loc = DRE->getLocation(); - } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { - Var = cast<VarDecl>(ME->getMemberDecl()); - Loc = ME->getMemberLoc(); + if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { + MarkVarDeclODRUsed(cast<VarDecl>(DRE->getDecl()), + DRE->getLocation(), *this); + } else if (auto *ME = dyn_cast<MemberExpr>(E)) { + MarkVarDeclODRUsed(cast<VarDecl>(ME->getMemberDecl()), ME->getMemberLoc(), + *this); + } else if (auto *FP = dyn_cast<FunctionParmPackExpr>(E)) { + for (VarDecl *VD : *FP) + MarkVarDeclODRUsed(VD, FP->getParameterPackLocation(), *this); } else { llvm_unreachable("Unexpected expression"); } - - MarkVarDeclODRUsed(Var, Loc, *this, - /*MaxFunctionScopeIndex Pointer*/ nullptr); } assert(MaybeODRUseExprs.empty() && @@ -15789,7 +15796,8 @@ void Sema::CleanupVarDeclMarking() { static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, VarDecl *Var, Expr *E) { - assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) && + assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E) || + isa<FunctionParmPackExpr>(E)) && "Invalid Expr argument to DoMarkVarDeclReferenced"); Var->setReferenced(); @@ -16022,6 +16030,12 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse); } +/// Perform reference-marking and odr-use handling for a FunctionParmPackExpr. +void Sema::MarkFunctionParmPackReferenced(FunctionParmPackExpr *E) { + for (VarDecl *VD : *E) + MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true); +} + /// Perform marking for a reference to an arbitrary declaration. It /// marks the declaration referenced, and performs odr-use checking for /// functions and variables. This method should not be used when building a |