Skip to content

Commit 88c1779

Browse files
authored
Propagate ParameterModifiers in templates (#4089)
This addresses two issues that blocked template instantiation of functions with ParameterModifiers. The first issue is that template deduction was not propagating ParameterModifiers, but since the modifiers do influence overload resolution, matches were never being found. The second issue is that template instantiation was not propagating ParameterModifiers, so even if dedution managed to succeed, it would produce an instantiaton that wouldn't match. The silly issue that still remains after this is that our ParameterModifiers sholud be attached to the QualType for the parameters. We already bake in the effect of the ParameterModifier to the QualType, so we were getting overload mismatches on identical functions. If we move the ParameterModifiers to the QualTypes similar to other type qualifiers, we can actually get rid of this patch. This resolves #4084
1 parent 552b11b commit 88c1779

5 files changed

Lines changed: 98 additions & 18 deletions

File tree

tools/clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,10 +1254,12 @@ class Sema {
12541254
/// \returns A suitable function type, if there are no errors. The
12551255
/// unqualified type will always be a FunctionProtoType.
12561256
/// Otherwise, returns a NULL type.
1257-
QualType BuildFunctionType(QualType T,
1258-
MutableArrayRef<QualType> ParamTypes,
1257+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
1258+
QualType BuildFunctionType(QualType T, MutableArrayRef<QualType> ParamTypes,
12591259
SourceLocation Loc, DeclarationName Entity,
1260-
const FunctionProtoType::ExtProtoInfo &EPI);
1260+
const FunctionProtoType::ExtProtoInfo &EPI,
1261+
ArrayRef<hlsl::ParameterModifier> ParamMods);
1262+
// HLSL Change - End
12611263

12621264
QualType BuildMemberPointerType(QualType T, QualType Class,
12631265
SourceLocation Loc,

tools/clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,10 +2605,12 @@ Sema::SubstituteExplicitTemplateArguments(
26052605
return TDK_SubstitutionFailure;
26062606

26072607
if (FunctionType) {
2608-
*FunctionType = BuildFunctionType(ResultType, ParamTypes,
2609-
Function->getLocation(),
2610-
Function->getDeclName(),
2611-
Proto->getExtProtoInfo());
2608+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
2609+
*FunctionType = BuildFunctionType(
2610+
ResultType, ParamTypes, Function->getLocation(),
2611+
Function->getDeclName(), Proto->getExtProtoInfo(),
2612+
cast<FunctionProtoType>(Function->getType())->getParamMods());
2613+
// HLSL Change - End
26122614
if (FunctionType->isNull() || Trap.hasErrorOccurred())
26132615
return TDK_SubstitutionFailure;
26142616
}

tools/clang/lib/Sema/SemaType.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,10 +2240,13 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
22402240
return false;
22412241
}
22422242

2243+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
22432244
QualType Sema::BuildFunctionType(QualType T,
22442245
MutableArrayRef<QualType> ParamTypes,
22452246
SourceLocation Loc, DeclarationName Entity,
2246-
const FunctionProtoType::ExtProtoInfo &EPI) {
2247+
const FunctionProtoType::ExtProtoInfo &EPI,
2248+
ArrayRef<hlsl::ParameterModifier> ParamMods) {
2249+
// HLSL Change - End
22472250
bool Invalid = false;
22482251

22492252
Invalid |= CheckFunctionReturnType(T, Loc);
@@ -2267,8 +2270,9 @@ QualType Sema::BuildFunctionType(QualType T,
22672270
if (Invalid)
22682271
return QualType();
22692272

2270-
// HLSL Change - FIX - current contexts specialize templates with always-in parameters
2271-
return Context.getFunctionType(T, ParamTypes, EPI, None);
2273+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
2274+
return Context.getFunctionType(T, ParamTypes, EPI, ParamMods);
2275+
// HLSL Change End
22722276
}
22732277

22742278
/// \brief Build a member pointer type \c T Class::*.

tools/clang/lib/Sema/TreeTransform.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -793,9 +793,12 @@ class TreeTransform {
793793
///
794794
/// By default, performs semantic analysis when building the function type.
795795
/// Subclasses may override this routine to provide different behavior.
796-
QualType RebuildFunctionProtoType(QualType T,
797-
MutableArrayRef<QualType> ParamTypes,
798-
const FunctionProtoType::ExtProtoInfo &EPI);
796+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
797+
QualType
798+
RebuildFunctionProtoType(QualType T, MutableArrayRef<QualType> ParamTypes,
799+
ArrayRef<hlsl::ParameterModifier> ParamMods,
800+
const FunctionProtoType::ExtProtoInfo &EPI);
801+
// HLSL Change - End
799802

800803
/// \brief Build a new unprototyped function type.
801804
QualType RebuildFunctionNoProtoType(QualType ResultType);
@@ -4745,7 +4748,10 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
47454748
T->getNumParams() != ParamTypes.size() ||
47464749
!std::equal(T->param_type_begin(), T->param_type_end(),
47474750
ParamTypes.begin()) || EPIChanged) {
4748-
Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI);
4751+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
4752+
Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,
4753+
T->getParamMods(), EPI);
4754+
// HLSL Change - End
47494755
if (Result.isNull())
47504756
return QualType();
47514757
}
@@ -10631,9 +10637,11 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
1063110637
QualType exprResultType =
1063210638
getDerived().TransformType(exprFunctionType->getReturnType());
1063310639

10634-
QualType functionType =
10635-
getDerived().RebuildFunctionProtoType(exprResultType, paramTypes,
10636-
exprFunctionType->getExtProtoInfo());
10640+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
10641+
QualType functionType = getDerived().RebuildFunctionProtoType(
10642+
exprResultType, paramTypes, exprFunctionType->getParamMods(),
10643+
exprFunctionType->getExtProtoInfo());
10644+
// HLSL Change - End
1063710645
blockScope->FunctionType = functionType;
1063810646

1063910647
// Set the parameters on the block decl.
@@ -10873,16 +10881,19 @@ TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
1087310881
return SemaRef.BuildExtVectorType(ElementType, SizeExpr, AttributeLoc);
1087410882
}
1087510883

10884+
// HLSL Change - FIX - We should move param mods to parameter QualTypes
1087610885
template<typename Derived>
1087710886
QualType TreeTransform<Derived>::RebuildFunctionProtoType(
1087810887
QualType T,
1087910888
MutableArrayRef<QualType> ParamTypes,
10889+
ArrayRef<hlsl::ParameterModifier> ParamMods,
1088010890
const FunctionProtoType::ExtProtoInfo &EPI) {
1088110891
return SemaRef.BuildFunctionType(T, ParamTypes,
1088210892
getDerived().getBaseLocation(),
1088310893
getDerived().getBaseEntity(),
10884-
EPI);
10894+
EPI, ParamMods);
1088510895
}
10896+
// HLSL Change - End
1088610897

1088710898
template<typename Derived>
1088810899
QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %dxc -E main -T cs_6_0 -enable-templates -ast-dump %s | FileCheck %s
2+
template<typename T>
3+
void apply(in T X, inout T Y, out T Z);
4+
5+
template<>
6+
void apply<int>(in int X, inout int Y, out int Z){
7+
Z = (Y += X);
8+
}
9+
10+
template<>
11+
void apply<float3>(in float3 X, inout float3 Y, out float3 Z) {
12+
Y += X;
13+
Z = Y + X;
14+
}
15+
16+
[numthreads(1,1,1)]
17+
void main() {
18+
int X = 1, Y = 2;
19+
int Z;
20+
apply(X, Y, Z);
21+
22+
float3 V = {0.0, 0.0, 0.0};
23+
float3 W = {0.0, 1.0, 1.0};
24+
float3 T;
25+
apply(V, W, T);
26+
}
27+
28+
29+
// CHECK: FunctionTemplateDecl
30+
// CHECK-NEXT: | |-TemplateTypeParmDecl 0x{{[0-9a-fA-F]+}} <line:2:10, col:19> col:19 referenced typename T
31+
// CHECK-NEXT: | |-FunctionDecl 0x{{[0-9a-fA-F]+}} <line:3:1, col:38> col:6 apply 'void (T, T &__restrict, T &__restrict)'
32+
// CHECK-NEXT: | | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:12, col:17> col:17 X 'T'
33+
// CHECK-NEXT: | | | `-HLSLInAttr 0x{{[0-9a-fA-F]+}} <col:12>
34+
// CHECK-NEXT: | | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:20, col:28> col:28 Y 'T &__restrict'
35+
// CHECK-NEXT: | | | `-HLSLInOutAttr 0x{{[0-9a-fA-F]+}} <col:20>
36+
// CHECK-NEXT: | | `-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:31, col:37> col:37 Z 'T &__restrict'
37+
// CHECK-NEXT: | | `-HLSLOutAttr 0x{{[0-9a-fA-F]+}} <col:31>
38+
// CHECK-NEXT: | |-Function 0x{{[0-9a-fA-F]+}} 'apply' 'void (int, int &__restrict, int &__restrict)'
39+
// CHECK-NEXT: | `-Function 0x{{[0-9a-fA-F]+}} 'apply' 'void (float3, float3 &__restrict, float3 &__restrict)'
40+
// CHECK-NEXT: |-FunctionDecl 0x{{[0-9a-fA-F]+}} prev 0x{{[0-9a-fA-F]+}} <line:5:1, line:8:1> line:6:6 used apply 'void (int, int &__restrict, int &__restrict)'
41+
// CHECK-NEXT: | |-TemplateArgument type 'int'
42+
// CHECK-NEXT: | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:17, col:24> col:24 used X 'int'
43+
// CHECK-NEXT: | | `-HLSLInAttr 0x{{[0-9a-fA-F]+}} <col:17>
44+
// CHECK-NEXT: | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:27, col:37> col:37 used Y 'int &__restrict'
45+
// CHECK-NEXT: | | `-HLSLInOutAttr 0x{{[0-9a-fA-F]+}} <col:27>
46+
// CHECK-NEXT: | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:40, col:48> col:48 used Z 'int &__restrict'
47+
// CHECK-NEXT: | | `-HLSLOutAttr 0x{{[0-9a-fA-F]+}} <col:40>
48+
49+
// CHECK: |-FunctionDecl 0x{{[0-9a-fA-F]+}} prev 0x{{[0-9a-fA-F]+}} <line:10:1, line:14:1> line:11:6 used apply 'void (float3, float3 &__restrict, float3 &__restrict)'
50+
// CHECK-NEXT: | |-TemplateArgument type 'vector<float, 3>'
51+
// CHECK-NEXT: | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:20, col:30> col:30 used X 'float3':'vector<float, 3>'
52+
// CHECK-NEXT: | | `-HLSLInAttr 0x{{[0-9a-fA-F]+}} <col:20>
53+
// CHECK-NEXT: | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:33, col:46> col:46 used Y 'float3 &__restrict'
54+
// CHECK-NEXT: | | `-HLSLInOutAttr 0x{{[0-9a-fA-F]+}} <col:33>
55+
// CHECK-NEXT: | |-ParmVarDecl 0x{{[0-9a-fA-F]+}} <col:49, col:60> col:60 used Z 'float3 &__restrict'
56+
// CHECK-NEXT: | | `-HLSLOutAttr 0x{{[0-9a-fA-F]+}} <col:49>
57+
58+
// CHECK: | |-CallExpr 0x{{[0-9a-fA-F]+}} <line:20:3, col:16> 'void'
59+
// CHECK-NEXT: | | |-ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:3> 'void (*)(int, int &__restrict, int &__restrict)' <FunctionToPointerDecay>
60+
// CHECK: | `-CallExpr 0x{{[0-9a-fA-F]+}} <line:25:3, col:16> 'void'
61+
// CHECK-NEXT: | |-ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:3> 'void (*)(float3, float3 &__restrict, float3 &__restrict)' <FunctionToPointerDecay>

0 commit comments

Comments
 (0)