diff options
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r-- | lib/Sema/TreeTransform.h | 733 |
1 files changed, 548 insertions, 185 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index df14768cbe81..8df18b5c2784 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1,9 +1,8 @@ //===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception //===----------------------------------------------------------------------===// // // This file implements a semantic tree transformation that takes a given @@ -149,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. /// @@ -319,6 +323,13 @@ public: TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI); /// @} + /// The reason why the value of a statement is not discarded, if any. + enum StmtDiscardKind { + SDK_Discarded, + SDK_NotDiscarded, + SDK_StmtExprResult, + }; + /// Transform the given statement. /// /// By default, this routine transforms a statement by delegating to the @@ -328,7 +339,7 @@ public: /// other mechanism. /// /// \returns the transformed statement. - StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); + StmtResult TransformStmt(Stmt *S, StmtDiscardKind SDK = SDK_Discarded); /// Transform the given statement. /// @@ -444,8 +455,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. @@ -646,6 +659,12 @@ public: Optional<unsigned> NumExpansions, bool ExpectParameterPack); + /// Transform the body of a lambda-expression. + StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body); + /// Alternative implementation of TransformLambdaBody that skips transforming + /// the body. + StmtResult SkipLambdaBody(LambdaExpr *E, Stmt *Body); + QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); @@ -673,6 +692,9 @@ public: #define STMT(Node, Parent) \ LLVM_ATTRIBUTE_NOINLINE \ StmtResult Transform##Node(Node *S); +#define VALUESTMT(Node, Parent) \ + LLVM_ATTRIBUTE_NOINLINE \ + StmtResult Transform##Node(Node *S, StmtDiscardKind SDK); #define EXPR(Node, Parent) \ LLVM_ATTRIBUTE_NOINLINE \ ExprResult Transform##Node(Node *E); @@ -874,6 +896,12 @@ public: return SemaRef.Context.getTypeDeclType(Typedef); } + /// Build a new MacroDefined type. + QualType RebuildMacroQualifiedType(QualType T, + const IdentifierInfo *MacroII) { + return SemaRef.Context.getMacroQualifiedType(T, MacroII); + } + /// Build a new class/struct/union type. QualType RebuildRecordType(RecordDecl *Record) { return SemaRef.Context.getTypeDeclType(Record); @@ -1356,10 +1384,11 @@ public: unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, + unsigned NumLabels, SourceLocation RParenLoc) { return getSema().ActOnGCCAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs, - AsmString, Clobbers, RParenLoc); + AsmString, Clobbers, NumLabels, RParenLoc); } /// Build a new MS style inline asm statement. @@ -1545,6 +1574,16 @@ public: return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc); } + /// Build a new OpenMP 'allocator' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPAllocatorClause(Expr *A, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPAllocatorClause(A, StartLoc, LParenLoc, EndLoc); + } + /// Build a new OpenMP 'collapse' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -1795,17 +1834,30 @@ public: /// /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. - OMPClause * - RebuildOMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, - ArrayRef<SourceLocation> MapTypeModifiersLoc, - OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, - SourceLocation MapLoc, SourceLocation ColonLoc, - ArrayRef<Expr *> VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) { + OMPClause *RebuildOMPMapClause( + ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, + CXXScopeSpec MapperIdScopeSpec, DeclarationNameInfo MapperId, + OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, + SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { return getSema().ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc, - MapType, IsMapTypeImplicit, MapLoc, - ColonLoc, VarList, StartLoc, - LParenLoc, EndLoc); + MapperIdScopeSpec, MapperId, MapType, + IsMapTypeImplicit, MapLoc, ColonLoc, + VarList, Locs, UnresolvedMappers); + } + + /// Build a new OpenMP 'allocate' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPAllocateClause(Expr *Allocate, ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPAllocateClause(Allocate, VarList, StartLoc, + LParenLoc, ColonLoc, EndLoc); } /// Build a new OpenMP 'num_teams' clause. @@ -1892,10 +1944,12 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. OMPClause *RebuildOMPToClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { - return getSema().ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc); + CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperId, + const OMPVarListLocTy &Locs, + ArrayRef<Expr *> UnresolvedMappers) { + return getSema().ActOnOpenMPToClause(VarList, MapperIdScopeSpec, MapperId, + Locs, UnresolvedMappers); } /// Build a new OpenMP 'from' clause. @@ -1903,11 +1957,12 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. OMPClause *RebuildOMPFromClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { - return getSema().ActOnOpenMPFromClause(VarList, StartLoc, LParenLoc, - EndLoc); + CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperId, + const OMPVarListLocTy &Locs, + ArrayRef<Expr *> UnresolvedMappers) { + return getSema().ActOnOpenMPFromClause(VarList, MapperIdScopeSpec, MapperId, + Locs, UnresolvedMappers); } /// Build a new OpenMP 'use_device_ptr' clause. @@ -1915,11 +1970,8 @@ public: /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. OMPClause *RebuildOMPUseDevicePtrClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { - return getSema().ActOnOpenMPUseDevicePtrClause(VarList, StartLoc, LParenLoc, - EndLoc); + const OMPVarListLocTy &Locs) { + return getSema().ActOnOpenMPUseDevicePtrClause(VarList, Locs); } /// Build a new OpenMP 'is_device_ptr' clause. @@ -1927,11 +1979,8 @@ public: /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. OMPClause *RebuildOMPIsDevicePtrClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { - return getSema().ActOnOpenMPIsDevicePtrClause(VarList, StartLoc, LParenLoc, - EndLoc); + const OMPVarListLocTy &Locs) { + return getSema().ActOnOpenMPIsDevicePtrClause(VarList, Locs); } /// Rebuild the operand to an Objective-C \@synchronized statement. @@ -2232,8 +2281,8 @@ public: MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig = nullptr) { - return getSema().ActOnCallExpr(/*Scope=*/nullptr, Callee, LParenLoc, - Args, RParenLoc, ExecConfig); + return getSema().BuildCallExpr(/*Scope=*/nullptr, Callee, LParenLoc, Args, + RParenLoc, ExecConfig); } /// Build a new member access expression. @@ -2603,6 +2652,16 @@ public: ListInitialization); } + /// Build a new C++ __builtin_bit_cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildBuiltinBitCastExpr(SourceLocation KWLoc, + TypeSourceInfo *TSI, Expr *Sub, + SourceLocation RParenLoc) { + return getSema().BuildBuiltinBitCastExpr(KWLoc, TSI, Sub, RParenLoc); + } + /// Build a new C++ typeid(type) expression. /// /// By default, performs semantic analysis to build the new expression. @@ -2660,8 +2719,7 @@ public: ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { - getSema().CheckCXXThisCapture(ThisLoc); - return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit); + return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit); } /// Build a new C++ throw expression. @@ -2678,9 +2736,9 @@ public: /// By default, builds a new default-argument expression, which does not /// require any semantic analysis. Subclasses may override this routine to /// provide different behavior. - ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, - ParmVarDecl *Param) { - return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param); + ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, ParmVarDecl *Param) { + return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param, + getSema().CurContext); } /// Build a new C++11 default-initialization expression. @@ -2690,7 +2748,8 @@ public: /// routine to provide different behavior. ExprResult RebuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { - return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field); + return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field, + getSema().CurContext); } /// Build a new C++ zero-initialization expression. @@ -2716,7 +2775,7 @@ public: SourceRange TypeIdParens, QualType AllocatedType, TypeSourceInfo *AllocatedTypeInfo, - Expr *ArraySize, + Optional<Expr *> ArraySize, SourceRange DirectInitRange, Expr *Initializer) { return getSema().BuildCXXNew(StartLoc, UseGlobal, @@ -2944,6 +3003,18 @@ public: RParenLoc, Length, PartialArgs); } + /// Build a new expression representing a call to a source location + /// builtin. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildSourceLocExpr(SourceLocExpr::IdentKind Kind, + SourceLocation BuiltinLoc, + SourceLocation RPLoc, + DeclContext *ParentContext) { + return getSema().BuildSourceLocExpr(Kind, BuiltinLoc, RPLoc, ParentContext); + } + /// Build a new Objective-C boxed expression. /// /// By default, performs semantic analysis to build the new expression. @@ -3219,9 +3290,10 @@ public: ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Optional<unsigned> NumExpansions) { return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, EllipsisLoc, - RHS, RParenLoc); + RHS, RParenLoc, NumExpansions); } /// Build an empty C++1z fold-expression with the given operator. @@ -3270,7 +3342,7 @@ private: }; template <typename Derived> -StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { +StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, StmtDiscardKind SDK) { if (!S) return S; @@ -3278,8 +3350,12 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { case Stmt::NoStmtClass: break; // Transform individual statement nodes + // Pass SDK into statements that can produce a value #define STMT(Node, Parent) \ case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S)); +#define VALUESTMT(Node, Parent) \ + case Stmt::Node##Class: \ + return getDerived().Transform##Node(cast<Node>(S), SDK); #define ABSTRACT_STMT(Node) #define EXPR(Node, Parent) #include "clang/AST/StmtNodes.inc" @@ -3291,10 +3367,10 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { #include "clang/AST/StmtNodes.inc" { ExprResult E = getDerived().TransformExpr(cast<Expr>(S)); - if (E.isInvalid()) - return StmtError(); - return getSema().ActOnExprStmt(E, DiscardedValue); + if (SDK == SDK_StmtExprResult) + E = getSema().ActOnStmtExprResult(E); + return getSema().ActOnExprStmt(E, SDK == SDK_Discarded); } } @@ -3879,10 +3955,6 @@ template<typename Derived> bool TreeTransform<Derived>::TransformTemplateArgument( const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output, bool Uneval) { - EnterExpressionEvaluationContext EEEC( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, /*ExprContext=*/ - Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); const TemplateArgument &Arg = Input.getArgument(); switch (Arg.getKind()) { case TemplateArgument::Null: @@ -3931,9 +4003,11 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Expression: { // Template argument expressions are constant expressions. EnterExpressionEvaluationContext Unevaluated( - getSema(), Uneval - ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated); + getSema(), + Uneval ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated, + /*LambdaContextDecl=*/nullptr, /*ExprContext=*/ + Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); @@ -4462,6 +4536,14 @@ QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB, return Result; } +/// Helper to deduce addr space of a pointee type in OpenCL mode. +/// If the type is updated it will be overwritten in PointeeType param. +static void deduceOpenCLPointeeAddrSpace(Sema &SemaRef, QualType &PointeeType) { + if (PointeeType.getAddressSpace() == LangAS::Default) + PointeeType = SemaRef.Context.getAddrSpaceQualType(PointeeType, + LangAS::opencl_generic); +} + template<typename Derived> QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB, PointerTypeLoc TL) { @@ -4470,6 +4552,9 @@ QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (PointeeType->getAs<ObjCObjectType>()) { // A dependent pointer type 'T *' has is being transformed such @@ -4508,6 +4593,9 @@ TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != TL.getPointeeLoc().getType()) { @@ -4537,6 +4625,9 @@ TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeTypeAsWritten()) { @@ -5301,13 +5392,6 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType( if (ResultType.isNull()) return QualType(); - // Return type can not be qualified with an address space. - if (ResultType.getAddressSpace() != LangAS::Default) { - SemaRef.Diag(TL.getReturnLoc().getBeginLoc(), - diag::err_attribute_address_function_type); - return QualType(); - } - if (getDerived().TransformFunctionTypeParams( TL.getBeginLoc(), TL.getParams(), TL.getTypePtr()->param_type_begin(), @@ -6160,6 +6244,27 @@ TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB, return Result; } +template <typename Derived> +QualType +TreeTransform<Derived>::TransformMacroQualifiedType(TypeLocBuilder &TLB, + MacroQualifiedTypeLoc TL) { + QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (Inner.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || Inner != TL.getInnerLoc().getType()) { + Result = + getDerived().RebuildMacroQualifiedType(Inner, TL.getMacroIdentifier()); + if (Result.isNull()) + return QualType(); + } + + MacroQualifiedTypeLoc NewTL = TLB.push<MacroQualifiedTypeLoc>(Result); + NewTL.setExpansionLoc(TL.getExpansionLoc()); + return Result; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformDependentNameType( TypeLocBuilder &TLB, DependentNameTypeLoc TL) { @@ -6517,12 +6622,13 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr) { Sema::CompoundScopeRAII CompoundScope(getSema()); + const Stmt *ExprResult = S->getStmtExprResult(); bool SubStmtInvalid = false; bool SubStmtChanged = false; SmallVector<Stmt*, 8> Statements; for (auto *B : S->body()) { - StmtResult Result = - getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back()); + StmtResult Result = getDerived().TransformStmt( + B, IsStmtExpr && B == ExprResult ? SDK_StmtExprResult : SDK_Discarded); if (Result.isInvalid()) { // Immediately fail if this was a DeclStmt, since it's very @@ -6585,7 +6691,8 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { return StmtError(); // Transform the statement following the case - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + StmtResult SubStmt = + getDerived().TransformStmt(S->getSubStmt()); if (SubStmt.isInvalid()) return StmtError(); @@ -6593,11 +6700,11 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { // Transform the statement following the default case - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + StmtResult SubStmt = + getDerived().TransformStmt(S->getSubStmt()); if (SubStmt.isInvalid()) return StmtError(); @@ -6608,8 +6715,8 @@ TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { template<typename Derived> StmtResult -TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) { - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); +TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S, StmtDiscardKind SDK) { + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); if (SubStmt.isInvalid()) return StmtError(); @@ -6618,6 +6725,11 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) { if (!LD) return StmtError(); + // If we're transforming "in-place" (we're not creating new local + // declarations), assume we're replacing the old label statement + // and clear out the reference to it. + if (LD == S->getDecl()) + S->getDecl()->setStmt(nullptr); // FIXME: Pass the real colon location in. return getDerived().RebuildLabelStmt(S->getIdentLoc(), @@ -6643,7 +6755,9 @@ const Attr *TreeTransform<Derived>::TransformAttr(const Attr *R) { } template <typename Derived> -StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) { +StmtResult +TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S, + StmtDiscardKind SDK) { bool AttrsChanged = false; SmallVector<const Attr *, 1> Attrs; @@ -6654,7 +6768,7 @@ StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) { Attrs.push_back(R); } - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); if (SubStmt.isInvalid()) return StmtError(); @@ -6967,6 +7081,16 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) { Exprs.push_back(Result.get()); } + // Go through the Labels. + for (unsigned I = 0, E = S->getNumLabels(); I != E; ++I) { + Names.push_back(S->getLabelIdentifier(I)); + + ExprResult Result = getDerived().TransformExpr(S->getLabelExpr(I)); + if (Result.isInvalid()) + return StmtError(); + ExprsChanged |= Result.get() != S->getLabelExpr(I); + Exprs.push_back(Result.get()); + } if (!getDerived().AlwaysRebuild() && !ExprsChanged) return S; @@ -6980,7 +7104,8 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) { S->isVolatile(), S->getNumOutputs(), S->getNumInputs(), Names.data(), Constraints, Exprs, AsmString.get(), - Clobbers, S->getRParenLoc()); + Clobbers, S->getNumLabels(), + S->getRParenLoc()); } template<typename Derived> @@ -7039,7 +7164,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 @@ -7071,13 +7196,22 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { Builder.ReturnValue = Res.get(); if (S->hasDependentPromiseType()) { - assert(!Promise->getType()->isDependentType() && - "the promise type must no longer be dependent"); - assert(!S->getFallthroughHandler() && !S->getExceptionHandler() && - !S->getReturnStmtOnAllocFailure() && !S->getDeallocate() && - "these nodes should not have been built yet"); - if (!Builder.buildDependentStatements()) - return StmtError(); + // PR41909: We may find a generic coroutine lambda definition within a + // template function that is being instantiated. In this case, the lambda + // will have a dependent promise type, until it is used in an expression + // that creates an instantiation with a non-dependent promise type. We + // should not assert or build coroutine dependent statements for such a + // generic lambda. + auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD); + if (!MD || !MD->getParent()->isGenericLambda()) { + assert(!Promise->getType()->isDependentType() && + "the promise type must no longer be dependent"); + assert(!S->getFallthroughHandler() && !S->getExceptionHandler() && + !S->getReturnStmtOnAllocFailure() && !S->getDeallocate() && + "these nodes should not have been built yet"); + if (!Builder.buildDependentStatements()) + return StmtError(); + } } else { if (auto *OnFallthrough = S->getFallthroughHandler()) { StmtResult Res = getDerived().TransformStmt(OnFallthrough); @@ -7359,7 +7493,8 @@ StmtResult TreeTransform<Derived>::TransformObjCForCollectionStmt( ObjCForCollectionStmt *S) { // Transform the element statement. - StmtResult Element = getDerived().TransformStmt(S->getElement()); + StmtResult Element = + getDerived().TransformStmt(S->getElement(), SDK_NotDiscarded); if (Element.isInvalid()) return StmtError(); @@ -8325,6 +8460,16 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) { template <typename Derived> OMPClause * +TreeTransform<Derived>::TransformOMPAllocatorClause(OMPAllocatorClause *C) { + ExprResult E = getDerived().TransformExpr(C->getAllocator()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPAllocatorClause( + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); +} + +template <typename Derived> +OMPClause * TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) { ExprResult E = getDerived().TransformExpr(C->getSimdlen()); if (E.isInvalid()) @@ -8797,8 +8942,85 @@ TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) { C->getLParenLoc(), C->getEndLoc()); } +template <typename Derived, class T> +bool transformOMPMappableExprListClause( + TreeTransform<Derived> &TT, OMPMappableExprListClause<T> *C, + llvm::SmallVectorImpl<Expr *> &Vars, CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperIdInfo, + llvm::SmallVectorImpl<Expr *> &UnresolvedMappers) { + // Transform expressions in the list. + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlists()) { + ExprResult EVar = TT.getDerived().TransformExpr(cast<Expr>(VE)); + if (EVar.isInvalid()) + return true; + Vars.push_back(EVar.get()); + } + // Transform mapper scope specifier and identifier. + NestedNameSpecifierLoc QualifierLoc; + if (C->getMapperQualifierLoc()) { + QualifierLoc = TT.getDerived().TransformNestedNameSpecifierLoc( + C->getMapperQualifierLoc()); + if (!QualifierLoc) + return true; + } + MapperIdScopeSpec.Adopt(QualifierLoc); + MapperIdInfo = C->getMapperIdInfo(); + if (MapperIdInfo.getName()) { + MapperIdInfo = TT.getDerived().TransformDeclarationNameInfo(MapperIdInfo); + if (!MapperIdInfo.getName()) + return true; + } + // Build a list of all candidate OMPDeclareMapperDecls, which is provided by + // the previous user-defined mapper lookup in dependent environment. + for (auto *E : C->mapperlists()) { + // Transform all the decls. + if (E) { + auto *ULE = cast<UnresolvedLookupExpr>(E); + UnresolvedSet<8> Decls; + for (auto *D : ULE->decls()) { + NamedDecl *InstD = + cast<NamedDecl>(TT.getDerived().TransformDecl(E->getExprLoc(), D)); + Decls.addDecl(InstD, InstD->getAccess()); + } + UnresolvedMappers.push_back(UnresolvedLookupExpr::Create( + TT.getSema().Context, /*NamingClass=*/nullptr, + MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context), + MapperIdInfo, /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), + Decls.end())); + } else { + UnresolvedMappers.push_back(nullptr); + } + } + return false; +} + template <typename Derived> OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) { + OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); + llvm::SmallVector<Expr *, 16> Vars; + CXXScopeSpec MapperIdScopeSpec; + DeclarationNameInfo MapperIdInfo; + llvm::SmallVector<Expr *, 16> UnresolvedMappers; + if (transformOMPMappableExprListClause<Derived, OMPMapClause>( + *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers)) + return nullptr; + return getDerived().RebuildOMPMapClause( + C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), MapperIdScopeSpec, + MapperIdInfo, C->getMapType(), C->isImplicitMapType(), C->getMapLoc(), + C->getColonLoc(), Vars, Locs, UnresolvedMappers); +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPAllocateClause(OMPAllocateClause *C) { + Expr *Allocator = C->getAllocator(); + if (Allocator) { + ExprResult AllocatorRes = getDerived().TransformExpr(Allocator); + if (AllocatorRes.isInvalid()) + return nullptr; + Allocator = AllocatorRes.get(); + } llvm::SmallVector<Expr *, 16> Vars; Vars.reserve(C->varlist_size()); for (auto *VE : C->varlists()) { @@ -8807,10 +9029,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) { return nullptr; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPMapClause( - C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), C->getMapType(), - C->isImplicitMapType(), C->getMapLoc(), C->getColonLoc(), Vars, - C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); + return getDerived().RebuildOMPAllocateClause( + Allocator, Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(), + C->getEndLoc()); } template <typename Derived> @@ -8891,30 +9112,30 @@ TreeTransform<Derived>::TransformOMPDefaultmapClause(OMPDefaultmapClause *C) { template <typename Derived> OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) { + OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); llvm::SmallVector<Expr *, 16> Vars; - Vars.reserve(C->varlist_size()); - for (auto *VE : C->varlists()) { - ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); - if (EVar.isInvalid()) - return 0; - Vars.push_back(EVar.get()); - } - return getDerived().RebuildOMPToClause(Vars, C->getBeginLoc(), - C->getLParenLoc(), C->getEndLoc()); + CXXScopeSpec MapperIdScopeSpec; + DeclarationNameInfo MapperIdInfo; + llvm::SmallVector<Expr *, 16> UnresolvedMappers; + if (transformOMPMappableExprListClause<Derived, OMPToClause>( + *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers)) + return nullptr; + return getDerived().RebuildOMPToClause(Vars, MapperIdScopeSpec, MapperIdInfo, + Locs, UnresolvedMappers); } template <typename Derived> OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) { + OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); llvm::SmallVector<Expr *, 16> Vars; - Vars.reserve(C->varlist_size()); - for (auto *VE : C->varlists()) { - ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); - if (EVar.isInvalid()) - return 0; - Vars.push_back(EVar.get()); - } - return getDerived().RebuildOMPFromClause(Vars, C->getBeginLoc(), - C->getLParenLoc(), C->getEndLoc()); + CXXScopeSpec MapperIdScopeSpec; + DeclarationNameInfo MapperIdInfo; + llvm::SmallVector<Expr *, 16> UnresolvedMappers; + if (transformOMPMappableExprListClause<Derived, OMPFromClause>( + *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers)) + return nullptr; + return getDerived().RebuildOMPFromClause( + Vars, MapperIdScopeSpec, MapperIdInfo, Locs, UnresolvedMappers); } template <typename Derived> @@ -8928,8 +9149,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPUseDevicePtrClause( return nullptr; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPUseDevicePtrClause( - Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); + OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); + return getDerived().RebuildOMPUseDevicePtrClause(Vars, Locs); } template <typename Derived> @@ -8943,8 +9164,8 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) { return nullptr; Vars.push_back(EVar.get()); } - return getDerived().RebuildOMPIsDevicePtrClause( - Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); + OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); + return getDerived().RebuildOMPIsDevicePtrClause(Vars, Locs); } //===----------------------------------------------------------------------===// @@ -9072,10 +9293,10 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { SmallVector<Expr *, 4> AssocExprs; SmallVector<TypeSourceInfo *, 4> AssocTypes; - for (unsigned i = 0; i != E->getNumAssocs(); ++i) { - TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i); - if (TS) { - TypeSourceInfo *AssocType = getDerived().TransformType(TS); + for (const GenericSelectionExpr::Association &Assoc : E->associations()) { + TypeSourceInfo *TSI = Assoc.getTypeSourceInfo(); + if (TSI) { + TypeSourceInfo *AssocType = getDerived().TransformType(TSI); if (!AssocType) return ExprError(); AssocTypes.push_back(AssocType); @@ -9083,7 +9304,8 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { AssocTypes.push_back(nullptr); } - ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i)); + ExprResult AssocExpr = + getDerived().TransformExpr(Assoc.getAssociationExpr()); if (AssocExpr.isInvalid()) return ExprError(); AssocExprs.push_back(AssocExpr.get()); @@ -9974,6 +10196,19 @@ TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) { return getDerived().TransformCallExpr(E); } +template <typename Derived> +ExprResult TreeTransform<Derived>::TransformSourceLocExpr(SourceLocExpr *E) { + bool NeedRebuildFunc = E->getIdentKind() == SourceLocExpr::Function && + getSema().CurContext != E->getParentContext(); + + if (!getDerived().AlwaysRebuild() && !NeedRebuildFunc) + return E; + + return getDerived().RebuildSourceLocExpr(E->getIdentKind(), E->getBeginLoc(), + E->getEndLoc(), + getSema().CurContext); +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) { @@ -10032,6 +10267,22 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformBuiltinBitCastExpr(BuiltinBitCastExpr *BCE) { + TypeSourceInfo *TSI = + getDerived().TransformType(BCE->getTypeInfoAsWritten()); + if (!TSI) + return ExprError(); + + ExprResult Sub = getDerived().TransformExpr(BCE->getSubExpr()); + if (Sub.isInvalid()) + return ExprError(); + + return getDerived().RebuildBuiltinBitCastExpr(BCE->getBeginLoc(), TSI, + Sub.get(), BCE->getEndLoc()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) { return getDerived().TransformCXXNamedCastExpr(E); } @@ -10169,8 +10420,9 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { QualType T = getSema().getCurrentThisType(); if (!getDerived().AlwaysRebuild() && T == E->getType()) { - // Make sure that we capture 'this'. - getSema().CheckCXXThisCapture(E->getBeginLoc()); + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + getSema().MarkThisReferenced(E); return E; } @@ -10200,8 +10452,8 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { if (!Param) return ExprError(); - if (!getDerived().AlwaysRebuild() && - Param == E->getParam()) + if (!getDerived().AlwaysRebuild() && Param == E->getParam() && + E->getUsedContext() == SemaRef.CurContext) return E; return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param); @@ -10215,7 +10467,8 @@ TreeTransform<Derived>::TransformCXXDefaultInitExpr(CXXDefaultInitExpr *E) { if (!Field) return ExprError(); - if (!getDerived().AlwaysRebuild() && Field == E->getField()) + if (!getDerived().AlwaysRebuild() && Field == E->getField() && + E->getUsedContext() == SemaRef.CurContext) return E; return getDerived().RebuildCXXDefaultInitExpr(E->getExprLoc(), Field); @@ -10248,9 +10501,16 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { return ExprError(); // Transform the size of the array we're allocating (if any). - ExprResult ArraySize = getDerived().TransformExpr(E->getArraySize()); - if (ArraySize.isInvalid()) - return ExprError(); + Optional<Expr *> ArraySize; + if (Optional<Expr *> OldArraySize = E->getArraySize()) { + ExprResult NewArraySize; + if (*OldArraySize) { + NewArraySize = getDerived().TransformExpr(*OldArraySize); + if (NewArraySize.isInvalid()) + return ExprError(); + } + ArraySize = NewArraySize.get(); + } // Transform the placement arguments (if any). bool ArgumentChanged = false; @@ -10287,7 +10547,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { if (!getDerived().AlwaysRebuild() && AllocTypeInfo == E->getAllocatedTypeSourceInfo() && - ArraySize.get() == E->getArraySize() && + ArraySize == E->getArraySize() && NewInit.get() == OldInit && OperatorNew == E->getOperatorNew() && OperatorDelete == E->getOperatorDelete() && @@ -10314,7 +10574,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { } QualType AllocType = AllocTypeInfo->getType(); - if (!ArraySize.get()) { + if (!ArraySize) { // If no array size was specified, but the new expression was // instantiated with an array type (e.g., "new T" where T is // instantiated with "int[4]"), extract the outer bound from the @@ -10342,7 +10602,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { E->getBeginLoc(), E->isGlobalNew(), /*FIXME:*/ E->getBeginLoc(), PlacementArgs, /*FIXME:*/ E->getBeginLoc(), E->getTypeIdParens(), AllocType, - AllocTypeInfo, ArraySize.get(), E->getDirectInitRange(), NewInit.get()); + AllocTypeInfo, ArraySize, E->getDirectInitRange(), NewInit.get()); } template<typename Derived> @@ -10984,33 +11244,78 @@ 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) { + 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 @@ -11048,19 +11353,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()->getConstexprKind(), Mangling); LSI->CallOperator = NewCallOperator; @@ -11078,7 +11389,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, @@ -11096,16 +11407,13 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { bool Invalid = false; // Transform captures. - bool FinishedExplicitCaptures = false; for (LambdaExpr::capture_iterator C = E->capture_begin(), CEnd = E->capture_end(); C != CEnd; ++C) { // When we hit the first implicit capture, tell Sema that we've finished // the list of explicit captures. - if (!FinishedExplicitCaptures && C->isImplicit()) { - getSema().finishLambdaExplicitCaptures(LSI); - FinishedExplicitCaptures = true; - } + if (C->isImplicit()) + break; // Capturing 'this' is trivial. if (C->capturesThis()) { @@ -11121,24 +11429,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().addInitCapture(LSI, NewVD); } - getSema().buildInitCaptureField(LSI, NewVD); + + if (Invalid) + break; + + getDerived().transformedLocalDecl(OldVD, NewVDs); continue; } @@ -11205,17 +11522,16 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind, EllipsisLoc); } - if (!FinishedExplicitCaptures) - getSema().finishLambdaExplicitCaptures(LSI); + getSema().finishLambdaExplicitCaptures(LSI); - // Enter a new evaluation context to insulate the lambda from any - // cleanups from the enclosing full-expression. + // FIXME: Sema's lambda-building mechanism expects us to push an expression + // evaluation context even if we're not transforming the function body. getSema().PushExpressionEvaluationContext( Sema::ExpressionEvaluationContext::PotentiallyEvaluated); // Instantiate the body of the lambda expression. StmtResult Body = - Invalid ? StmtError() : getDerived().TransformStmt(E->getBody()); + Invalid ? StmtError() : getDerived().TransformLambdaBody(E, E->getBody()); // ActOnLambda* will pop the function scope for us. FuncScopeCleanup.disable(); @@ -11240,6 +11556,52 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformLambdaBody(LambdaExpr *E, Stmt *S) { + return TransformStmt(S); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::SkipLambdaBody(LambdaExpr *E, Stmt *S) { + // Transform captures. + for (LambdaExpr::capture_iterator C = E->capture_begin(), + CEnd = E->capture_end(); + C != CEnd; ++C) { + // When we hit the first implicit capture, tell Sema that we've finished + // the list of explicit captures. + if (!C->isImplicit()) + continue; + + // Capturing 'this' is trivial. + if (C->capturesThis()) { + getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit(), + /*BuildAndDiagnose*/ true, nullptr, + C->getCaptureKind() == LCK_StarThis); + continue; + } + // Captured expression will be recaptured during captured variables + // rebuilding. + if (C->capturesVLAType()) + continue; + + assert(C->capturesVariable() && "unexpected kind of lambda capture"); + assert(!E->isInitCapture(C) && "implicit init-capture?"); + + // Transform the captured variable. + VarDecl *CapturedVar = cast_or_null<VarDecl>( + getDerived().TransformDecl(C->getLocation(), C->getCapturedVar())); + if (!CapturedVar || CapturedVar->isInvalidDecl()) + return StmtError(); + + // Capture the transformed variable. + getSema().tryCaptureVariable(CapturedVar, C->getLocation()); + } + + return S; +} + +template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { @@ -11659,7 +12021,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { // be expanded. bool Expand = true; bool RetainExpansion = false; - Optional<unsigned> NumExpansions; + Optional<unsigned> OrigNumExpansions = E->getNumExpansions(), + NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(E->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, @@ -11688,7 +12051,7 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { return getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(), - RHS.get(), E->getEndLoc()); + RHS.get(), E->getEndLoc(), NumExpansions); } // The transform has determined that we should perform an elementwise @@ -11709,7 +12072,7 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { Result = getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(), - Result.get(), E->getEndLoc()); + Result.get(), E->getEndLoc(), OrigNumExpansions); if (Result.isInvalid()) return true; } @@ -11726,7 +12089,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { Result = getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), LeftFold ? Result.get() : Out.get(), E->getOperator(), E->getEllipsisLoc(), - LeftFold ? Out.get() : Result.get(), E->getEndLoc()); + LeftFold ? Out.get() : Result.get(), E->getEndLoc(), + OrigNumExpansions); } else if (Result.isUsable()) { // We've got down to a single element; build a binary operator. Result = getDerived().RebuildBinaryOperator( @@ -11751,7 +12115,7 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { Result = getDerived().RebuildCXXFoldExpr( E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(), - Out.get(), E->getEndLoc()); + Out.get(), E->getEndLoc(), OrigNumExpansions); if (Result.isInvalid()) return true; } @@ -12277,8 +12641,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 = |