diff options
author | Saar Raz <saar@raz.email> | 2020-02-03 15:44:33 +0200 |
---|---|---|
committer | Saar Raz <saar@raz.email> | 2020-02-03 16:53:14 +0200 |
commit | 1ac1c4b4850c1a507caa7da068f44a45ef4ba3c7 (patch) | |
tree | e854f23be39a895eec3de22d8dab2836b7f6fe53 /clang/lib/Sema | |
parent | c822edc11bf0583f0d4e0f6458ca60f57bc621ed (diff) | |
download | bcm5719-llvm-1ac1c4b4850c1a507caa7da068f44a45ef4ba3c7.tar.gz bcm5719-llvm-1ac1c4b4850c1a507caa7da068f44a45ef4ba3c7.zip |
[Concepts] Instantiate invented template type parameter type-constraint along with function parameters
We previously instantiated type-constraints of template type parameters along with the type parameter itself,
this caused problems when the type-constraints created by abbreviated templates refreneced other parameters
in the abbreviated templates.
When encountering a template type parameter with a type constraint, if it is implicit, delay instantiation of
the type-constraint until the function parameter which created the invented template type parameter is
instantiated.
Reland after fixing bug caused by another flow reaching SubstParmVarDecl and instantiating the TypeConstraint
a second time.
(cherry picked from commit 84959ae47f447fca9d56a9c61e8c46e993d0387a)
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 129 | ||||
-rwxr-xr-x | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 46 |
2 files changed, 155 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index dff336f2ff2..a9357ede700 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyDeclStackTrace.h" +#include "clang/AST/TypeVisitor.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Stack.h" #include "clang/Sema/DeclSpec.h" @@ -2145,6 +2146,94 @@ void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, UpdateExceptionSpec(New, ESI); } +namespace { + + struct GetContainedInventedTypeParmVisitor : + public TypeVisitor<GetContainedInventedTypeParmVisitor, + TemplateTypeParmDecl *> { + using TypeVisitor<GetContainedInventedTypeParmVisitor, + TemplateTypeParmDecl *>::Visit; + + TemplateTypeParmDecl *Visit(QualType T) { + if (T.isNull()) + return nullptr; + return Visit(T.getTypePtr()); + } + // The deduced type itself. + TemplateTypeParmDecl *VisitTemplateTypeParmType( + const TemplateTypeParmType *T) { + if (!T->getDecl()->isImplicit()) + return nullptr; + return T->getDecl(); + } + + // Only these types can contain 'auto' types, and subsequently be replaced + // by references to invented parameters. + + TemplateTypeParmDecl *VisitElaboratedType(const ElaboratedType *T) { + return Visit(T->getNamedType()); + } + + TemplateTypeParmDecl *VisitPointerType(const PointerType *T) { + return Visit(T->getPointeeType()); + } + + TemplateTypeParmDecl *VisitBlockPointerType(const BlockPointerType *T) { + return Visit(T->getPointeeType()); + } + + TemplateTypeParmDecl *VisitReferenceType(const ReferenceType *T) { + return Visit(T->getPointeeTypeAsWritten()); + } + + TemplateTypeParmDecl *VisitMemberPointerType(const MemberPointerType *T) { + return Visit(T->getPointeeType()); + } + + TemplateTypeParmDecl *VisitArrayType(const ArrayType *T) { + return Visit(T->getElementType()); + } + + TemplateTypeParmDecl *VisitDependentSizedExtVectorType( + const DependentSizedExtVectorType *T) { + return Visit(T->getElementType()); + } + + TemplateTypeParmDecl *VisitVectorType(const VectorType *T) { + return Visit(T->getElementType()); + } + + TemplateTypeParmDecl *VisitFunctionProtoType(const FunctionProtoType *T) { + return VisitFunctionType(T); + } + + TemplateTypeParmDecl *VisitFunctionType(const FunctionType *T) { + return Visit(T->getReturnType()); + } + + TemplateTypeParmDecl *VisitParenType(const ParenType *T) { + return Visit(T->getInnerType()); + } + + TemplateTypeParmDecl *VisitAttributedType(const AttributedType *T) { + return Visit(T->getModifiedType()); + } + + TemplateTypeParmDecl *VisitMacroQualifiedType(const MacroQualifiedType *T) { + return Visit(T->getUnderlyingType()); + } + + TemplateTypeParmDecl *VisitAdjustedType(const AdjustedType *T) { + return Visit(T->getOriginalType()); + } + + TemplateTypeParmDecl *VisitPackExpansionType(const PackExpansionType *T) { + return Visit(T->getPattern()); + } + }; + +} // namespace + ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, @@ -2192,6 +2281,46 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, return nullptr; } + // In abbreviated templates, TemplateTypeParmDecls with possible + // TypeConstraints are created when the parameter list is originally parsed. + // The TypeConstraints can therefore reference other functions parameters in + // the abbreviated function template, which is why we must instantiate them + // here, when the instantiated versions of those referenced parameters are in + // scope. + if (TemplateTypeParmDecl *TTP = + GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) { + if (const TypeConstraint *TC = TTP->getTypeConstraint()) { + auto *Inst = cast<TemplateTypeParmDecl>( + FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs)); + // We will first get here when instantiating the abbreviated function + // template's described function, but we might also get here later. + // Make sure we do not instantiate the TypeConstraint more than once. + if (Inst && !Inst->hasTypeConstraint()) { + // TODO: Concepts: do not instantiate the constraint (delayed constraint + // substitution) + const ASTTemplateArgumentListInfo *TemplArgInfo + = TC->getTemplateArgsAsWritten(); + TemplateArgumentListInfo InstArgs; + + if (TemplArgInfo) { + InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); + InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); + if (Subst(TemplArgInfo->getTemplateArgs(), + TemplArgInfo->NumTemplateArgs, InstArgs, TemplateArgs)) + return nullptr; + } + if (AttachTypeConstraint( + TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), + TC->getNamedConcept(), &InstArgs, Inst, + TTP->isParameterPack() + ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) + ->getEllipsisLoc() + : SourceLocation())) + return nullptr; + } + } + } + ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(), OldParm->getInnerLocStart(), OldParm->getLocation(), diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 2637b4cb6dc..0e1d5fa77c6 100755 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2525,28 +2525,34 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( Inst->setAccess(AS_public); Inst->setImplicit(D->isImplicit()); if (auto *TC = D->getTypeConstraint()) { - // TODO: Concepts: do not instantiate the constraint (delayed constraint - // substitution) - const ASTTemplateArgumentListInfo *TemplArgInfo - = TC->getTemplateArgsAsWritten(); - TemplateArgumentListInfo InstArgs; - - if (TemplArgInfo) { - InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); - InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstArgs, TemplateArgs)) + if (!D->isImplicit()) { + // Invented template parameter type constraints will be instantiated with + // the corresponding auto-typed parameter as it might reference other + // parameters. + + // TODO: Concepts: do not instantiate the constraint (delayed constraint + // substitution) + const ASTTemplateArgumentListInfo *TemplArgInfo + = TC->getTemplateArgsAsWritten(); + TemplateArgumentListInfo InstArgs; + + if (TemplArgInfo) { + InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); + InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); + if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), + TemplArgInfo->NumTemplateArgs, + InstArgs, TemplateArgs)) + return nullptr; + } + if (SemaRef.AttachTypeConstraint( + TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), + TC->getNamedConcept(), &InstArgs, Inst, + D->isParameterPack() + ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) + ->getEllipsisLoc() + : SourceLocation())) return nullptr; } - if (SemaRef.AttachTypeConstraint( - TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), - TC->getNamedConcept(), &InstArgs, Inst, - D->isParameterPack() - ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) - ->getEllipsisLoc() - : SourceLocation())) - return nullptr; } if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { TypeSourceInfo *InstantiatedDefaultArg = |