summaryrefslogtreecommitdiff
path: root/lib/Sema/TreeTransform.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r--lib/Sema/TreeTransform.h552
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();
}