diff options
Diffstat (limited to 'clang/lib/Sema/TreeTransform.h')
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 473 |
1 files changed, 281 insertions, 192 deletions
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6a05ecc5370f..10b3587885e3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -19,8 +19,8 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/OpenMPClause.h" @@ -31,6 +31,7 @@ #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Sema/Designator.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/ParsedTemplate.h" @@ -377,22 +378,43 @@ public: /// By default, this routine transforms a statement by delegating to the /// appropriate TransformXXXAttr function to transform a specific kind /// of attribute. Subclasses may override this function to transform - /// attributed statements using some other mechanism. + /// attributed statements/types using some other mechanism. /// /// \returns the transformed attribute const Attr *TransformAttr(const Attr *S); -/// Transform the specified attribute. -/// -/// Subclasses should override the transformation of attributes with a pragma -/// spelling to transform expressions stored within the attribute. -/// -/// \returns the transformed attribute. -#define ATTR(X) -#define PRAGMA_SPELLING_ATTR(X) \ + // Transform the given statement attribute. + // + // Delegates to the appropriate TransformXXXAttr function to transform a + // specific kind of statement attribute. Unlike the non-statement taking + // version of this, this implements all attributes, not just pragmas. + const Attr *TransformStmtAttr(const Stmt *OrigS, const Stmt *InstS, + const Attr *A); + + // Transform the specified attribute. + // + // Subclasses should override the transformation of attributes with a pragma + // spelling to transform expressions stored within the attribute. + // + // \returns the transformed attribute. +#define ATTR(X) \ const X##Attr *Transform##X##Attr(const X##Attr *R) { return R; } #include "clang/Basic/AttrList.inc" + // Transform the specified attribute. + // + // Subclasses should override the transformation of attributes to do + // transformation and checking of statement attributes. By default, this + // delegates to the non-statement taking version. + // + // \returns the transformed attribute. +#define ATTR(X) \ + const X##Attr *TransformStmt##X##Attr(const Stmt *, const Stmt *, \ + const X##Attr *A) { \ + return getDerived().Transform##X##Attr(A); \ + } +#include "clang/Basic/AttrList.inc" + /// Transform the given expression. /// /// By default, this routine transforms an expression by delegating to the @@ -2400,6 +2422,19 @@ public: return getSema().ActOnOpenMPMessageClause(MS, StartLoc, LParenLoc, EndLoc); } + /// Build a new OpenMP 'doacross' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause * + RebuildOMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, + SourceLocation DepLoc, SourceLocation ColonLoc, + ArrayRef<Expr *> VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) { + return getSema().ActOnOpenMPDoacrossClause( + DepType, DepLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc); + } + /// Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -2803,6 +2838,21 @@ public: R.addDecl(FoundDecl); R.resolveKind(); + if (getSema().isUnevaluatedContext() && Base->isImplicitCXXThis() && + isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(Member)) { + if (auto *ThisClass = cast<CXXThisExpr>(Base) + ->getType() + ->getPointeeType() + ->getAsCXXRecordDecl()) { + auto *Class = cast<CXXRecordDecl>(Member->getDeclContext()); + // In unevaluated contexts, an expression supposed to be a member access + // might reference a member in an unrelated class. + if (!ThisClass->Equals(Class) && !ThisClass->isDerivedFrom(Class)) + return getSema().BuildDeclRefExpr(Member, Member->getType(), + VK_LValue, Member->getLocation()); + } + } + return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow, SS, TemplateKWLoc, FirstQualifierInScope, @@ -2977,7 +3027,7 @@ public: RParenLoc); } - /// Build a new generic selection expression. + /// Build a new generic selection expression with an expression predicate. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. @@ -2988,9 +3038,25 @@ public: ArrayRef<TypeSourceInfo *> Types, ArrayRef<Expr *> Exprs) { return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + /*PredicateIsExpr=*/true, ControllingExpr, Types, Exprs); } + /// Build a new generic selection expression with a type predicate. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + TypeSourceInfo *ControllingType, + ArrayRef<TypeSourceInfo *> Types, + ArrayRef<Expr *> Exprs) { + return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + /*PredicateIsExpr=*/false, + ControllingType, Types, Exprs); + } + /// Build a new overloaded operator call expression. /// /// By default, performs semantic analysis to build the new expression. @@ -3000,10 +3066,11 @@ public: /// argument-dependent lookup, etc. Subclasses may override this routine to /// provide different behavior. ExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, - SourceLocation OpLoc, - Expr *Callee, - Expr *First, - Expr *Second); + SourceLocation OpLoc, + SourceLocation CalleeLoc, + bool RequiresADL, + const UnresolvedSetImpl &Functions, + Expr *First, Expr *Second); /// Build a new C++ "named" cast expression, such as static_cast or /// reinterpret_cast. @@ -3137,6 +3204,13 @@ public: Expr *Sub, SourceLocation RParenLoc, bool ListInitialization) { + // If Sub is a ParenListExpr, then Sub is the syntatic form of a + // CXXParenListInitExpr. Pass its expanded arguments so that the + // CXXParenListInitExpr can be rebuilt. + if (auto *PLE = dyn_cast<ParenListExpr>(Sub)) + return getSema().BuildCXXTypeConstructExpr( + TInfo, LParenLoc, MultiExprArg(PLE->getExprs(), PLE->getNumExprs()), + RParenLoc, ListInitialization); return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc, MultiExprArg(&Sub, 1), RParenLoc, ListInitialization); @@ -3866,16 +3940,6 @@ public: return getSema().BuildEmptyCXXFoldExpr(EllipsisLoc, Operator); } - ExprResult RebuildCXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T, - unsigned NumUserSpecifiedExprs, - SourceLocation InitLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { - return CXXParenListInitExpr::Create(getSema().Context, Args, T, - NumUserSpecifiedExprs, InitLoc, - LParenLoc, RParenLoc); - } - /// Build a new atomic operation expression. /// /// By default, performs semantic analysis to build the new expression. @@ -4569,7 +4633,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument( getSema(), Uneval ? Sema::ExpressionEvaluationContext::Unevaluated : Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, /*ExprContext=*/ + Sema::ReuseLambdaContextDecl, /*ExprContext=*/ Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); Expr *InputExpr = Input.getSourceExpression(); @@ -5897,7 +5961,6 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams( = dyn_cast<PackExpansionType>(OldType)) { // We have a function parameter pack that may need to be expanded. QualType Pattern = Expansion->getPattern(); - NumExpansions = Expansion->getNumExpansions(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); @@ -6992,7 +7055,8 @@ QualType TreeTransform<Derived>::TransformAttributedType( // type sugar, and therefore cannot be diagnosed in any other way. if (auto nullability = oldType->getImmediateNullability()) { if (!modifiedType->canHaveNullability()) { - SemaRef.Diag(TL.getAttr()->getLocation(), + SemaRef.Diag((TL.getAttr() ? TL.getAttr()->getLocation() + : TL.getModifiedLoc().getBeginLoc()), diag::err_nullability_nonpointer) << DiagNullabilityKind(*nullability, false) << modifiedType; return QualType(); @@ -7536,36 +7600,52 @@ const Attr *TreeTransform<Derived>::TransformAttr(const Attr *R) { return R; switch (R->getKind()) { -// Transform attributes with a pragma spelling by calling TransformXXXAttr. -#define ATTR(X) -#define PRAGMA_SPELLING_ATTR(X) \ +// Transform attributes by calling TransformXXXAttr. +#define ATTR(X) \ case attr::X: \ return getDerived().Transform##X##Attr(cast<X##Attr>(R)); #include "clang/Basic/AttrList.inc" - default: + } + return R; +} + +template <typename Derived> +const Attr *TreeTransform<Derived>::TransformStmtAttr(const Stmt *OrigS, + const Stmt *InstS, + const Attr *R) { + if (!R) return R; + + switch (R->getKind()) { +// Transform attributes by calling TransformStmtXXXAttr. +#define ATTR(X) \ + case attr::X: \ + return getDerived().TransformStmt##X##Attr(OrigS, InstS, cast<X##Attr>(R)); +#include "clang/Basic/AttrList.inc" } + return TransformAttr(R); } template <typename Derived> StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S, StmtDiscardKind SDK) { + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); + if (SubStmt.isInvalid()) + return StmtError(); + bool AttrsChanged = false; SmallVector<const Attr *, 1> Attrs; // Visit attributes and keep track if any are transformed. for (const auto *I : S->getAttrs()) { - const Attr *R = getDerived().TransformAttr(I); + const Attr *R = + getDerived().TransformStmtAttr(S->getSubStmt(), SubStmt.get(), I); AttrsChanged |= (I != R); if (R) Attrs.push_back(R); } - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); - if (SubStmt.isInvalid()) - return StmtError(); - if (SubStmt.get() == S->getSubStmt() && !AttrsChanged) return S; @@ -7943,8 +8023,7 @@ TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) { TransformedExprs, S->getEndLoc()); } -// C++ Coroutines TS - +// C++ Coroutines template<typename Derived> StmtResult TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { @@ -8052,6 +8131,13 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { return StmtError(); Builder.Deallocate = DeallocRes.get(); + if (auto *ResultDecl = S->getResultDecl()) { + StmtResult Res = getDerived().TransformStmt(ResultDecl); + if (Res.isInvalid()) + return StmtError(); + Builder.ResultDecl = Res.get(); + } + if (auto *ReturnStmt = S->getReturnStmt()) { StmtResult Res = getDerived().TransformStmt(ReturnStmt); if (Res.isInvalid()) @@ -10654,6 +10740,22 @@ OMPClause *TreeTransform<Derived>::TransformOMPXDynCGroupMemClause( Size.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPDoacrossClause(OMPDoacrossClause *C) { + 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 nullptr; + Vars.push_back(EVar.get()); + } + return getDerived().RebuildOMPDoacrossClause( + C->getDependenceType(), C->getDependenceLoc(), C->getColonLoc(), Vars, + C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// @@ -10797,9 +10899,14 @@ TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { - ExprResult ControllingExpr = - getDerived().TransformExpr(E->getControllingExpr()); - if (ControllingExpr.isInvalid()) + ExprResult ControllingExpr; + TypeSourceInfo *ControllingType = nullptr; + if (E->isExprPredicate()) + ControllingExpr = getDerived().TransformExpr(E->getControllingExpr()); + else + ControllingType = getDerived().TransformType(E->getControllingType()); + + if (ControllingExpr.isInvalid() && !ControllingType) return ExprError(); SmallVector<Expr *, 4> AssocExprs; @@ -10822,12 +10929,16 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { AssocExprs.push_back(AssocExpr.get()); } + if (!ControllingType) return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(), E->getDefaultLoc(), E->getRParenLoc(), ControllingExpr.get(), AssocTypes, AssocExprs); + return getDerived().RebuildGenericSelectionExpr( + E->getGenericLoc(), E->getDefaultLoc(), E->getRParenLoc(), + ControllingType, AssocTypes, AssocExprs); } template<typename Derived> @@ -11346,7 +11457,8 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { if (LHS.isInvalid()) return ExprError(); - ExprResult RHS = getDerived().TransformExpr(E->getRHS()); + ExprResult RHS = + getDerived().TransformInitializer(E->getRHS(), /*NotCopyInit=*/false); if (RHS.isInvalid()) return ExprError(); @@ -11606,13 +11718,12 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { bool ExprChanged = false; for (const DesignatedInitExpr::Designator &D : E->designators()) { if (D.isFieldDesignator()) { - Desig.AddDesignator(Designator::getField(D.getFieldName(), - D.getDotLoc(), - D.getFieldLoc())); - if (D.getField()) { + Desig.AddDesignator(Designator::CreateFieldDesignator( + D.getFieldName(), D.getDotLoc(), D.getFieldLoc())); + if (D.getFieldDecl()) { FieldDecl *Field = cast_or_null<FieldDecl>( - getDerived().TransformDecl(D.getFieldLoc(), D.getField())); - if (Field != D.getField()) + getDerived().TransformDecl(D.getFieldLoc(), D.getFieldDecl())); + if (Field != D.getFieldDecl()) // Rebuild the expression when the transformed FieldDecl is // different to the already assigned FieldDecl. ExprChanged = true; @@ -11631,7 +11742,7 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { return ExprError(); Desig.AddDesignator( - Designator::getArray(Index.get(), D.getLBracketLoc())); + Designator::CreateArrayDesignator(Index.get(), D.getLBracketLoc())); ExprChanged = ExprChanged || Init.get() != E->getArrayIndex(D); ArrayExprs.push_back(Index.get()); @@ -11648,10 +11759,8 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { if (End.isInvalid()) return ExprError(); - Desig.AddDesignator(Designator::getArrayRange(Start.get(), - End.get(), - D.getLBracketLoc(), - D.getEllipsisLoc())); + Desig.AddDesignator(Designator::CreateArrayRangeDesignator( + Start.get(), End.get(), D.getLBracketLoc(), D.getEllipsisLoc())); ExprChanged = ExprChanged || Start.get() != E->getArrayRangeStart(D) || End.get() != E->getArrayRangeEnd(D); @@ -11883,10 +11992,6 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { llvm_unreachable("not an overloaded operator?"); } - ExprResult Callee = getDerived().TransformExpr(E->getCallee()); - if (Callee.isInvalid()) - return ExprError(); - ExprResult First; if (E->getOperator() == OO_Amp) First = getDerived().TransformAddressOfOperand(E->getArg(0)); @@ -11897,28 +12002,45 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { ExprResult Second; if (E->getNumArgs() == 2) { - Second = getDerived().TransformExpr(E->getArg(1)); + Second = + getDerived().TransformInitializer(E->getArg(1), /*NotCopyInit=*/false); if (Second.isInvalid()) return ExprError(); } - if (!getDerived().AlwaysRebuild() && - Callee.get() == E->getCallee() && - First.get() == E->getArg(0) && - (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) - return SemaRef.MaybeBindToTemporary(E); - Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); FPOptionsOverride NewOverrides(E->getFPFeatures()); getSema().CurFPFeatures = NewOverrides.applyOverrides(getSema().getLangOpts()); getSema().FpPragmaStack.CurrentValue = NewOverrides; - return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), - E->getOperatorLoc(), - Callee.get(), - First.get(), - Second.get()); + Expr *Callee = E->getCallee(); + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) { + LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), + Sema::LookupOrdinaryName); + if (getDerived().TransformOverloadExprDecls(ULE, ULE->requiresADL(), R)) + return ExprError(); + + return getDerived().RebuildCXXOperatorCallExpr( + E->getOperator(), E->getOperatorLoc(), Callee->getBeginLoc(), + ULE->requiresADL(), R.asUnresolvedSet(), First.get(), Second.get()); + } + + UnresolvedSet<1> Functions; + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) + Callee = ICE->getSubExprAsWritten(); + NamedDecl *DR = cast<DeclRefExpr>(Callee)->getDecl(); + ValueDecl *VD = cast_or_null<ValueDecl>( + getDerived().TransformDecl(DR->getLocation(), DR)); + if (!VD) + return ExprError(); + + if (!isa<CXXMethodDecl>(VD)) + Functions.addDecl(VD); + + return getDerived().RebuildCXXOperatorCallExpr( + E->getOperator(), E->getOperatorLoc(), Callee->getBeginLoc(), + /*RequiresADL=*/false, Functions, First.get(), Second.get()); } template<typename Derived> @@ -13237,37 +13359,6 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { LambdaScopeInfo *LSI = getSema().PushLambdaScope(); Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); - // Transform the template parameters, and add them to the current - // instantiation scope. The null case is handled correctly. - auto TPL = getDerived().TransformTemplateParameterList( - E->getTemplateParameterList()); - LSI->GLTemplateParameterList = TPL; - - // Transform the type of the original lambda's call operator. - // The transformation MUST be done in the CurrentInstantiationScope since - // it introduces a mapping of the original to the newly created - // transformed parameters. - TypeSourceInfo *NewCallOpTSI = nullptr; - { - TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo(); - FunctionProtoTypeLoc OldCallOpFPTL = - OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); - - TypeLocBuilder NewCallOpTLBuilder; - SmallVector<QualType, 4> ExceptionStorage; - TreeTransform *This = this; // Work around gcc.gnu.org/PR56135. - QualType NewCallOpType = TransformFunctionProtoType( - NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(), - [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { - return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI, - ExceptionStorage, Changed); - }); - if (NewCallOpType.isNull()) - return ExprError(); - NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, - NewCallOpType); - } - // Create the local class that will describe the lambda. // FIXME: DependencyKind below is wrong when substituting inside a templated @@ -13284,49 +13375,24 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { DependencyKind = CXXRecordDecl::LDK_NeverDependent; CXXRecordDecl *OldClass = E->getLambdaClass(); - CXXRecordDecl *Class = - getSema().createLambdaClosureType(E->getIntroducerRange(), NewCallOpTSI, - DependencyKind, E->getCaptureDefault()); - + CXXRecordDecl *Class = getSema().createLambdaClosureType( + E->getIntroducerRange(), /*Info=*/nullptr, DependencyKind, + E->getCaptureDefault()); getDerived().transformedLocalDecl(OldClass, {Class}); - std::optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling; - if (getDerived().ReplacingOriginal()) - Mangling = std::make_tuple(OldClass->hasKnownLambdaInternalLinkage(), - OldClass->getLambdaManglingNumber(), - OldClass->getDeviceLambdaManglingNumber(), - OldClass->getLambdaContextDecl()); - - // Build the call operator. - CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition( - Class, E->getIntroducerRange(), NewCallOpTSI, - E->getCallOperator()->getEndLoc(), - NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(), - E->getCallOperator()->getConstexprKind(), - E->getCallOperator()->getStorageClass(), - E->getCallOperator()->getTrailingRequiresClause()); - - LSI->CallOperator = NewCallOperator; - - getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); - getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator}); + CXXMethodDecl *NewCallOperator = + getSema().CreateLambdaCallOperator(E->getIntroducerRange(), Class); + NewCallOperator->setLexicalDeclContext(getSema().CurContext); - // Number the lambda for linkage purposes if necessary. - getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling); + // Enter the scope of the lambda. + getSema().buildLambdaScope(LSI, NewCallOperator, E->getIntroducerRange(), + E->getCaptureDefault(), E->getCaptureDefaultLoc(), + E->hasExplicitParameters(), E->isMutable()); // Introduce the context of the call operator. Sema::ContextRAII SavedContext(getSema(), NewCallOperator, /*NewThisContext*/false); - // Enter the scope of the lambda. - getSema().buildLambdaScope(LSI, NewCallOperator, - E->getIntroducerRange(), - E->getCaptureDefault(), - E->getCaptureDefaultLoc(), - E->hasExplicitParameters(), - E->hasExplicitResultType(), - E->isMutable()); - bool Invalid = false; // Transform captures. @@ -13366,7 +13432,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl( OldVD->getLocation(), InitQualType, NewC.EllipsisLoc, - OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get()); + OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get(), + getSema().CurContext); if (!NewVD) { Invalid = true; break; @@ -13446,6 +13513,61 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } getSema().finishLambdaExplicitCaptures(LSI); + // Transform the template parameters, and add them to the current + // instantiation scope. The null case is handled correctly. + auto TPL = getDerived().TransformTemplateParameterList( + E->getTemplateParameterList()); + LSI->GLTemplateParameterList = TPL; + + // Transform the type of the original lambda's call operator. + // The transformation MUST be done in the CurrentInstantiationScope since + // it introduces a mapping of the original to the newly created + // transformed parameters. + TypeSourceInfo *NewCallOpTSI = nullptr; + { + TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo(); + auto OldCallOpFPTL = + OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); + + TypeLocBuilder NewCallOpTLBuilder; + SmallVector<QualType, 4> ExceptionStorage; + TreeTransform *This = this; // Work around gcc.gnu.org/PR56135. + QualType NewCallOpType = TransformFunctionProtoType( + NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(), + [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { + return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI, + ExceptionStorage, Changed); + }); + if (NewCallOpType.isNull()) + return ExprError(); + NewCallOpTSI = + NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); + } + + getSema().CompleteLambdaCallOperator( + NewCallOperator, E->getCallOperator()->getLocation(), + E->getCallOperator()->getInnerLocStart(), + E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI, + E->getCallOperator()->getConstexprKind(), + E->getCallOperator()->getStorageClass(), + NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(), + E->hasExplicitResultType()); + + getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); + getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator}); + + { + // Number the lambda for linkage purposes if necessary. + Sema::ContextRAII ManglingContext(getSema(), Class->getDeclContext()); + + std::optional<CXXRecordDecl::LambdaNumbering> Numbering; + if (getDerived().ReplacingOriginal()) { + Numbering = OldClass->getLambdaNumbering(); + } + + getSema().handleLambdaNumbering(Class, NewCallOperator, Numbering); + } + // 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( @@ -14028,13 +14150,17 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) { // We've got down to a single element; build a binary operator. Expr *LHS = LeftFold ? Result.get() : Out.get(); Expr *RHS = LeftFold ? Out.get() : Result.get(); - if (Callee) + if (Callee) { + UnresolvedSet<16> Functions; + Functions.append(Callee->decls_begin(), Callee->decls_end()); Result = getDerived().RebuildCXXOperatorCallExpr( BinaryOperator::getOverloadedOperator(E->getOperator()), - E->getEllipsisLoc(), Callee, LHS, RHS); - else + E->getEllipsisLoc(), Callee->getBeginLoc(), Callee->requiresADL(), + Functions, LHS, RHS); + } else { Result = getDerived().RebuildBinaryOperator(E->getEllipsisLoc(), E->getOperator(), LHS, RHS); + } } else Result = Out; @@ -14076,9 +14202,8 @@ TreeTransform<Derived>::TransformCXXParenListInitExpr(CXXParenListInitExpr *E) { TransformedInits)) return ExprError(); - return getDerived().RebuildCXXParenListInitExpr( - TransformedInits, E->getType(), E->getUserSpecifiedInitExprs().size(), - E->getInitLoc(), E->getBeginLoc(), E->getEndLoc()); + return getDerived().RebuildParenListExpr(E->getBeginLoc(), TransformedInits, + E->getEndLoc()); } template<typename Derived> @@ -14600,7 +14725,12 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { oldCapture)); assert(blockScope->CaptureMap.count(newCapture)); } - assert(oldBlock->capturesCXXThis() == blockScope->isCXXThisCaptured()); + + // The this pointer may not be captured by the instantiated block, even when + // it's captured by the original block, if the expression causing the + // capture is in the discarded branch of a constexpr if statement. + assert((!blockScope->isCXXThisCaptured() || oldBlock->capturesCXXThis()) && + "this pointer isn't captured in the old block"); } #endif @@ -15034,14 +15164,11 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, return Template.get(); } -template<typename Derived> -ExprResult -TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, - SourceLocation OpLoc, - Expr *OrigCallee, - Expr *First, - Expr *Second) { - Expr *Callee = OrigCallee->IgnoreParenCasts(); +template <typename Derived> +ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr( + OverloadedOperatorKind Op, SourceLocation OpLoc, SourceLocation CalleeLoc, + bool RequiresADL, const UnresolvedSetImpl &Functions, Expr *First, + Expr *Second) { bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus); if (First->getObjectKind() == OK_ObjCProperty) { @@ -15066,8 +15193,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, if (Op == OO_Subscript) { if (!First->getType()->isOverloadableType() && !Second->getType()->isOverloadableType()) - return getSema().CreateBuiltinArraySubscriptExpr( - First, Callee->getBeginLoc(), Second, OpLoc); + return getSema().CreateBuiltinArraySubscriptExpr(First, CalleeLoc, Second, + OpLoc); } else if (Op == OO_Arrow) { // It is possible that the type refers to a RecoveryExpr created earlier // in the tree transformation. @@ -15101,27 +15228,6 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, } } - // Compute the transformed set of functions (and function templates) to be - // used during overload resolution. - UnresolvedSet<16> Functions; - bool RequiresADL; - - if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) { - Functions.append(ULE->decls_begin(), ULE->decls_end()); - // If the overload could not be resolved in the template definition - // (because we had a dependent argument), ADL is performed as part of - // template instantiation. - RequiresADL = ULE->requiresADL(); - } else { - // If we've resolved this to a particular non-member function, just call - // that function. If we resolved it to a member function, - // CreateOverloaded* will find that function for us. - NamedDecl *ND = cast<DeclRefExpr>(Callee)->getDecl(); - if (!isa<CXXMethodDecl>(ND)) - Functions.addDecl(ND); - RequiresADL = false; - } - // Add any functions found via argument-dependent lookup. Expr *Args[2] = { First, Second }; unsigned NumArgs = 1 + (Second != nullptr); @@ -15134,23 +15240,6 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, RequiresADL); } - if (Op == OO_Subscript) { - SourceLocation LBrace; - SourceLocation RBrace; - - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) { - DeclarationNameLoc NameLoc = DRE->getNameInfo().getInfo(); - LBrace = NameLoc.getCXXOperatorNameBeginLoc(); - RBrace = NameLoc.getCXXOperatorNameEndLoc(); - } else { - LBrace = Callee->getBeginLoc(); - RBrace = OpLoc; - } - - return SemaRef.CreateOverloadedArraySubscriptExpr(LBrace, RBrace, - First, Second); - } - // Create the overloaded operator invocation for binary operators. BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); ExprResult Result = SemaRef.CreateOverloadedBinOp( |