Skip to content

Commit 3fad6d1

Browse files
hokeinaniplcc
authored andcommitted
[clang] CTAD: Fix require-clause is not transformed. (llvm#89378)
Fixes llvm#89013 When building the deduction guide, we use the TemplateArgsForBuildingFPrime to transform the require-clause from the underlying class deduction guide. However, we do this at the wrong place where not all elements of TemplateArgsForBuildingFPrime are initialized. The fix involves rearranging the transformRequireClause call to the correct location. As part of the fix, we extend the TemplateInstantiator to support more types in the template-rewrite mode. Otherwise, we will encounter an assertion error when attempting to rewrite the template type parameter type like D with a complex type like Derived<U>.
1 parent f5971ce commit 3fad6d1

File tree

4 files changed

+61
-17
lines changed

4 files changed

+61
-17
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,19 +2962,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
29622962
Context.getCanonicalTemplateArgument(
29632963
Context.getInjectedTemplateArg(NewParam));
29642964
}
2965-
// Substitute new template parameters into requires-clause if present.
2966-
Expr *RequiresClause =
2967-
transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime);
2968-
// FIXME: implement the is_deducible constraint per C++
2969-
// [over.match.class.deduct]p3.3:
2970-
// ... and a constraint that is satisfied if and only if the arguments
2971-
// of A are deducible (see below) from the return type.
2972-
auto *FPrimeTemplateParamList = TemplateParameterList::Create(
2973-
Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
2974-
AliasTemplate->getTemplateParameters()->getLAngleLoc(),
2975-
FPrimeTemplateParams,
2976-
AliasTemplate->getTemplateParameters()->getRAngleLoc(),
2977-
/*RequiresClause=*/RequiresClause);
29782965

29792966
// To form a deduction guide f' from f, we leverage clang's instantiation
29802967
// mechanism, we construct a template argument list where the template
@@ -3020,6 +3007,20 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
30203007
F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(),
30213008
Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
30223009
auto *GG = cast<CXXDeductionGuideDecl>(FPrime);
3010+
// Substitute new template parameters into requires-clause if present.
3011+
Expr *RequiresClause =
3012+
transformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime);
3013+
// FIXME: implement the is_deducible constraint per C++
3014+
// [over.match.class.deduct]p3.3:
3015+
// ... and a constraint that is satisfied if and only if the arguments
3016+
// of A are deducible (see below) from the return type.
3017+
auto *FPrimeTemplateParamList = TemplateParameterList::Create(
3018+
Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
3019+
AliasTemplate->getTemplateParameters()->getLAngleLoc(),
3020+
FPrimeTemplateParams,
3021+
AliasTemplate->getTemplateParameters()->getRAngleLoc(),
3022+
/*RequiresClause=*/RequiresClause);
3023+
30233024
buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList,
30243025
GG->getCorrespondingConstructor(),
30253026
GG->getExplicitSpecifier(), GG->getTypeSourceInfo(),

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,10 +2502,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
25022502
assert(Arg.getKind() == TemplateArgument::Type &&
25032503
"unexpected nontype template argument kind in template rewrite");
25042504
QualType NewT = Arg.getAsType();
2505-
assert(isa<TemplateTypeParmType>(NewT) &&
2506-
"type parm not rewritten to type parm");
2507-
auto NewTL = TLB.push<TemplateTypeParmTypeLoc>(NewT);
2508-
NewTL.setNameLoc(TL.getNameLoc());
2505+
TLB.pushTrivial(SemaRef.Context, NewT, TL.getNameLoc());
25092506
return NewT;
25102507
}
25112508

clang/test/SemaCXX/cxx20-ctad-type-alias.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,21 @@ using String = Array<char, N>;
289289
// Verify no crash on constructing the aggregate deduction guides.
290290
String s("hello");
291291
} // namespace test21
292+
293+
// GH89013
294+
namespace test22 {
295+
class Base {};
296+
template <typename T>
297+
class Derived final : public Base {};
298+
299+
template <typename T, typename D>
300+
requires __is_base_of(Base, D)
301+
struct Foo {
302+
explicit Foo(D) {}
303+
};
304+
305+
template <typename U>
306+
using AFoo = Foo<int, Derived<U>>;
307+
308+
AFoo a(Derived<int>{});
309+
} // namespace test22

clang/test/SemaTemplate/deduction-guide.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,31 @@ AG ag = {1};
260260
// CHECK: |-TemplateArgument type 'int'
261261
// CHECK: | `-BuiltinType {{.*}} 'int'
262262
// CHECK: `-ParmVarDecl {{.*}} 'int'
263+
264+
template <typename D>
265+
requires (sizeof(D) == 4)
266+
struct Foo {
267+
Foo(D);
268+
};
269+
270+
template <typename U>
271+
using AFoo = Foo<G<U>>;
272+
// Verify that the require-clause from the Foo deduction guide is transformed.
273+
// The D occurrence should be rewritten to G<type-parameter-0-0>.
274+
//
275+
// CHECK-LABEL: Dumping <deduction guide for AFoo>
276+
// CHECK: FunctionTemplateDecl {{.*}} implicit <deduction guide for AFoo>
277+
// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 U
278+
// CHECK-NEXT: |-ParenExpr {{.*}} 'bool'
279+
// CHECK-NEXT: | `-BinaryOperator {{.*}} 'bool' '=='
280+
// CHECK-NEXT: | |-UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' sizeof 'G<type-parameter-0-0>'
281+
// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'unsigned long' <IntegralCast>
282+
// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4
283+
// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for AFoo> 'auto (G<type-parameter-0-0>) -> Foo<G<type-parameter-0-0>>'
284+
// CHECK-NEXT: | `-ParmVarDecl {{.*}} 'G<type-parameter-0-0>'
285+
// CHECK-NEXT: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for AFoo> 'auto (G<int>) -> Foo<G<int>>' implicit_instantiation
286+
// CHECK-NEXT: |-TemplateArgument type 'int'
287+
// CHECK-NEXT: | `-BuiltinType {{.*}} 'int'
288+
// CHECK-NEXT: `-ParmVarDecl {{.*}} 'G<int>'
289+
290+
AFoo aa(G<int>{});

0 commit comments

Comments
 (0)