Skip to content

Commit 38d71c9

Browse files
authored
[Clang] Fix the assertion condition after b8d1f3d (llvm#132669)
Thanks to the example provided by MagentaTreehouse, I realized the assertion I added in b8d1f3d didn't cover all valid cases like, when inheriting from a class template specialization, the source of a synthesized template parameter might be an implicit specialization, whose inner function template is thus living at depth 0, for which we don’t want it to overflow too. I've decided to remove that assertion because I don't think it's particularly useful: we're checking whether Depth = 0 parameters come from function templates whose parents contribute no template parameters to the depth, which is redundant given what the template depth already means. This also incorporates a drive-by fix for llvm#132061 (comment), which I somehow missed.
1 parent ec9546d commit 38d71c9

File tree

2 files changed

+65
-20
lines changed

2 files changed

+65
-20
lines changed

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,10 @@ struct ConvertConstructorToDeductionGuideTransform {
376376
if (NestedPattern)
377377
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
378378
auto [Depth, Index] = getDepthAndIndex(Param);
379-
// Depth can still be 0 if FTD belongs to an explicit class template
380-
// specialization with an empty template parameter list. In that case,
381-
// we don't want the NewDepth to overflow, and it should remain 0.
382-
assert(Depth ||
383-
cast<ClassTemplateSpecializationDecl>(FTD->getDeclContext())
384-
->isExplicitSpecialization());
379+
// Depth can be 0 if FTD belongs to a non-template class/a class
380+
// template specialization with an empty template parameter list. In
381+
// that case, we don't want the NewDepth to overflow, and it should
382+
// remain 0.
385383
NamedDecl *NewParam = transformTemplateParameter(
386384
SemaRef, DC, Param, Args, Index + Depth1IndexAdjustment,
387385
Depth ? Depth - 1 : 0);
@@ -970,6 +968,19 @@ getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
970968
return {Template, AliasRhsTemplateArgs};
971969
}
972970

971+
bool IsNonDeducedArgument(const TemplateArgument &TA) {
972+
// The following cases indicate the template argument is non-deducible:
973+
// 1. The result is null. E.g. When it comes from a default template
974+
// argument that doesn't appear in the alias declaration.
975+
// 2. The template parameter is a pack and that cannot be deduced from
976+
// the arguments within the alias declaration.
977+
// Non-deducible template parameters will persist in the transformed
978+
// deduction guide.
979+
return TA.isNull() ||
980+
(TA.getKind() == TemplateArgument::Pack &&
981+
llvm::any_of(TA.pack_elements(), IsNonDeducedArgument));
982+
}
983+
973984
// Build deduction guides for a type alias template from the given underlying
974985
// deduction guide F.
975986
FunctionTemplateDecl *
@@ -1033,20 +1044,6 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
10331044
AliasRhsTemplateArgs, TDeduceInfo, DeduceResults,
10341045
/*NumberOfArgumentsMustMatch=*/false);
10351046

1036-
static std::function<bool(const TemplateArgument &TA)> IsNonDeducedArgument =
1037-
[](const TemplateArgument &TA) {
1038-
// The following cases indicate the template argument is non-deducible:
1039-
// 1. The result is null. E.g. When it comes from a default template
1040-
// argument that doesn't appear in the alias declaration.
1041-
// 2. The template parameter is a pack and that cannot be deduced from
1042-
// the arguments within the alias declaration.
1043-
// Non-deducible template parameters will persist in the transformed
1044-
// deduction guide.
1045-
return TA.isNull() ||
1046-
(TA.getKind() == TemplateArgument::Pack &&
1047-
llvm::any_of(TA.pack_elements(), IsNonDeducedArgument));
1048-
};
1049-
10501047
SmallVector<TemplateArgument> DeducedArgs;
10511048
SmallVector<unsigned> NonDeducedTemplateParamsInFIndex;
10521049
// !!NOTE: DeduceResults respects the sequence of template parameters of

clang/test/SemaTemplate/deduction-guide.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,3 +723,51 @@ void test() { NewDeleteAllocator abc(42); } // expected-error {{no viable constr
723723
// CHECK-NEXT: `-ParmVarDecl {{.+}} 'T'
724724

725725
} // namespace GH128691
726+
727+
namespace GH132616_DeductionGuide {
728+
729+
template <class T> struct A {
730+
template <class U>
731+
A(U);
732+
};
733+
734+
template <typename>
735+
struct B : A<int> {
736+
using A::A;
737+
};
738+
739+
template <class T>
740+
B(T) -> B<T>;
741+
742+
B b(24);
743+
744+
// CHECK-LABEL: Dumping GH132616_DeductionGuide::<deduction guide for B>:
745+
// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for B>
746+
// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} typename depth 0 index 0
747+
// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 1 U
748+
// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for B> 'auto (U) -> B<type-parameter-0-0>'
749+
// CHECK-NEXT: `-ParmVarDecl {{.+}} 'U'
750+
751+
struct C {
752+
template <class U>
753+
C(U);
754+
};
755+
756+
template <typename>
757+
struct D : C {
758+
using C::C;
759+
};
760+
761+
template <class T>
762+
D(T) -> D<T>;
763+
764+
D d(24);
765+
766+
// CHECK-LABEL: Dumping GH132616_DeductionGuide::<deduction guide for D>:
767+
// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for D>
768+
// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} typename depth 0 index 0
769+
// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 1 U
770+
// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for D> 'auto (U) -> D<type-parameter-0-0>'
771+
// CHECK-NEXT: `-ParmVarDecl {{.+}} 'U'
772+
773+
} // namespace GH132616_DeductionGuide

0 commit comments

Comments
 (0)