diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-02-21 06:30:38 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-02-21 06:30:38 +0000 |
| commit | b4f9625a7bd5601534952b478040e6836e37eb47 (patch) | |
| tree | 4cfa08c4839e2e7be37102ccd5797a78beb1f18e /clang/lib/Sema | |
| parent | 16d9730b8673741e4b2b18caa087f71c2318be98 (diff) | |
| download | bcm5719-llvm-b4f9625a7bd5601534952b478040e6836e37eb47.tar.gz bcm5719-llvm-b4f9625a7bd5601534952b478040e6836e37eb47.zip | |
PR32010: Fix template argument depth mixup when forming implicit constructor
template deduction guides for class template argument deduction.
Ensure that we have a local instantiation scope for tracking the instantiated
parameters. Additionally, unusually, we're substituting at depth 1 and leaving
depth 0 alone; make sure that we don't reduce template parameter depth by 2 for
inner parameters in the process. (This is probably also broken for alias
templates in the case where they're expanded within a dependent context, but
this patch doesn't fix that.)
llvm-svn: 295696
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 46 |
3 files changed, 44 insertions, 36 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4b4a47d63c8..ad7b9e54f90 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1442,6 +1442,8 @@ struct ConvertConstructorToDeductionGuideTransform { CXXConstructorDecl *CD) { SmallVector<TemplateArgument, 16> SubstArgs; + LocalInstantiationScope Scope(SemaRef); + // C++ [over.match.class.deduct]p1: // -- For each constructor of the class template designated by the // template-name, a function template with the following properties: @@ -1463,7 +1465,7 @@ struct ConvertConstructorToDeductionGuideTransform { for (NamedDecl *Param : *InnerParams) { MultiLevelTemplateArgumentList Args; Args.addOuterTemplateArguments(SubstArgs); - Args.addOuterTemplateArguments(None); + Args.addOuterRetainedLevel(); NamedDecl *NewParam = transformTemplateParameter(Param, Args); if (!NewParam) return nullptr; @@ -1483,7 +1485,7 @@ struct ConvertConstructorToDeductionGuideTransform { MultiLevelTemplateArgumentList Args; if (FTD) { Args.addOuterTemplateArguments(SubstArgs); - Args.addOuterTemplateArguments(None); + Args.addOuterRetainedLevel(); } FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc() @@ -1555,6 +1557,8 @@ private: if (InstantiatedDefaultArg) NewTTP->setDefaultArgument(InstantiatedDefaultArg); } + SemaRef.CurrentInstantiationScope->InstantiatedLocal(TemplateParam, + NewTTP); return NewTTP; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 723a6c0e4de..f7535e6d242 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1121,6 +1121,23 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, return E; TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition()); + + if (TemplateArgs.getNumLevels() != TemplateArgs.getNumSubstitutedLevels()) { + // We're performing a partial substitution, so the substituted argument + // could be dependent. As a result we can't create a SubstNonType*Expr + // node now, since that represents a fully-substituted argument. + // FIXME: We should have some AST representation for this. + if (Arg.getKind() == TemplateArgument::Pack) { + // FIXME: This won't work for alias templates. + assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() && + "unexpected pack arguments in partial substitution"); + Arg = Arg.pack_begin()->getPackExpansionPattern(); + } + assert(Arg.getKind() == TemplateArgument::Expression && + "unexpected nontype template argument kind in partial substitution"); + return Arg.getAsExpr(); + } + if (NTTP->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); @@ -1429,12 +1446,9 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( TransformDecl(TL.getNameLoc(), OldTTPDecl)); - QualType Result - = getSema().Context.getTemplateTypeParmType(T->getDepth() - - TemplateArgs.getNumLevels(), - T->getIndex(), - T->isParameterPack(), - NewTTPDecl); + QualType Result = getSema().Context.getTemplateTypeParmType( + T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(), + T->isParameterPack(), NewTTPDecl); TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 63c10c0c712..b285d4f3814 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2074,13 +2074,10 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( // TODO: don't always clone when decls are refcounted. assert(D->getTypeForDecl()->isTemplateTypeParmType()); - TemplateTypeParmDecl *Inst = - TemplateTypeParmDecl::Create(SemaRef.Context, Owner, - D->getLocStart(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumLevels(), - D->getIndex(), D->getIdentifier(), - D->wasDeclaredWithTypename(), - D->isParameterPack()); + TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create( + SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), + D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(), + D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); Inst->setAccess(AS_public); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { @@ -2218,17 +2215,14 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( if (IsExpandedParameterPack) Param = NonTypeTemplateParmDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumLevels(), D->getPosition(), - D->getIdentifier(), T, DI, ExpandedParameterPackTypes, + D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), + D->getPosition(), D->getIdentifier(), T, DI, ExpandedParameterPackTypes, ExpandedParameterPackTypesAsWritten); else - Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, - D->getInnerLocStart(), - D->getLocation(), - D->getDepth() - TemplateArgs.getNumLevels(), - D->getPosition(), - D->getIdentifier(), T, - D->isParameterPack(), DI); + Param = NonTypeTemplateParmDecl::Create( + SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), + D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), + D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); Param->setAccess(AS_public); if (Invalid) @@ -2349,19 +2343,15 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( // Build the template template parameter. TemplateTemplateParmDecl *Param; if (IsExpandedParameterPack) - Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, - D->getLocation(), - D->getDepth() - TemplateArgs.getNumLevels(), - D->getPosition(), - D->getIdentifier(), InstParams, - ExpandedParams); + Param = TemplateTemplateParmDecl::Create( + SemaRef.Context, Owner, D->getLocation(), + D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), + D->getPosition(), D->getIdentifier(), InstParams, ExpandedParams); else - Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, - D->getLocation(), - D->getDepth() - TemplateArgs.getNumLevels(), - D->getPosition(), - D->isParameterPack(), - D->getIdentifier(), InstParams); + Param = TemplateTemplateParmDecl::Create( + SemaRef.Context, Owner, D->getLocation(), + D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), + D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { NestedNameSpecifierLoc QualifierLoc = D->getDefaultArgument().getTemplateQualifierLoc(); |

