From c69c600bcea762d6c9aeadc49f658aa9d239d96d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sun, 2 Jun 2019 18:53:44 +0000 Subject: [PATCH] Transform lambda expression captures when transforming an expression to potentially-evaluated. This ensures that every potentially-evaluated expression is built in a potentially-evaluated context. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@362336 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 12 ++++++------ lib/Sema/SemaExpr.cpp | 17 ++++++----------- lib/Sema/SemaLambda.cpp | 27 +++++++++++++++------------ lib/Sema/TreeTransform.h | 28 +++++++++++++++++++++++----- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a6db2f046b..b4f721c091 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5710,12 +5710,12 @@ public: LambdaCaptureDefault CaptureDefault); /// Start the definition of a lambda expression. - CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodType, - SourceLocation EndLoc, - ArrayRef Params, - bool IsConstexprSpecified); + CXXMethodDecl * + startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, + TypeSourceInfo *MethodType, SourceLocation EndLoc, + ArrayRef Params, + bool IsConstexprSpecified, + Optional> Mangling = None); /// Endow the lambda scope info with the relevant properties. void buildLambdaScope(sema::LambdaScopeInfo *LSI, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5746a102b7..72b61b8e58 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -14579,6 +14579,7 @@ namespace { // Make sure we redo semantic analysis bool AlwaysRebuild() { return true; } + bool ReplacingOriginal() { return true; } // We need to special-case DeclRefExprs referring to FieldDecls which // are not part of a member pointer formation; normal TreeTransforming @@ -14605,10 +14606,11 @@ namespace { return BaseTransform::TransformUnaryOperator(E); } - ExprResult TransformLambdaExpr(LambdaExpr *E) { - // Lambdas never need to be transformed. - return E; - } + // The body of a lambda-expression is in a separate expression evaluation + // 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; } }; } @@ -14715,13 +14717,6 @@ void Sema::PopExpressionEvaluationContext() { for (const auto *L : Rec.Lambdas) Diag(L->getBeginLoc(), D); - } else { - // Mark the capture expressions odr-used. This was deferred - // during lambda expression creation. - for (auto *Lambda : Rec.Lambdas) { - for (auto *C : Lambda->capture_inits()) - MarkDeclarationsReferencedInExpr(C); - } } } diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 4b832f5653..ccc8f6f42a 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -367,12 +367,11 @@ Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( return *MangleNumbering; } -CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodTypeInfo, - SourceLocation EndLoc, - ArrayRef Params, - const bool IsConstexprSpecified) { +CXXMethodDecl *Sema::startLambdaDefinition( + CXXRecordDecl *Class, SourceRange IntroducerRange, + TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, + ArrayRef Params, const bool IsConstexprSpecified, + Optional> Mangling) { QualType MethodType = MethodTypeInfo->getType(); TemplateParameterList *TemplateParams = getGenericLambdaTemplateParameterList(getCurLambda(), *this); @@ -438,12 +437,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, P->setOwningFunction(Method); } - Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - getCurrentMangleNumberContext(Class->getDeclContext(), - ManglingContextDecl)) { - unsigned ManglingNumber = MCtx->getManglingNumber(Method); - Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); + if (Mangling) { + Class->setLambdaMangling(Mangling->first, Mangling->second); + } else { + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(Class->getDeclContext(), + ManglingContextDecl)) { + unsigned ManglingNumber = MCtx->getManglingNumber(Method); + Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); + } } return Method; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 6620885f23..f46193502b 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -148,6 +148,11 @@ public: /// statement node appears at most once in its containing declaration. bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; } + /// Whether the transformation is forming an expression or statement that + /// replaces the original. In this case, we'll reuse mangling numbers from + /// existing lambdas. + bool ReplacingOriginal() { return false; } + /// Returns the location of the entity being transformed, if that /// information was not available elsewhere in the AST. /// @@ -654,6 +659,9 @@ public: Optional NumExpansions, bool ExpectParameterPack); + /// Transform the body of a lambda-expression. + StmtResult TransformLambdaBody(Stmt *Body); + QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); @@ -11197,8 +11205,6 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { auto SubstInitCapture = [&](SourceLocation EllipsisLoc, Optional NumExpansions) { - EnterExpressionEvaluationContext EEEC( - getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated); ExprResult NewExprInitResult = getDerived().TransformInitializer( OldVD->getInit(), OldVD->getInitStyle() == VarDecl::CallInit); @@ -11289,19 +11295,25 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { LSI->GLTemplateParameterList = TPL; // Create the local class that will describe the lambda. + CXXRecordDecl *OldClass = E->getLambdaClass(); CXXRecordDecl *Class = getSema().createLambdaClosureType(E->getIntroducerRange(), NewCallOpTSI, /*KnownDependent=*/false, E->getCaptureDefault()); - getDerived().transformedLocalDecl(E->getLambdaClass(), {Class}); + getDerived().transformedLocalDecl(OldClass, {Class}); + + Optional> Mangling; + if (getDerived().ReplacingOriginal()) + Mangling = std::make_pair(OldClass->getLambdaManglingNumber(), + OldClass->getLambdaContextDecl()); // Build the call operator. CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition( Class, E->getIntroducerRange(), NewCallOpTSI, E->getCallOperator()->getEndLoc(), NewCallOpTSI->getTypeLoc().castAs().getParams(), - E->getCallOperator()->isConstexpr()); + E->getCallOperator()->isConstexpr(), Mangling); LSI->CallOperator = NewCallOperator; @@ -11465,7 +11477,7 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { // Instantiate the body of the lambda expression. StmtResult Body = - Invalid ? StmtError() : getDerived().TransformStmt(E->getBody()); + Invalid ? StmtError() : getDerived().TransformLambdaBody(E->getBody()); // ActOnLambda* will pop the function scope for us. FuncScopeCleanup.disable(); @@ -11489,6 +11501,12 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { &LSICopy); } +template +StmtResult +TreeTransform::TransformLambdaBody(Stmt *S) { + return TransformStmt(S); +} + template ExprResult TreeTransform::TransformCXXUnresolvedConstructExpr( -- 2.40.0