Skip to content

Commit 699f228

Browse files
bob80905tmsri
authored andcommitted
[HLSL] Add testing for space parameter on global constants (llvm#106782)
The space parameter in the register binding annotation may not be used for global constants. There was previously no diagnostic emitted when this case occurred. This PR adds a diagnostic when this case occurs, and tests these cases. A new file was made to specifically test the space parameter, so some cases in `\clang\test\SemaHLSL\resource_binding_attr_error.hlsl` were moved over to this new file. Fixes llvm#104521
1 parent d389939 commit 699f228

File tree

5 files changed

+102
-41
lines changed

5 files changed

+102
-41
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12381,6 +12381,7 @@ def warn_hlsl_deprecated_register_type_b: Warning<"binding type 'b' only applies
1238112381
def warn_hlsl_deprecated_register_type_i: Warning<"binding type 'i' ignored. The 'integer constant' binding type is no longer supported">, InGroup<LegacyConstantRegisterBinding>, DefaultError;
1238212382
def err_hlsl_unsupported_register_number : Error<"register number should be an integer">;
1238312383
def err_hlsl_expected_space : Error<"invalid space specifier '%0' used; expected 'space' followed by an integer, like space1">;
12384+
def err_hlsl_space_on_global_constant : Error<"register space cannot be specified on global constants">;
1238412385
def warn_hlsl_packoffset_mix : Warning<"cannot mix packoffset elements with nonpackoffset elements in a cbuffer">,
1238512386
InGroup<HLSLMixPackOffset>;
1238612387
def err_hlsl_packoffset_overlap : Error<"packoffset overlap between %0, %1">;

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,8 @@ static void ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl,
969969
}
970970

971971
static void DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc,
972-
Decl *TheDecl, RegisterType regType) {
972+
Decl *TheDecl, RegisterType RegType,
973+
const bool SpecifiedSpace) {
973974

974975
// exactly one of these two types should be set
975976
assert(((isa<VarDecl>(TheDecl) && !isa<HLSLBufferDecl>(TheDecl)) ||
@@ -982,42 +983,46 @@ static void DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc,
982983
1 &&
983984
"only one resource analysis result should be expected");
984985

985-
int regTypeNum = static_cast<int>(regType);
986+
int RegTypeNum = static_cast<int>(RegType);
986987

987988
// first, if "other" is set, emit an error
988989
if (Flags.Other) {
989-
S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << regTypeNum;
990+
S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
990991
return;
991992
}
992993

993994
// next, if multiple register annotations exist, check that none conflict.
994-
ValidateMultipleRegisterAnnotations(S, TheDecl, regType);
995+
ValidateMultipleRegisterAnnotations(S, TheDecl, RegType);
995996

996997
// next, if resource is set, make sure the register type in the register
997998
// annotation is compatible with the variable's resource type.
998999
if (Flags.Resource) {
999-
RegisterType expRegType = getRegisterType(Flags.ResourceClass.value());
1000-
if (regType != expRegType) {
1000+
RegisterType ExpRegType = getRegisterType(Flags.ResourceClass.value());
1001+
if (RegType != ExpRegType) {
10011002
S.Diag(TheDecl->getLocation(), diag::err_hlsl_binding_type_mismatch)
1002-
<< regTypeNum;
1003+
<< RegTypeNum;
10031004
}
1005+
10041006
return;
10051007
}
10061008

10071009
// next, handle diagnostics for when the "basic" flag is set
10081010
if (Flags.Basic) {
1011+
if (SpecifiedSpace && !isDeclaredWithinCOrTBuffer(TheDecl))
1012+
S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);
1013+
10091014
if (Flags.DefaultGlobals) {
1010-
if (regType == RegisterType::CBuffer)
1015+
if (RegType == RegisterType::CBuffer)
10111016
S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);
1012-
else if (regType != RegisterType::C)
1013-
S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << regTypeNum;
1017+
else if (RegType != RegisterType::C)
1018+
S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
10141019
return;
10151020
}
10161021

1017-
if (regType == RegisterType::C)
1022+
if (RegType == RegisterType::C)
10181023
S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);
10191024
else
1020-
S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << regTypeNum;
1025+
S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;
10211026

10221027
return;
10231028
}
@@ -1026,15 +1031,13 @@ static void DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc,
10261031
if (Flags.UDT) {
10271032
const bool ExpectedRegisterTypesForUDT[] = {
10281033
Flags.SRV, Flags.UAV, Flags.CBV, Flags.Sampler, Flags.ContainsNumeric};
1029-
assert((size_t)regTypeNum < std::size(ExpectedRegisterTypesForUDT) &&
1034+
assert((size_t)RegTypeNum < std::size(ExpectedRegisterTypesForUDT) &&
10301035
"regType has unexpected value");
10311036

1032-
if (!ExpectedRegisterTypesForUDT[regTypeNum])
1037+
if (!ExpectedRegisterTypesForUDT[RegTypeNum])
10331038
S.Diag(TheDecl->getLocation(),
10341039
diag::warn_hlsl_user_defined_type_missing_member)
1035-
<< regTypeNum;
1036-
1037-
return;
1040+
<< RegTypeNum;
10381041
}
10391042
}
10401043

@@ -1059,7 +1062,9 @@ void SemaHLSL::handleResourceBindingAttr(Decl *TheDecl, const ParsedAttr &AL) {
10591062
SourceLocation ArgLoc = Loc->Loc;
10601063

10611064
SourceLocation SpaceArgLoc;
1065+
bool SpecifiedSpace = false;
10621066
if (AL.getNumArgs() == 2) {
1067+
SpecifiedSpace = true;
10631068
Slot = Str;
10641069
if (!AL.isArgIdent(1)) {
10651070
Diag(AL.getLoc(), diag::err_attribute_argument_type)
@@ -1107,7 +1112,8 @@ void SemaHLSL::handleResourceBindingAttr(Decl *TheDecl, const ParsedAttr &AL) {
11071112
return;
11081113
}
11091114

1110-
DiagnoseHLSLRegisterAttribute(SemaRef, ArgLoc, TheDecl, regType);
1115+
DiagnoseHLSLRegisterAttribute(SemaRef, ArgLoc, TheDecl, regType,
1116+
SpecifiedSpace);
11111117

11121118
HLSLResourceBindingAttr *NewAttr =
11131119
HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);

clang/test/SemaHLSL/resource_binding_attr_error.hlsl

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,9 @@ float a : register(c0);
1313
cbuffer b : register(i0) {
1414

1515
}
16-
// expected-error@+1 {{invalid space specifier 's2' used; expected 'space' followed by an integer, like space1}}
17-
cbuffer c : register(b0, s2) {
1816

19-
}
2017
// expected-error@+1 {{register number should be an integer}}
21-
cbuffer d : register(bf, s2) {
22-
23-
}
24-
// expected-error@+1 {{invalid space specifier 'spaces' used; expected 'space' followed by an integer, like space1}}
25-
cbuffer e : register(b2, spaces) {
18+
cbuffer c : register(bf, s2) {
2619

2720
}
2821

@@ -35,9 +28,8 @@ cbuffer B : register(space1) {}
3528
// expected-error@+1 {{wrong argument format for hlsl attribute, use b2 instead}}
3629
cbuffer C : register(b 2) {}
3730

38-
// expected-error@+2 {{wrong argument format for hlsl attribute, use b2 instead}}
39-
// expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}}
40-
cbuffer D : register(b 2, space 3) {}
31+
// expected-error@+1 {{wrong argument format for hlsl attribute, use b2 instead}}
32+
cbuffer D : register(b 2, space3) {}
4133

4234
// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
4335
static MyTemplatedSRV<float> U : register(u5);
@@ -61,9 +53,6 @@ void foo2() {
6153
extern MyTemplatedSRV<float> U2 : register(u5);
6254
}
6355

64-
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
65-
float b : register(u0, space1);
66-
6756
// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
6857
void bar(MyTemplatedSRV<float> U : register(u3)) {
6958

clang/test/SemaHLSL/resource_binding_attr_error_basic.hlsl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,40 @@
33
// expected-error@+1{{binding type 't' only applies to SRV resources}}
44
float f1 : register(t0);
55

6-
7-
float f2 : register(c0);
6+
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
7+
float f2 : register(u0);
88

99
// expected-error@+1{{binding type 'b' only applies to constant buffers. The 'bool constant' binding type is no longer supported}}
1010
float f3 : register(b9);
1111

12+
// expected-error@+1 {{binding type 's' only applies to sampler state}}
13+
float f4 : register(s0);
14+
1215
// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
13-
float f4 : register(i9);
16+
float f5 : register(i9);
1417

1518
// expected-error@+1{{binding type 'x' is invalid}}
16-
float f5 : register(x9);
19+
float f6 : register(x9);
1720

1821
cbuffer g_cbuffer1 {
1922
// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}}
20-
float f6 : register(c2);
23+
float f7 : register(c2);
2124
};
2225

2326
tbuffer g_tbuffer1 {
2427
// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}}
25-
float f7 : register(c2);
28+
float f8 : register(c2);
2629
};
2730

2831
cbuffer g_cbuffer2 {
2932
// expected-error@+1{{binding type 'b' only applies to constant buffer resources}}
30-
float f8 : register(b2);
33+
float f9 : register(b2);
3134
};
3235

3336
tbuffer g_tbuffer2 {
3437
// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
35-
float f9 : register(i2);
38+
float f10 : register(i2);
3639
};
3740

3841
// expected-error@+1{{binding type 'c' only applies to numeric variables in the global scope}}
39-
RWBuffer<float> f10 : register(c3);
42+
RWBuffer<float> f11 : register(c3);
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
2+
3+
// valid
4+
cbuffer cbuf {
5+
RWBuffer<int> r : register(u0, space0);
6+
}
7+
8+
cbuffer cbuf2 {
9+
struct x {
10+
// this test validates that no diagnostic is emitted on the space parameter, because
11+
// this register annotation is not in the global scope.
12+
// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
13+
RWBuffer<int> E : register(u2, space3);
14+
};
15+
}
16+
17+
struct MyStruct {
18+
RWBuffer<int> E;
19+
};
20+
21+
cbuffer cbuf3 {
22+
// valid
23+
MyStruct E : register(u2, space3);
24+
}
25+
26+
// valid
27+
MyStruct F : register(u3, space4);
28+
29+
cbuffer cbuf4 {
30+
// this test validates that no diagnostic is emitted on the space parameter, because
31+
// this register annotation is not in the global scope.
32+
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
33+
float a : register(u2, space3);
34+
}
35+
36+
// expected-error@+1 {{invalid space specifier 's2' used; expected 'space' followed by an integer, like space1}}
37+
cbuffer a : register(b0, s2) {
38+
39+
}
40+
41+
// expected-error@+1 {{invalid space specifier 'spaces' used; expected 'space' followed by an integer, like space1}}
42+
cbuffer b : register(b2, spaces) {
43+
44+
}
45+
46+
// expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}}
47+
cbuffer c : register(b2, space 3) {}
48+
49+
// expected-error@+1 {{register space cannot be specified on global constants}}
50+
int d : register(c2, space3);
51+
52+
// expected-error@+1 {{register space cannot be specified on global constants}}
53+
int e : register(c2, space0);
54+
55+
// expected-error@+1 {{register space cannot be specified on global constants}}
56+
int f : register(c2, space00);
57+
58+
// valid
59+
RWBuffer<int> g : register(u2, space0);
60+
61+
// valid
62+
RWBuffer<int> h : register(u2, space0);

0 commit comments

Comments
 (0)