diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-02 18:53:44 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-02 18:53:44 +0000 |
commit | 87346a15db59fbbb9828f232e8025dca4e610163 (patch) | |
tree | 24cd5c67f670469c27cb23777368203eee397897 /clang/lib | |
parent | 59a8db628b7f1ba9905f45883ea8810e4dcee924 (diff) | |
download | bcm5719-llvm-87346a15db59fbbb9828f232e8025dca4e610163.tar.gz bcm5719-llvm-87346a15db59fbbb9828f232e8025dca4e610163.zip |
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.
llvm-svn: 362336
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 28 |
3 files changed, 44 insertions, 28 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5746a102b71..72b61b8e584 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 4b832f56530..ccc8f6f42a5 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/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<ParmVarDecl *> Params, - const bool IsConstexprSpecified) { +CXXMethodDecl *Sema::startLambdaDefinition( + CXXRecordDecl *Class, SourceRange IntroducerRange, + TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, + ArrayRef<ParmVarDecl *> Params, const bool IsConstexprSpecified, + Optional<std::pair<unsigned, Decl *>> 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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6620885f239..f46193502b6 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/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<unsigned> 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<Derived>::TransformLambdaExpr(LambdaExpr *E) { auto SubstInitCapture = [&](SourceLocation EllipsisLoc, Optional<unsigned> NumExpansions) { - EnterExpressionEvaluationContext EEEC( - getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated); ExprResult NewExprInitResult = getDerived().TransformInitializer( OldVD->getInit(), OldVD->getInitStyle() == VarDecl::CallInit); @@ -11289,19 +11295,25 @@ TreeTransform<Derived>::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<std::pair<unsigned, Decl*>> 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<FunctionProtoTypeLoc>().getParams(), - E->getCallOperator()->isConstexpr()); + E->getCallOperator()->isConstexpr(), Mangling); LSI->CallOperator = NewCallOperator; @@ -11465,7 +11477,7 @@ TreeTransform<Derived>::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(); @@ -11490,6 +11502,12 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformLambdaBody(Stmt *S) { + return TransformStmt(S); +} + +template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { |