diff options
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r-- | lib/Sema/TreeTransform.h | 552 |
1 files changed, 434 insertions, 118 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index f8e65a119c3ce..693b5c088acc1 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H #define LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H +#include "CoroutineStmtBuilder.h" #include "TypeLocBuilder.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" @@ -307,6 +308,17 @@ public: /// QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL); + /// \brief Transform a type that is permitted to produce a + /// DeducedTemplateSpecializationType. + /// + /// This is used in the (relatively rare) contexts where it is acceptable + /// for transformation to produce a class template type with deduced + /// template arguments. + /// @{ + QualType TransformTypeWithDeducedTST(QualType T); + TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI); + /// @} + /// \brief Transform the given statement. /// /// By default, this routine transforms a statement by delegating to the @@ -505,7 +517,8 @@ public: TransformTemplateName(CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc, QualType ObjectType = QualType(), - NamedDecl *FirstQualifierInScope = nullptr); + NamedDecl *FirstQualifierInScope = nullptr, + bool AllowInjectedClassName = false); /// \brief Transform the given template argument. /// @@ -671,6 +684,16 @@ public: OMPClause *Transform ## Class(Class *S); #include "clang/Basic/OpenMPKinds.def" + /// \brief Build a new qualified type given its unqualified type and type + /// qualifiers. + /// + /// By default, this routine adds type qualifiers only to types that can + /// have qualifiers, and silently suppresses those qualifiers that are not + /// permitted. Subclasses may override this routine to provide different + /// behavior. + QualType RebuildQualifiedType(QualType T, SourceLocation Loc, + Qualifiers Quals); + /// \brief Build a new pointer type given its pointee type. /// /// By default, performs semantic analysis when building the pointer type. @@ -875,6 +898,14 @@ public: /*IsDependent*/ false); } + /// By default, builds a new DeducedTemplateSpecializationType with the given + /// deduced type. + QualType RebuildDeducedTemplateSpecializationType(TemplateName Template, + QualType Deduced) { + return SemaRef.Context.getDeducedTemplateSpecializationType( + Template, Deduced, /*IsDependent*/ false); + } + /// \brief Build a new template specialization type. /// /// By default, performs semantic analysis when building the template @@ -889,7 +920,7 @@ public: /// By default, builds a new ParenType type from the inner type. /// Subclasses may override this routine to provide different behavior. QualType RebuildParenType(QualType InnerType) { - return SemaRef.Context.getParenType(InnerType); + return SemaRef.BuildParenType(InnerType); } /// \brief Build a new qualified name type. @@ -916,14 +947,15 @@ public: NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo *Name, SourceLocation NameLoc, - TemplateArgumentListInfo &Args) { + TemplateArgumentListInfo &Args, + bool AllowInjectedClassName) { // Rebuild the template name. // TODO: avoid TemplateName abstraction CXXScopeSpec SS; SS.Adopt(QualifierLoc); TemplateName InstName = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), - nullptr); + nullptr, AllowInjectedClassName); if (InstName.isNull()) return QualType(); @@ -958,7 +990,8 @@ public: SourceLocation KeywordLoc, NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo *Id, - SourceLocation IdLoc) { + SourceLocation IdLoc, + bool DeducedTSTContext) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); @@ -970,9 +1003,25 @@ public: Id); } - if (Keyword == ETK_None || Keyword == ETK_Typename) - return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, - *Id, IdLoc); + if (Keyword == ETK_None || Keyword == ETK_Typename) { + QualType T = SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); + // If a dependent name resolves to a deduced template specialization type, + // check that we're in one of the syntactic contexts permitting it. + if (!DeducedTSTContext) { + if (auto *Deduced = dyn_cast_or_null<DeducedTemplateSpecializationType>( + T.isNull() ? nullptr : T->getContainedDeducedType())) { + SemaRef.Diag(IdLoc, diag::err_dependent_deduced_tst) + << (int)SemaRef.getTemplateNameKindForDiagnostics( + Deduced->getTemplateName()) + << QualType(QualifierLoc.getNestedNameSpecifier()->getAsType(), 0); + if (auto *TD = Deduced->getTemplateName().getAsTemplateDecl()) + SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here); + return QualType(); + } + } + return T; + } TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); @@ -1088,7 +1137,8 @@ public: const IdentifierInfo &Name, SourceLocation NameLoc, QualType ObjectType, - NamedDecl *FirstQualifierInScope); + NamedDecl *FirstQualifierInScope, + bool AllowInjectedClassName); /// \brief Build a new template name given a nested name specifier and the /// overloaded operator name that is referred to as a template. @@ -1100,7 +1150,8 @@ public: TemplateName RebuildTemplateName(CXXScopeSpec &SS, OverloadedOperatorKind Operator, SourceLocation NameLoc, - QualType ObjectType); + QualType ObjectType, + bool AllowInjectedClassName); /// \brief Build a new template name given a template template parameter pack /// and the @@ -1312,16 +1363,28 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result) { - return getSema().BuildCoreturnStmt(CoreturnLoc, Result); + StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result, + bool IsImplicit) { + return getSema().BuildCoreturnStmt(CoreturnLoc, Result, IsImplicit); + } + + /// \brief Build a new co_await expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCoawaitExpr(SourceLocation CoawaitLoc, Expr *Result, + bool IsImplicit) { + return getSema().BuildResolvedCoawaitExpr(CoawaitLoc, Result, IsImplicit); } /// \brief Build a new co_await expression. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildCoawaitExpr(SourceLocation CoawaitLoc, Expr *Result) { - return getSema().BuildCoawaitExpr(CoawaitLoc, Result); + ExprResult RebuildDependentCoawaitExpr(SourceLocation CoawaitLoc, + Expr *Result, + UnresolvedLookupExpr *Lookup) { + return getSema().BuildUnresolvedCoawaitExpr(CoawaitLoc, Result, Lookup); } /// \brief Build a new co_yield expression. @@ -1332,6 +1395,10 @@ public: return getSema().BuildCoyieldExpr(CoyieldLoc, Result); } + StmtResult RebuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) { + return getSema().BuildCoroutineBodyStmt(Args); + } + /// \brief Build a new Objective-C \@try statement. /// /// By default, performs semantic analysis to build the new statement. @@ -3146,6 +3213,10 @@ private: TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *FirstQualifierInScope, CXXScopeSpec &SS); + + QualType TransformDependentNameType(TypeLocBuilder &TLB, + DependentNameTypeLoc TL, + bool DeducibleTSTContext); }; template<typename Derived> @@ -3563,6 +3634,19 @@ TreeTransform<Derived> case DeclarationName::CXXUsingDirective: return NameInfo; + case DeclarationName::CXXDeductionGuideName: { + TemplateDecl *OldTemplate = Name.getCXXDeductionGuideTemplate(); + TemplateDecl *NewTemplate = cast_or_null<TemplateDecl>( + getDerived().TransformDecl(NameInfo.getLoc(), OldTemplate)); + if (!NewTemplate) + return DeclarationNameInfo(); + + DeclarationNameInfo NewNameInfo(NameInfo); + NewNameInfo.setName( + SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(NewTemplate)); + return NewNameInfo; + } + case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: { @@ -3602,7 +3686,8 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc, QualType ObjectType, - NamedDecl *FirstQualifierInScope) { + NamedDecl *FirstQualifierInScope, + bool AllowInjectedClassName) { if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getTemplateDecl(); assert(Template && "qualified template name must refer to a template"); @@ -3639,11 +3724,12 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, *DTN->getIdentifier(), NameLoc, ObjectType, - FirstQualifierInScope); + FirstQualifierInScope, + AllowInjectedClassName); } return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc, - ObjectType); + ObjectType, AllowInjectedClassName); } if (TemplateDecl *Template = Name.getAsTemplateDecl()) { @@ -3782,7 +3868,9 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Expression: { // Template argument expressions are constant expressions. EnterExpressionEvaluationContext Unevaluated( - getSema(), Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated); + getSema(), Uneval + ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated); Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); @@ -4035,11 +4123,57 @@ TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) { llvm_unreachable("unhandled type loc!"); } -/// FIXME: By default, this routine adds type qualifiers only to types -/// that can have qualifiers, and silently suppresses those qualifiers -/// that are not permitted (e.g., qualifiers on reference or function -/// types). This is the right thing for template instantiation, but -/// probably not for other clients. +template<typename Derived> +QualType TreeTransform<Derived>::TransformTypeWithDeducedTST(QualType T) { + if (!isa<DependentNameType>(T)) + return TransformType(T); + + if (getDerived().AlreadyTransformed(T)) + return T; + TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(T, + getDerived().getBaseLocation()); + TypeSourceInfo *NewDI = getDerived().TransformTypeWithDeducedTST(DI); + return NewDI ? NewDI->getType() : QualType(); +} + +template<typename Derived> +TypeSourceInfo * +TreeTransform<Derived>::TransformTypeWithDeducedTST(TypeSourceInfo *DI) { + if (!isa<DependentNameType>(DI->getType())) + return TransformType(DI); + + // Refine the base location to the type's location. + TemporaryBase Rebase(*this, DI->getTypeLoc().getBeginLoc(), + getDerived().getBaseEntity()); + if (getDerived().AlreadyTransformed(DI->getType())) + return DI; + + TypeLocBuilder TLB; + + TypeLoc TL = DI->getTypeLoc(); + TLB.reserve(TL.getFullDataSize()); + + Qualifiers Quals; + auto QTL = TL.getAs<QualifiedTypeLoc>(); + if (QTL) + TL = QTL.getUnqualifiedLoc(); + + auto DNTL = TL.castAs<DependentNameTypeLoc>(); + + QualType Result = getDerived().TransformDependentNameType( + TLB, DNTL, /*DeducedTSTContext*/true); + if (Result.isNull()) + return nullptr; + + if (QTL) { + Result = getDerived().RebuildQualifiedType( + Result, QTL.getBeginLoc(), QTL.getType().getLocalQualifiers()); + TLB.TypeWasModifiedSafely(Result); + } + + return TLB.getTypeSourceInfo(SemaRef.Context, Result); +} + template<typename Derived> QualType TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, @@ -4050,64 +4184,71 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, if (Result.isNull()) return QualType(); - // Silently suppress qualifiers if the result type can't be qualified. - // FIXME: this is the right thing for template instantiation, but - // probably not for other clients. - if (Result->isFunctionType() || Result->isReferenceType()) - return Result; + Result = getDerived().RebuildQualifiedType(Result, T.getBeginLoc(), Quals); + + // RebuildQualifiedType might have updated the type, but not in a way + // that invalidates the TypeLoc. (There's no location information for + // qualifiers.) + TLB.TypeWasModifiedSafely(Result); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T, + SourceLocation Loc, + Qualifiers Quals) { + // C++ [dcl.fct]p7: + // [When] adding cv-qualifications on top of the function type [...] the + // cv-qualifiers are ignored. + // C++ [dcl.ref]p1: + // when the cv-qualifiers are introduced through the use of a typedef-name + // or decltype-specifier [...] the cv-qualifiers are ignored. + // Note that [dcl.ref]p1 lists all cases in which cv-qualifiers can be + // applied to a reference type. + // FIXME: This removes all qualifiers, not just cv-qualifiers! + if (T->isFunctionType() || T->isReferenceType()) + return T; // Suppress Objective-C lifetime qualifiers if they don't make sense for the // resulting type. if (Quals.hasObjCLifetime()) { - if (!Result->isObjCLifetimeType() && !Result->isDependentType()) + if (!T->isObjCLifetimeType() && !T->isDependentType()) Quals.removeObjCLifetime(); - else if (Result.getObjCLifetime()) { + else if (T.getObjCLifetime()) { // Objective-C ARC: // A lifetime qualifier applied to a substituted template parameter // overrides the lifetime qualifier from the template argument. const AutoType *AutoTy; if (const SubstTemplateTypeParmType *SubstTypeParam - = dyn_cast<SubstTemplateTypeParmType>(Result)) { + = dyn_cast<SubstTemplateTypeParmType>(T)) { QualType Replacement = SubstTypeParam->getReplacementType(); Qualifiers Qs = Replacement.getQualifiers(); Qs.removeObjCLifetime(); - Replacement - = SemaRef.Context.getQualifiedType(Replacement.getUnqualifiedType(), - Qs); - Result = SemaRef.Context.getSubstTemplateTypeParmType( - SubstTypeParam->getReplacedParameter(), - Replacement); - TLB.TypeWasModifiedSafely(Result); - } else if ((AutoTy = dyn_cast<AutoType>(Result)) && AutoTy->isDeduced()) { + Replacement = SemaRef.Context.getQualifiedType( + Replacement.getUnqualifiedType(), Qs); + T = SemaRef.Context.getSubstTemplateTypeParmType( + SubstTypeParam->getReplacedParameter(), Replacement); + } else if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) { // 'auto' types behave the same way as template parameters. QualType Deduced = AutoTy->getDeducedType(); Qualifiers Qs = Deduced.getQualifiers(); Qs.removeObjCLifetime(); - Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), - Qs); - Result = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(), - AutoTy->isDependentType()); - TLB.TypeWasModifiedSafely(Result); + Deduced = + SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), Qs); + T = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(), + AutoTy->isDependentType()); } else { // Otherwise, complain about the addition of a qualifier to an // already-qualified type. - SourceRange R = T.getUnqualifiedLoc().getSourceRange(); - SemaRef.Diag(R.getBegin(), diag::err_attr_objc_ownership_redundant) - << Result << R; - + // FIXME: Why is this check not in Sema::BuildQualifiedType? + SemaRef.Diag(Loc, diag::err_attr_objc_ownership_redundant) << T; Quals.removeObjCLifetime(); } } } - if (!Quals.empty()) { - Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals); - // BuildQualifiedType might not add qualifiers if they are invalid. - if (Result.hasLocalQualifiers()) - TLB.push<QualifiedTypeLoc>(Result); - // No location information to preserve. - } - return Result; + return SemaRef.BuildQualifiedType(T, Loc, Quals); } template<typename Derived> @@ -4153,11 +4294,9 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope( TemplateSpecializationTypeLoc SpecTL = TL.castAs<TemplateSpecializationTypeLoc>(); - TemplateName Template - = getDerived().TransformTemplateName(SS, - SpecTL.getTypePtr()->getTemplateName(), - SpecTL.getTemplateNameLoc(), - ObjectType, UnqualLookup); + TemplateName Template = getDerived().TransformTemplateName( + SS, SpecTL.getTypePtr()->getTemplateName(), SpecTL.getTemplateNameLoc(), + ObjectType, UnqualLookup, /*AllowInjectedClassName*/true); if (Template.isNull()) return nullptr; @@ -4171,7 +4310,8 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope( = getDerived().RebuildTemplateName(SS, *SpecTL.getTypePtr()->getIdentifier(), SpecTL.getTemplateNameLoc(), - ObjectType, UnqualLookup); + ObjectType, UnqualLookup, + /*AllowInjectedClassName*/true); if (Template.isNull()) return nullptr; @@ -4435,8 +4575,8 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB, Expr *Size = TL.getSizeExpr(); if (Size) { - EnterExpressionEvaluationContext Unevaluated(SemaRef, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); Size = getDerived().TransformExpr(Size).template getAs<Expr>(); Size = SemaRef.ActOnConstantExpression(Size).get(); } @@ -4482,8 +4622,15 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB, if (ElementType.isNull()) return QualType(); - ExprResult SizeResult - = getDerived().TransformExpr(T->getSizeExpr()); + ExprResult SizeResult; + { + EnterExpressionEvaluationContext Context( + SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + SizeResult = getDerived().TransformExpr(T->getSizeExpr()); + } + if (SizeResult.isInvalid()) + return QualType(); + SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get()); if (SizeResult.isInvalid()) return QualType(); @@ -4522,8 +4669,8 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, return QualType(); // Array bounds are constant expressions. - EnterExpressionEvaluationContext Unevaluated(SemaRef, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); // Prefer the expression from the TypeLoc; the other may have been uniqued. Expr *origSize = TL.getSizeExpr(); @@ -4572,8 +4719,8 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType( return QualType(); // Vector sizes are constant expressions. - EnterExpressionEvaluationContext Unevaluated(SemaRef, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); Size = SemaRef.ActOnConstantExpression(Size); @@ -5040,8 +5187,8 @@ bool TreeTransform<Derived>::TransformExceptionSpec( // Instantiate a dynamic noexcept expression, if any. if (ESI.Type == EST_ComputedNoexcept) { - EnterExpressionEvaluationContext Unevaluated(getSema(), - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + getSema(), Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr); if (NoexceptExpr.isInvalid()) return true; @@ -5208,8 +5355,9 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, TypeOfExprTypeLoc TL) { // typeof expressions are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr()); if (E.isInvalid()) @@ -5266,8 +5414,9 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, const DecltypeType *T = TL.getTypePtr(); // decltype expressions are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, - nullptr, /*IsDecltype=*/ true); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, + /*IsDecltype=*/true); ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); if (E.isInvalid()) @@ -5342,6 +5491,37 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, } template<typename Derived> +QualType TreeTransform<Derived>::TransformDeducedTemplateSpecializationType( + TypeLocBuilder &TLB, DeducedTemplateSpecializationTypeLoc TL) { + const DeducedTemplateSpecializationType *T = TL.getTypePtr(); + + CXXScopeSpec SS; + TemplateName TemplateName = getDerived().TransformTemplateName( + SS, T->getTemplateName(), TL.getTemplateNameLoc()); + if (TemplateName.isNull()) + return QualType(); + + QualType OldDeduced = T->getDeducedType(); + QualType NewDeduced; + if (!OldDeduced.isNull()) { + NewDeduced = getDerived().TransformType(OldDeduced); + if (NewDeduced.isNull()) + return QualType(); + } + + QualType Result = getDerived().RebuildDeducedTemplateSpecializationType( + TemplateName, NewDeduced); + if (Result.isNull()) + return QualType(); + + DeducedTemplateSpecializationTypeLoc NewTL = + TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); + + return Result; +} + +template<typename Derived> QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB, RecordTypeLoc TL) { const RecordType *T = TL.getTypePtr(); @@ -5811,8 +5991,14 @@ TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB, } template<typename Derived> -QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL) { +QualType TreeTransform<Derived>::TransformDependentNameType( + TypeLocBuilder &TLB, DependentNameTypeLoc TL) { + return TransformDependentNameType(TLB, TL, false); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformDependentNameType( + TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext) { const DependentNameType *T = TL.getTypePtr(); NestedNameSpecifierLoc QualifierLoc @@ -5825,7 +6011,8 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, TL.getElaboratedKeywordLoc(), QualifierLoc, T->getIdentifier(), - TL.getNameLoc()); + TL.getNameLoc(), + DeducedTSTContext); if (Result.isNull()) return QualType(); @@ -5879,12 +6066,10 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, NewTemplateArgs)) return QualType(); - QualType Result - = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), - QualifierLoc, - T->getIdentifier(), - TL.getTemplateNameLoc(), - NewTemplateArgs); + QualType Result = getDerived().RebuildDependentTemplateSpecializationType( + T->getKeyword(), QualifierLoc, T->getIdentifier(), + TL.getTemplateNameLoc(), NewTemplateArgs, + /*AllowInjectedClassName*/ false); if (Result.isNull()) return QualType(); @@ -6206,8 +6391,8 @@ StmtResult TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { ExprResult LHS, RHS; { - EnterExpressionEvaluationContext Unevaluated(SemaRef, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); // Transform the left-hand case value. LHS = getDerived().TransformExpr(S->getLHS()); @@ -6667,9 +6852,99 @@ TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) { template<typename Derived> StmtResult TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { - // The coroutine body should be re-formed by the caller if necessary. - // FIXME: The coroutine body is always rebuilt by ActOnFinishFunctionBody - return getDerived().TransformStmt(S->getBody()); + auto *ScopeInfo = SemaRef.getCurFunction(); + auto *FD = cast<FunctionDecl>(SemaRef.CurContext); + assert(FD && ScopeInfo && !ScopeInfo->CoroutinePromise && + ScopeInfo->NeedsCoroutineSuspends && + ScopeInfo->CoroutineSuspends.first == nullptr && + ScopeInfo->CoroutineSuspends.second == nullptr && + "expected clean scope info"); + + // Set that we have (possibly-invalid) suspend points before we do anything + // that may fail. + ScopeInfo->setNeedsCoroutineSuspends(false); + + // The new CoroutinePromise object needs to be built and put into the current + // FunctionScopeInfo before any transformations or rebuilding occurs. + auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation()); + if (!Promise) + return StmtError(); + getDerived().transformedLocalDecl(S->getPromiseDecl(), Promise); + ScopeInfo->CoroutinePromise = Promise; + + // Transform the implicit coroutine statements we built during the initial + // parse. + StmtResult InitSuspend = getDerived().TransformStmt(S->getInitSuspendStmt()); + if (InitSuspend.isInvalid()) + return StmtError(); + StmtResult FinalSuspend = + getDerived().TransformStmt(S->getFinalSuspendStmt()); + if (FinalSuspend.isInvalid()) + return StmtError(); + ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get()); + assert(isa<Expr>(InitSuspend.get()) && isa<Expr>(FinalSuspend.get())); + + StmtResult BodyRes = getDerived().TransformStmt(S->getBody()); + if (BodyRes.isInvalid()) + return StmtError(); + + CoroutineStmtBuilder Builder(SemaRef, *FD, *ScopeInfo, BodyRes.get()); + if (Builder.isInvalid()) + return StmtError(); + + Expr *ReturnObject = S->getReturnValueInit(); + assert(ReturnObject && "the return object is expected to be valid"); + ExprResult Res = getDerived().TransformInitializer(ReturnObject, + /*NoCopyInit*/ false); + if (Res.isInvalid()) + return StmtError(); + 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(); + } else { + if (auto *OnFallthrough = S->getFallthroughHandler()) { + StmtResult Res = getDerived().TransformStmt(OnFallthrough); + if (Res.isInvalid()) + return StmtError(); + Builder.OnFallthrough = Res.get(); + } + + if (auto *OnException = S->getExceptionHandler()) { + StmtResult Res = getDerived().TransformStmt(OnException); + if (Res.isInvalid()) + return StmtError(); + Builder.OnException = Res.get(); + } + + if (auto *OnAllocFailure = S->getReturnStmtOnAllocFailure()) { + StmtResult Res = getDerived().TransformStmt(OnAllocFailure); + if (Res.isInvalid()) + return StmtError(); + Builder.ReturnStmtOnAllocFailure = Res.get(); + } + + // Transform any additional statements we may have already built + assert(S->getAllocate() && S->getDeallocate() && + "allocation and deallocation calls must already be built"); + ExprResult AllocRes = getDerived().TransformExpr(S->getAllocate()); + if (AllocRes.isInvalid()) + return StmtError(); + Builder.Allocate = AllocRes.get(); + + ExprResult DeallocRes = getDerived().TransformExpr(S->getDeallocate()); + if (DeallocRes.isInvalid()) + return StmtError(); + Builder.Deallocate = DeallocRes.get(); + } + + return getDerived().RebuildCoroutineBodyStmt(Builder); } template<typename Derived> @@ -6682,7 +6957,8 @@ TreeTransform<Derived>::TransformCoreturnStmt(CoreturnStmt *S) { // Always rebuild; we don't know if this needs to be injected into a new // context or if the promise type has changed. - return getDerived().RebuildCoreturnStmt(S->getKeywordLoc(), Result.get()); + return getDerived().RebuildCoreturnStmt(S->getKeywordLoc(), Result.get(), + S->isImplicit()); } template<typename Derived> @@ -6695,7 +6971,29 @@ TreeTransform<Derived>::TransformCoawaitExpr(CoawaitExpr *E) { // Always rebuild; we don't know if this needs to be injected into a new // context or if the promise type has changed. - return getDerived().RebuildCoawaitExpr(E->getKeywordLoc(), Result.get()); + return getDerived().RebuildCoawaitExpr(E->getKeywordLoc(), Result.get(), + E->isImplicit()); +} + +template <typename Derived> +ExprResult +TreeTransform<Derived>::TransformDependentCoawaitExpr(DependentCoawaitExpr *E) { + ExprResult OperandResult = getDerived().TransformInitializer(E->getOperand(), + /*NotCopyInit*/ false); + if (OperandResult.isInvalid()) + return ExprError(); + + ExprResult LookupResult = getDerived().TransformUnresolvedLookupExpr( + E->getOperatorCoawaitLookup()); + + if (LookupResult.isInvalid()) + return ExprError(); + + // Always rebuild; we don't know if this needs to be injected into a new + // context or if the promise type has changed. + return getDerived().RebuildDependentCoawaitExpr( + E->getKeywordLoc(), OperandResult.get(), + cast<UnresolvedLookupExpr>(LookupResult.get())); } template<typename Derived> @@ -7239,8 +7537,12 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective( StmtResult Body; { Sema::CompoundScopeRAII CompoundScope(getSema()); - Body = getDerived().TransformStmt( - cast<CapturedStmt>(D->getAssociatedStmt())->getCapturedStmt()); + int ThisCaptureLevel = + Sema::getOpenMPCaptureLevels(D->getDirectiveKind()); + Stmt *CS = D->getAssociatedStmt(); + while (--ThisCaptureLevel >= 0) + CS = cast<CapturedStmt>(CS)->getCapturedStmt(); + Body = getDerived().TransformStmt(CS); } AssociatedStmt = getDerived().getSema().ActOnOpenMPRegionEnd(Body, TClauses); @@ -8642,8 +8944,9 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr( // C++0x [expr.sizeof]p1: // The operand is either an expression, which is an unevaluated operand // [...] - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); // Try to recover if we have something like sizeof(T::X) where X is a type. // Notably, there must be *exactly* one set of parens if X is a type. @@ -8855,7 +9158,7 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { return E; Sema::FPContractStateRAII FPContractState(getSema()); - getSema().FPFeatures.fp_contract = E->isFPContractable(); + getSema().FPFeatures = E->getFPFeatures(); return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get()); @@ -9335,7 +9638,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { return SemaRef.MaybeBindToTemporary(E); Sema::FPContractStateRAII FPContractState(getSema()); - getSema().FPFeatures.fp_contract = E->isFPContractable(); + getSema().FPFeatures = E->getFPFeatures(); return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), E->getOperatorLoc(), @@ -9435,7 +9738,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXFunctionalCastExpr( CXXFunctionalCastExpr *E) { - TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten()); + TypeSourceInfo *Type = + getDerived().TransformTypeWithDeducedTST(E->getTypeInfoAsWritten()); if (!Type) return ExprError(); @@ -9478,8 +9782,9 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { // after we perform semantic analysis. We speculatively assume it is // unevaluated; it will get fixed later if the subexpression is in fact // potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); if (SubExpr.isInvalid()) @@ -9514,7 +9819,8 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { E->getLocEnd()); } - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); if (SubExpr.isInvalid()) @@ -9624,8 +9930,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { // Transform the type that we're allocating - TypeSourceInfo *AllocTypeInfo - = getDerived().TransformType(E->getAllocatedTypeSourceInfo()); + TypeSourceInfo *AllocTypeInfo = + getDerived().TransformTypeWithDeducedTST(E->getAllocatedTypeSourceInfo()); if (!AllocTypeInfo) return ExprError(); @@ -10128,7 +10434,8 @@ TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { ExprResult SubExpr; { - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); SubExpr = getDerived().TransformExpr(E->getDimensionExpression()); if (SubExpr.isInvalid()) return ExprError(); @@ -10149,7 +10456,8 @@ ExprResult TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) { ExprResult SubExpr; { - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); SubExpr = getDerived().TransformExpr(E->getQueriedExpression()); if (SubExpr.isInvalid()) return ExprError(); @@ -10336,7 +10644,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( CXXTemporaryObjectExpr *E) { - TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + TypeSourceInfo *T = + getDerived().TransformTypeWithDeducedTST(E->getTypeSourceInfo()); if (!T) return ExprError(); @@ -10384,8 +10693,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { C != CEnd; ++C) { if (!E->isInitCapture(C)) continue; - EnterExpressionEvaluationContext EEEC(getSema(), - Sema::PotentiallyEvaluated); + EnterExpressionEvaluationContext EEEC( + getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated); ExprResult NewExprInitResult = getDerived().TransformInitializer( C->getCapturedVar()->getInit(), C->getCapturedVar()->getInitStyle() == VarDecl::CallInit); @@ -10461,7 +10770,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { auto *P = NewCallOperator->getParamDecl(I); if (P->hasUninstantiatedDefaultArg()) { EnterExpressionEvaluationContext Eval( - getSema(), Sema::PotentiallyEvaluatedIfUsed, P); + getSema(), + Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, P); ExprResult R = getDerived().TransformExpr( E->getCallOperator()->getParamDecl(I)->getDefaultArg()); P->setDefaultArg(R.get()); @@ -10601,7 +10911,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. - getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + getSema().PushExpressionEvaluationContext( + Sema::ExpressionEvaluationContext::PotentiallyEvaluated); // Instantiate the body of the lambda expression. StmtResult Body = @@ -10633,7 +10944,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { - TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + TypeSourceInfo *T = + getDerived().TransformTypeWithDeducedTST(E->getTypeSourceInfo()); if (!T) return ExprError(); @@ -10836,7 +11148,8 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) { - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult SubExpr = getDerived().TransformExpr(E->getOperand()); if (SubExpr.isInvalid()) return ExprError(); @@ -10869,7 +11182,8 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { if (!E->isValueDependent()) return E; - EnterExpressionEvaluationContext Unevaluated(getSema(), Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + getSema(), Sema::ExpressionEvaluationContext::Unevaluated); ArrayRef<TemplateArgument> PackArgs; TemplateArgument ArgStorage; @@ -12018,7 +12332,8 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, const IdentifierInfo &Name, SourceLocation NameLoc, QualType ObjectType, - NamedDecl *FirstQualifierInScope) { + NamedDecl *FirstQualifierInScope, + bool AllowInjectedClassName) { UnqualifiedId TemplateName; TemplateName.setIdentifier(&Name, NameLoc); Sema::TemplateTy Template; @@ -12027,7 +12342,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, SS, TemplateKWLoc, TemplateName, ParsedType::make(ObjectType), /*EnteringContext=*/false, - Template); + Template, AllowInjectedClassName); return Template.get(); } @@ -12036,7 +12351,8 @@ TemplateName TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, OverloadedOperatorKind Operator, SourceLocation NameLoc, - QualType ObjectType) { + QualType ObjectType, + bool AllowInjectedClassName) { UnqualifiedId Name; // FIXME: Bogus location information. SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc }; @@ -12047,7 +12363,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, SS, TemplateKWLoc, Name, ParsedType::make(ObjectType), /*EnteringContext=*/false, - Template); + Template, AllowInjectedClassName); return Template.get(); } |