[clang] [HLSL][RootSignature] Audit `RootSignatureParser` diagnostic production (PR #147800)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 11 18:45:39 PDT 2025
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147800
>From a510b930402cd4a6a00f253093d1a3ddfab918ac Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 15:50:55 +0000
Subject: [PATCH 01/11] remove confusing hlsl_unexpected_end_of_params
diagnostic
- It has been noted more than once that this diagnostic is confusing and
misleading. It can be more concise
---
.../clang/Basic/DiagnosticParseKinds.td | 2 --
clang/lib/Parse/ParseHLSLRootSignature.cpp | 29 +++++--------------
clang/test/SemaHLSL/RootSignature-err.hlsl | 8 ++---
.../Parse/ParseHLSLRootSignatureTest.cpp | 16 +++++-----
4 files changed, 19 insertions(+), 36 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 178f14d9fdd84..890c53e580f56 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1863,8 +1863,6 @@ def err_hlsl_virtual_inheritance
: Error<"virtual inheritance is unsupported in HLSL">;
// HLSL Root Signature Parser Diagnostics
-def err_hlsl_unexpected_end_of_params
- : Error<"expected %0 to denote end of parameters, or, another valid parameter of %1">;
def err_hlsl_rootsig_repeat_param : Error<"specified the same parameter '%0' multiple times">;
def err_hlsl_rootsig_missing_param : Error<"did not specify mandatory parameter '%0'">;
def err_hlsl_number_literal_overflow : Error<
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 4f4bbb5ced13b..47b82a0dfa86b 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -66,9 +66,7 @@ bool RootSignatureParser::parse() {
break;
}
- return consumeExpectedToken(TokenKind::end_of_stream,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/TokenKind::kw_RootSignature);
+ return consumeExpectedToken(TokenKind::end_of_stream);
}
template <typename FlagType>
@@ -119,9 +117,7 @@ std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
} while (tryConsumeExpectedToken(TokenKind::pu_or));
}
- if (consumeExpectedToken(TokenKind::pu_r_paren,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/TokenKind::kw_RootFlags))
+ if (consumeExpectedToken(TokenKind::pu_r_paren))
return std::nullopt;
return Flags;
@@ -141,9 +137,7 @@ std::optional<RootConstants> RootSignatureParser::parseRootConstants() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/TokenKind::kw_RootConstants))
+ if (consumeExpectedToken(TokenKind::pu_r_paren))
return std::nullopt;
// Check mandatory parameters where provided
@@ -208,9 +202,7 @@ std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/DescriptorKind))
+ if (consumeExpectedToken(TokenKind::pu_r_paren))
return std::nullopt;
// Check mandatory parameters were provided
@@ -276,9 +268,7 @@ std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
break;
}
- if (consumeExpectedToken(TokenKind::pu_r_paren,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/TokenKind::kw_DescriptorTable))
+ if (consumeExpectedToken(TokenKind::pu_r_paren))
return std::nullopt;
// Fill in optional visibility
@@ -330,9 +320,7 @@ RootSignatureParser::parseDescriptorTableClause() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/ParamKind))
+ if (consumeExpectedToken(TokenKind::pu_r_paren))
return std::nullopt;
// Check mandatory parameters were provided
@@ -373,9 +361,7 @@ std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren,
- diag::err_hlsl_unexpected_end_of_params,
- /*param of=*/TokenKind::kw_StaticSampler))
+ if (consumeExpectedToken(TokenKind::pu_r_paren))
return std::nullopt;
// Check mandatory parameters were provided
@@ -1282,7 +1268,6 @@ bool RootSignatureParser::consumeExpectedToken(TokenKind Expected,
case diag::err_expected:
DB << Expected;
break;
- case diag::err_hlsl_unexpected_end_of_params:
case diag::err_expected_either:
case diag::err_expected_after:
DB << Expected << Context;
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index 04013974d28b9..563659040091e 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -17,10 +17,10 @@ void bad_root_signature_2() {}
[RootSignature(""), RootSignature("")] // expected-warning {{attribute 'RootSignature' is already applied}}
void bad_root_signature_3() {}
-[RootSignature("DescriptorTable(), invalid")] // expected-error {{expected end of stream to denote end of parameters, or, another valid parameter of RootSignature}}
+[RootSignature("DescriptorTable(), invalid")] // expected-error {{expected end of stream}}
void bad_root_signature_4() {}
-// expected-error at +1 {{expected ')' to denote end of parameters, or, another valid parameter of RootConstants}}
+// expected-error at +1 {{expected ')'}}
[RootSignature("RootConstants(b0, num32BitConstants = 1, invalid)")]
void bad_root_signature_5() {}
@@ -31,10 +31,10 @@ void bad_root_signature_5() {}
// CHECK: [[@LINE-2]]:42: note: expanded from macro 'MultiLineRootSignature'
// CHECK-NEXT: [[@LINE-3]] | "RootConstants(num32BitConstants = 3, b0, invalid)"
// CHECK-NEXT: | ^
-// expected-error at +1 {{expected ')' to denote end of parameters, or, another valid parameter of RootConstants}}
+// expected-error at +1 {{expected ')'}}
[RootSignature(MultiLineRootSignature)]
void bad_root_signature_6() {}
-// expected-error at +1 {{expected end of stream to denote end of parameters, or, another valid parameter of RootSignature}}
+// expected-error at +1 {{expected end of stream}}
[RootSignature("RootFlags() RootConstants(b0, num32BitConstants = 1)")]
void bad_root_signature_7() {}
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 5b1ab149f4497..baa772bab99ed 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -843,7 +843,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedTokenTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -865,7 +865,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseInvalidTokenTest) {
Signature, *PP);
// Test correct diagnostic produced - invalid token
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1258,7 +1258,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootElementMissingCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1285,7 +1285,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableMissingCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1312,7 +1312,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootConstantParamsCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1339,7 +1339,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamsCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1368,7 +1368,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorClauseParamsCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1395,7 +1395,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_hlsl_unexpected_end_of_params);
+ Consumer->setExpected(diag::err_expected);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
>From d055d51980bfca49e0b27fe694e0c1bec129c618 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 16:07:51 +0000
Subject: [PATCH 02/11] add invalid_param diagnostic to differentiate between
missing comma vs invalid token
---
.../clang/Basic/DiagnosticParseKinds.td | 1 +
.../clang/Parse/ParseHLSLRootSignature.h | 6 ++-
clang/lib/Parse/ParseHLSLRootSignature.cpp | 38 +++++++++++++++++--
clang/test/SemaHLSL/RootSignature-err.hlsl | 27 ++++++++++---
.../Parse/ParseHLSLRootSignatureTest.cpp | 4 +-
5 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 890c53e580f56..57cc935ff5f7a 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1863,6 +1863,7 @@ def err_hlsl_virtual_inheritance
: Error<"virtual inheritance is unsupported in HLSL">;
// HLSL Root Signature Parser Diagnostics
+def err_hlsl_invalid_param : Error<"invalid parameter of %0">;
def err_hlsl_rootsig_repeat_param : Error<"specified the same parameter '%0' multiple times">;
def err_hlsl_rootsig_missing_param : Error<"did not specify mandatory parameter '%0'">;
def err_hlsl_number_literal_overflow : Error<
diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index 500e79a7ba574..0c12421723feb 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -100,7 +100,8 @@ class RootSignatureParser {
std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
};
std::optional<ParsedRootDescriptorParams>
- parseRootDescriptorParams(RootSignatureToken::Kind RegType);
+ parseRootDescriptorParams(RootSignatureToken::Kind DescKind,
+ RootSignatureToken::Kind RegType);
struct ParsedClauseParams {
std::optional<llvm::hlsl::rootsig::Register> Reg;
@@ -110,7 +111,8 @@ class RootSignatureParser {
std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
};
std::optional<ParsedClauseParams>
- parseDescriptorTableClauseParams(RootSignatureToken::Kind RegType);
+ parseDescriptorTableClauseParams(RootSignatureToken::Kind ClauseKind,
+ RootSignatureToken::Kind RegType);
struct ParsedStaticSamplerParams {
std::optional<llvm::hlsl::rootsig::Register> Reg;
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 47b82a0dfa86b..1b0cf53920f00 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -59,6 +59,11 @@ bool RootSignatureParser::parse() {
if (!Sampler.has_value())
return true;
Elements.emplace_back(ElementLoc, *Sampler);
+ } else {
+ consumeNextToken(); // let diagnostic be at the start of invalid token
+ reportDiag(diag::err_hlsl_invalid_param)
+ << /*param of*/ TokenKind::kw_RootSignature;
+ return true;
}
// ',' denotes another element, otherwise, expected to be at end of stream
@@ -198,7 +203,7 @@ std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
}
Descriptor.setDefaultFlags(Version);
- auto Params = parseRootDescriptorParams(ExpectedReg);
+ auto Params = parseRootDescriptorParams(DescriptorKind, ExpectedReg);
if (!Params.has_value())
return std::nullopt;
@@ -261,6 +266,11 @@ std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
Visibility = parseShaderVisibility();
if (!Visibility.has_value())
return std::nullopt;
+ } else {
+ consumeNextToken(); // let diagnostic be at the start of invalid token
+ reportDiag(diag::err_hlsl_invalid_param)
+ << /*param of*/ TokenKind::kw_DescriptorTable;
+ return std::nullopt;
}
// ',' denotes another element, otherwise, expected to be at ')'
@@ -316,7 +326,7 @@ RootSignatureParser::parseDescriptorTableClause() {
}
Clause.setDefaultFlags(Version);
- auto Params = parseDescriptorTableClauseParams(ExpectedReg);
+ auto Params = parseDescriptorTableClauseParams(ParamKind, ExpectedReg);
if (!Params.has_value())
return std::nullopt;
@@ -474,6 +484,11 @@ RootSignatureParser::parseRootConstantParams() {
if (!Visibility.has_value())
return std::nullopt;
Params.Visibility = Visibility;
+ } else {
+ consumeNextToken(); // let diagnostic be at the start of invalid token
+ reportDiag(diag::err_hlsl_invalid_param)
+ << /*param of*/ TokenKind::kw_RootConstants;
+ return std::nullopt;
}
// ',' denotes another element, otherwise, expected to be at ')'
@@ -485,7 +500,8 @@ RootSignatureParser::parseRootConstantParams() {
}
std::optional<RootSignatureParser::ParsedRootDescriptorParams>
-RootSignatureParser::parseRootDescriptorParams(TokenKind RegType) {
+RootSignatureParser::parseRootDescriptorParams(TokenKind DescKind,
+ TokenKind RegType) {
assert(CurToken.TokKind == TokenKind::pu_l_paren &&
"Expects to only be invoked starting at given token");
@@ -543,6 +559,10 @@ RootSignatureParser::parseRootDescriptorParams(TokenKind RegType) {
if (!Flags.has_value())
return std::nullopt;
Params.Flags = Flags;
+ } else {
+ consumeNextToken(); // let diagnostic be at the start of invalid token
+ reportDiag(diag::err_hlsl_invalid_param) << /*param of*/ DescKind;
+ return std::nullopt;
}
// ',' denotes another element, otherwise, expected to be at ')'
@@ -554,7 +574,8 @@ RootSignatureParser::parseRootDescriptorParams(TokenKind RegType) {
}
std::optional<RootSignatureParser::ParsedClauseParams>
-RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) {
+RootSignatureParser::parseDescriptorTableClauseParams(TokenKind ClauseKind,
+ TokenKind RegType) {
assert(CurToken.TokKind == TokenKind::pu_l_paren &&
"Expects to only be invoked starting at given token");
@@ -638,6 +659,10 @@ RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) {
if (!Flags.has_value())
return std::nullopt;
Params.Flags = Flags;
+ } else {
+ consumeNextToken(); // let diagnostic be at the start of invalid token
+ reportDiag(diag::err_hlsl_invalid_param) << /*param of*/ ClauseKind;
+ return std::nullopt;
}
// ',' denotes another element, otherwise, expected to be at ')'
@@ -833,6 +858,11 @@ RootSignatureParser::parseStaticSamplerParams() {
if (!Visibility.has_value())
return std::nullopt;
Params.Visibility = Visibility;
+ } else {
+ consumeNextToken(); // let diagnostic be at the start of invalid token
+ reportDiag(diag::err_hlsl_invalid_param)
+ << /*param of*/ TokenKind::kw_StaticSampler;
+ return std::nullopt;
}
// ',' denotes another element, otherwise, expected to be at ')'
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index 563659040091e..b95c58bc5d79b 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -17,10 +17,11 @@ void bad_root_signature_2() {}
[RootSignature(""), RootSignature("")] // expected-warning {{attribute 'RootSignature' is already applied}}
void bad_root_signature_3() {}
-[RootSignature("DescriptorTable(), invalid")] // expected-error {{expected end of stream}}
+// expected-error at +1 {{invalid parameter of RootSignature}}
+[RootSignature("DescriptorTable(), invalid")]
void bad_root_signature_4() {}
-// expected-error at +1 {{expected ')'}}
+// expected-error at +1 {{invalid parameter of RootConstants}}
[RootSignature("RootConstants(b0, num32BitConstants = 1, invalid)")]
void bad_root_signature_5() {}
@@ -28,13 +29,29 @@ void bad_root_signature_5() {}
"CBV(b0)," \
"RootConstants(num32BitConstants = 3, b0, invalid)"
-// CHECK: [[@LINE-2]]:42: note: expanded from macro 'MultiLineRootSignature'
+// CHECK: [[@LINE-2]]:44: note: expanded from macro 'MultiLineRootSignature'
// CHECK-NEXT: [[@LINE-3]] | "RootConstants(num32BitConstants = 3, b0, invalid)"
-// CHECK-NEXT: | ^
-// expected-error at +1 {{expected ')'}}
+// CHECK-NEXT: | ^
+// expected-error at +1 {{invalid parameter of RootConstants}}
[RootSignature(MultiLineRootSignature)]
void bad_root_signature_6() {}
// expected-error at +1 {{expected end of stream}}
[RootSignature("RootFlags() RootConstants(b0, num32BitConstants = 1)")]
void bad_root_signature_7() {}
+
+// expected-error at +1 {{invalid parameter of RootConstants}}
+[RootSignature("RootConstants(b0, num32BitConstantsTypo = 1))")]
+void bad_root_signature_8() {}
+
+// expected-error at +1 {{invalid parameter of UAV}}
+[RootSignature("UAV(b3")]
+void bad_root_signature_9() {}
+
+// expected-error at +1 {{invalid parameter of SRV}}
+[RootSignature("DescriptorTable(SRV(s1, invalid))")]
+void bad_root_signature_10() {}
+
+// expected-error at +1 {{invalid parameter of DescriptorTable}}
+[RootSignature("DescriptorTable(invalid))")]
+void bad_root_signature_11() {}
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index baa772bab99ed..76121a5844242 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -865,7 +865,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseInvalidTokenTest) {
Signature, *PP);
// Test correct diagnostic produced - invalid token
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_hlsl_invalid_param);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -886,7 +886,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedEndOfStreamTest) {
hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
Signature, *PP);
- // Test correct diagnostic produced - end of stream
+ // Test correct diagnostic produced - expected '(' after DescriptorTable
Consumer->setExpected(diag::err_expected_after);
ASSERT_TRUE(Parser.parse());
>From 54076b1f00d56a5428d925b1cd1a924b25c6ba82 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 16:19:28 +0000
Subject: [PATCH 03/11] keep test of missing comma
---
clang/test/SemaHLSL/RootSignature-err.hlsl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index b95c58bc5d79b..ec24c20178e52 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -21,8 +21,8 @@ void bad_root_signature_3() {}
[RootSignature("DescriptorTable(), invalid")]
void bad_root_signature_4() {}
-// expected-error at +1 {{invalid parameter of RootConstants}}
-[RootSignature("RootConstants(b0, num32BitConstants = 1, invalid)")]
+// expected-error at +1 {{expected ')'}}
+[RootSignature("RootConstants(b0 num32BitConstants = 1)")]
void bad_root_signature_5() {}
#define MultiLineRootSignature \
>From f06ca8bc477ec600774634fe42c2a0381215e2d1 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 16:29:56 +0000
Subject: [PATCH 04/11] audit use of err_expected_after
the order of the parameters is switched as opposed to either and this
was not caught in the unit tests
---
clang/lib/Parse/ParseHLSLRootSignature.cpp | 4 +++-
clang/test/SemaHLSL/RootSignature-err.hlsl | 12 ++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 1b0cf53920f00..125e7f14ccfdb 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -1299,9 +1299,11 @@ bool RootSignatureParser::consumeExpectedToken(TokenKind Expected,
DB << Expected;
break;
case diag::err_expected_either:
- case diag::err_expected_after:
DB << Expected << Context;
break;
+ case diag::err_expected_after:
+ DB << Context << Expected;
+ break;
default:
break;
}
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index ec24c20178e52..c3e56d7e38382 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -55,3 +55,15 @@ void bad_root_signature_10() {}
// expected-error at +1 {{invalid parameter of DescriptorTable}}
[RootSignature("DescriptorTable(invalid))")]
void bad_root_signature_11() {}
+
+// expected-error at +1 {{expected integer literal after '+'}}
+[RootSignature("CBV(space = +invalid))")]
+void bad_root_signature_12() {}
+
+// expected-error at +1 {{expected integer literal after '='}}
+[RootSignature("CBV(space = invalid))")]
+void bad_root_signature_13() {}
+
+// expected-error at +1 {{expected '(' after UAV}}
+[RootSignature("UAV invalid")]
+void bad_root_signature_14() {}
>From 4f0384cd07585ba4bb95ab5ee10922d3bd7e1dd9 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 16:36:06 +0000
Subject: [PATCH 05/11] nfc: prepare to extend diagnostic to values as well
---
.../clang/Basic/DiagnosticParseKinds.td | 2 +-
clang/lib/Parse/ParseHLSLRootSignature.cpp | 22 ++++++++++---------
.../Parse/ParseHLSLRootSignatureTest.cpp | 2 +-
3 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 57cc935ff5f7a..35903af998fbe 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1863,7 +1863,7 @@ def err_hlsl_virtual_inheritance
: Error<"virtual inheritance is unsupported in HLSL">;
// HLSL Root Signature Parser Diagnostics
-def err_hlsl_invalid_param : Error<"invalid parameter of %0">;
+def err_hlsl_invalid_token : Error<"invalid %select{parameter|value}0 of %1">;
def err_hlsl_rootsig_repeat_param : Error<"specified the same parameter '%0' multiple times">;
def err_hlsl_rootsig_missing_param : Error<"did not specify mandatory parameter '%0'">;
def err_hlsl_number_literal_overflow : Error<
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 125e7f14ccfdb..61ae6c6baf15f 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -61,8 +61,8 @@ bool RootSignatureParser::parse() {
Elements.emplace_back(ElementLoc, *Sampler);
} else {
consumeNextToken(); // let diagnostic be at the start of invalid token
- reportDiag(diag::err_hlsl_invalid_param)
- << /*param of*/ TokenKind::kw_RootSignature;
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*parameter=*/0 << /*param of*/ TokenKind::kw_RootSignature;
return true;
}
@@ -268,8 +268,8 @@ std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
return std::nullopt;
} else {
consumeNextToken(); // let diagnostic be at the start of invalid token
- reportDiag(diag::err_hlsl_invalid_param)
- << /*param of*/ TokenKind::kw_DescriptorTable;
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*parameter=*/0 << /*param of*/ TokenKind::kw_DescriptorTable;
return std::nullopt;
}
@@ -486,8 +486,8 @@ RootSignatureParser::parseRootConstantParams() {
Params.Visibility = Visibility;
} else {
consumeNextToken(); // let diagnostic be at the start of invalid token
- reportDiag(diag::err_hlsl_invalid_param)
- << /*param of*/ TokenKind::kw_RootConstants;
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*parameter=*/0 << /*param of*/ TokenKind::kw_RootConstants;
return std::nullopt;
}
@@ -561,7 +561,8 @@ RootSignatureParser::parseRootDescriptorParams(TokenKind DescKind,
Params.Flags = Flags;
} else {
consumeNextToken(); // let diagnostic be at the start of invalid token
- reportDiag(diag::err_hlsl_invalid_param) << /*param of*/ DescKind;
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*parameter=*/0 << /*param of*/ DescKind;
return std::nullopt;
}
@@ -661,7 +662,8 @@ RootSignatureParser::parseDescriptorTableClauseParams(TokenKind ClauseKind,
Params.Flags = Flags;
} else {
consumeNextToken(); // let diagnostic be at the start of invalid token
- reportDiag(diag::err_hlsl_invalid_param) << /*param of*/ ClauseKind;
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*parameter=*/0 << /*param of*/ ClauseKind;
return std::nullopt;
}
@@ -860,8 +862,8 @@ RootSignatureParser::parseStaticSamplerParams() {
Params.Visibility = Visibility;
} else {
consumeNextToken(); // let diagnostic be at the start of invalid token
- reportDiag(diag::err_hlsl_invalid_param)
- << /*param of*/ TokenKind::kw_StaticSampler;
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*parameter=*/0 << /*param of*/ TokenKind::kw_StaticSampler;
return std::nullopt;
}
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 76121a5844242..e4b3b4ca5c8a6 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -865,7 +865,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseInvalidTokenTest) {
Signature, *PP);
// Test correct diagnostic produced - invalid token
- Consumer->setExpected(diag::err_hlsl_invalid_param);
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
>From 1d95cb66887eba1b27f5e93a6726cff712ab4862 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 16:51:02 +0000
Subject: [PATCH 06/11] extend invalid_token diagnostic to enum parsing
---
.../clang/Parse/ParseHLSLRootSignature.h | 15 +++--
clang/lib/Parse/ParseHLSLRootSignature.cpp | 60 ++++++++++++-------
clang/test/SemaHLSL/RootSignature-err.hlsl | 24 ++++++++
.../Parse/ParseHLSLRootSignatureTest.cpp | 27 +++++++++
4 files changed, 101 insertions(+), 25 deletions(-)
diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index 0c12421723feb..b3a0f131483bd 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -137,11 +137,16 @@ class RootSignatureParser {
std::optional<float> parseFloatParam();
/// Parsing methods of various enums
- std::optional<llvm::dxbc::ShaderVisibility> parseShaderVisibility();
- std::optional<llvm::dxbc::SamplerFilter> parseSamplerFilter();
- std::optional<llvm::dxbc::TextureAddressMode> parseTextureAddressMode();
- std::optional<llvm::dxbc::ComparisonFunc> parseComparisonFunc();
- std::optional<llvm::dxbc::StaticBorderColor> parseStaticBorderColor();
+ std::optional<llvm::dxbc::ShaderVisibility>
+ parseShaderVisibility(RootSignatureToken::Kind Context);
+ std::optional<llvm::dxbc::SamplerFilter>
+ parseSamplerFilter(RootSignatureToken::Kind Context);
+ std::optional<llvm::dxbc::TextureAddressMode>
+ parseTextureAddressMode(RootSignatureToken::Kind Context);
+ std::optional<llvm::dxbc::ComparisonFunc>
+ parseComparisonFunc(RootSignatureToken::Kind Context);
+ std::optional<llvm::dxbc::StaticBorderColor>
+ parseStaticBorderColor(RootSignatureToken::Kind Context);
std::optional<llvm::dxbc::RootDescriptorFlags> parseRootDescriptorFlags();
std::optional<llvm::dxbc::DescriptorRangeFlags> parseDescriptorRangeFlags();
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 61ae6c6baf15f..38ee6a35f3914 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -263,7 +263,7 @@ std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- Visibility = parseShaderVisibility();
+ Visibility = parseShaderVisibility(TokenKind::kw_visibility);
if (!Visibility.has_value())
return std::nullopt;
} else {
@@ -480,7 +480,7 @@ RootSignatureParser::parseRootConstantParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto Visibility = parseShaderVisibility();
+ auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
if (!Visibility.has_value())
return std::nullopt;
Params.Visibility = Visibility;
@@ -541,7 +541,7 @@ RootSignatureParser::parseRootDescriptorParams(TokenKind DescKind,
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto Visibility = parseShaderVisibility();
+ auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
if (!Visibility.has_value())
return std::nullopt;
Params.Visibility = Visibility;
@@ -702,7 +702,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto Filter = parseSamplerFilter();
+ auto Filter = parseSamplerFilter(TokenKind::kw_filter);
if (!Filter.has_value())
return std::nullopt;
Params.Filter = Filter;
@@ -716,7 +716,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto AddressU = parseTextureAddressMode();
+ auto AddressU = parseTextureAddressMode(TokenKind::kw_addressU);
if (!AddressU.has_value())
return std::nullopt;
Params.AddressU = AddressU;
@@ -730,7 +730,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto AddressV = parseTextureAddressMode();
+ auto AddressV = parseTextureAddressMode(TokenKind::kw_addressV);
if (!AddressV.has_value())
return std::nullopt;
Params.AddressV = AddressV;
@@ -744,7 +744,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto AddressW = parseTextureAddressMode();
+ auto AddressW = parseTextureAddressMode(TokenKind::kw_addressW);
if (!AddressW.has_value())
return std::nullopt;
Params.AddressW = AddressW;
@@ -786,7 +786,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto CompFunc = parseComparisonFunc();
+ auto CompFunc = parseComparisonFunc(TokenKind::kw_comparisonFunc);
if (!CompFunc.has_value())
return std::nullopt;
Params.CompFunc = CompFunc;
@@ -800,7 +800,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto BorderColor = parseStaticBorderColor();
+ auto BorderColor = parseStaticBorderColor(TokenKind::kw_borderColor);
if (!BorderColor.has_value())
return std::nullopt;
Params.BorderColor = BorderColor;
@@ -856,7 +856,7 @@ RootSignatureParser::parseStaticSamplerParams() {
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto Visibility = parseShaderVisibility();
+ auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
if (!Visibility.has_value())
return std::nullopt;
Params.Visibility = Visibility;
@@ -952,7 +952,7 @@ std::optional<float> RootSignatureParser::parseFloatParam() {
}
std::optional<llvm::dxbc::ShaderVisibility>
-RootSignatureParser::parseShaderVisibility() {
+RootSignatureParser::parseShaderVisibility(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -961,8 +961,12 @@ RootSignatureParser::parseShaderVisibility() {
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
};
- if (!tryConsumeExpectedToken(Expected))
+ if (!tryConsumeExpectedToken(Expected)) {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
return std::nullopt;
+ }
switch (CurToken.TokKind) {
#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
@@ -978,7 +982,7 @@ RootSignatureParser::parseShaderVisibility() {
}
std::optional<llvm::dxbc::SamplerFilter>
-RootSignatureParser::parseSamplerFilter() {
+RootSignatureParser::parseSamplerFilter(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -987,8 +991,12 @@ RootSignatureParser::parseSamplerFilter() {
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
};
- if (!tryConsumeExpectedToken(Expected))
+ if (!tryConsumeExpectedToken(Expected)) {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
return std::nullopt;
+ }
switch (CurToken.TokKind) {
#define FILTER_ENUM(NAME, LIT) \
@@ -1004,7 +1012,7 @@ RootSignatureParser::parseSamplerFilter() {
}
std::optional<llvm::dxbc::TextureAddressMode>
-RootSignatureParser::parseTextureAddressMode() {
+RootSignatureParser::parseTextureAddressMode(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -1013,8 +1021,12 @@ RootSignatureParser::parseTextureAddressMode() {
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
};
- if (!tryConsumeExpectedToken(Expected))
+ if (!tryConsumeExpectedToken(Expected)) {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
return std::nullopt;
+ }
switch (CurToken.TokKind) {
#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) \
@@ -1030,7 +1042,7 @@ RootSignatureParser::parseTextureAddressMode() {
}
std::optional<llvm::dxbc::ComparisonFunc>
-RootSignatureParser::parseComparisonFunc() {
+RootSignatureParser::parseComparisonFunc(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -1039,8 +1051,12 @@ RootSignatureParser::parseComparisonFunc() {
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
};
- if (!tryConsumeExpectedToken(Expected))
+ if (!tryConsumeExpectedToken(Expected)) {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
return std::nullopt;
+ }
switch (CurToken.TokKind) {
#define COMPARISON_FUNC_ENUM(NAME, LIT) \
@@ -1056,7 +1072,7 @@ RootSignatureParser::parseComparisonFunc() {
}
std::optional<llvm::dxbc::StaticBorderColor>
-RootSignatureParser::parseStaticBorderColor() {
+RootSignatureParser::parseStaticBorderColor(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -1065,8 +1081,12 @@ RootSignatureParser::parseStaticBorderColor() {
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
};
- if (!tryConsumeExpectedToken(Expected))
+ if (!tryConsumeExpectedToken(Expected)) {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
return std::nullopt;
+ }
switch (CurToken.TokKind) {
#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) \
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index c3e56d7e38382..405d0a47563f4 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -67,3 +67,27 @@ void bad_root_signature_13() {}
// expected-error at +1 {{expected '(' after UAV}}
[RootSignature("UAV invalid")]
void bad_root_signature_14() {}
+
+// expected-error at +1 {{invalid value of visibility}}
+[RootSignature("StaticSampler(s0, visibility = visibility_typo)")]
+void bad_root_signature_15() {}
+
+// expected-error at +1 {{invalid value of filter}}
+[RootSignature("StaticSampler(s0, filter = filter_typo)")]
+void bad_root_signature_16() {}
+
+// expected-error at +1 {{invalid value of addressU}}
+[RootSignature("StaticSampler(s0, addressU = addressU_typo)")]
+void bad_root_signature_17() {}
+
+// expected-error at +1 {{invalid value of addressV}}
+[RootSignature("StaticSampler(s0, addressV = addressV_typo)")]
+void bad_root_signature_18() {}
+
+// expected-error at +1 {{invalid value of comparisonFunc}}
+[RootSignature("StaticSampler(s0, comparisonFunc = comparisonFunc_typo)")]
+void bad_root_signature_19() {}
+
+// expected-error at +1 {{invalid value of borderColor}}
+[RootSignature("StaticSampler(s0, borderColor = borderColor_typo)")]
+void bad_root_signature_20() {}
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index e4b3b4ca5c8a6..a16da73a38dbf 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -1401,4 +1401,31 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerCommaTest) {
ASSERT_TRUE(Consumer->isSatisfied());
}
+TEST_F(ParseHLSLRootSignatureTest, InvalidVisibilityValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ UAV(
+ u0,
+ visibility = SHADER_VISIBILITY_TYPO
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
} // anonymous namespace
>From 24369b3e32b0acdbf3299e177bc67ec1844ae9f7 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 17:00:31 +0000
Subject: [PATCH 07/11] extend invalid_token diagnostic to flag parsing
---
.../clang/Parse/ParseHLSLRootSignature.h | 6 ++++--
clang/lib/Parse/ParseHLSLRootSignature.cpp | 18 ++++++++++++++----
clang/test/SemaHLSL/RootSignature-err.hlsl | 8 ++++++++
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index b3a0f131483bd..404bccea10c99 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -147,8 +147,10 @@ class RootSignatureParser {
parseComparisonFunc(RootSignatureToken::Kind Context);
std::optional<llvm::dxbc::StaticBorderColor>
parseStaticBorderColor(RootSignatureToken::Kind Context);
- std::optional<llvm::dxbc::RootDescriptorFlags> parseRootDescriptorFlags();
- std::optional<llvm::dxbc::DescriptorRangeFlags> parseDescriptorRangeFlags();
+ std::optional<llvm::dxbc::RootDescriptorFlags>
+ parseRootDescriptorFlags(RootSignatureToken::Kind Context);
+ std::optional<llvm::dxbc::DescriptorRangeFlags>
+ parseDescriptorRangeFlags(RootSignatureToken::Kind Context);
/// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
/// 32-bit integer
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 38ee6a35f3914..a5f7daabe367c 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -555,7 +555,7 @@ RootSignatureParser::parseRootDescriptorParams(TokenKind DescKind,
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto Flags = parseRootDescriptorFlags();
+ auto Flags = parseRootDescriptorFlags(TokenKind::kw_flags);
if (!Flags.has_value())
return std::nullopt;
Params.Flags = Flags;
@@ -656,7 +656,7 @@ RootSignatureParser::parseDescriptorTableClauseParams(TokenKind ClauseKind,
if (consumeExpectedToken(TokenKind::pu_equal))
return std::nullopt;
- auto Flags = parseDescriptorRangeFlags();
+ auto Flags = parseDescriptorRangeFlags(TokenKind::kw_flags);
if (!Flags.has_value())
return std::nullopt;
Params.Flags = Flags;
@@ -1102,7 +1102,7 @@ RootSignatureParser::parseStaticBorderColor(TokenKind Context) {
}
std::optional<llvm::dxbc::RootDescriptorFlags>
-RootSignatureParser::parseRootDescriptorFlags() {
+RootSignatureParser::parseRootDescriptorFlags(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -1134,6 +1134,11 @@ RootSignatureParser::parseRootDescriptorFlags() {
default:
llvm_unreachable("Switch for consumed enum token was not provided");
}
+ } else {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
+ return std::nullopt;
}
} while (tryConsumeExpectedToken(TokenKind::pu_or));
@@ -1141,7 +1146,7 @@ RootSignatureParser::parseRootDescriptorFlags() {
}
std::optional<llvm::dxbc::DescriptorRangeFlags>
-RootSignatureParser::parseDescriptorRangeFlags() {
+RootSignatureParser::parseDescriptorRangeFlags(TokenKind Context) {
assert(CurToken.TokKind == TokenKind::pu_equal &&
"Expects to only be invoked starting at given keyword");
@@ -1173,6 +1178,11 @@ RootSignatureParser::parseDescriptorRangeFlags() {
default:
llvm_unreachable("Switch for consumed enum token was not provided");
}
+ } else {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ Context;
+ return std::nullopt;
}
} while (tryConsumeExpectedToken(TokenKind::pu_or));
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index 405d0a47563f4..e8abac07ab5a6 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -91,3 +91,11 @@ void bad_root_signature_19() {}
// expected-error at +1 {{invalid value of borderColor}}
[RootSignature("StaticSampler(s0, borderColor = borderColor_typo)")]
void bad_root_signature_20() {}
+
+// expected-error at +1 {{invalid value of flags}}
+[RootSignature("CBV(b0, flags = DATA_VOLATILE | root_descriptor_flag_typo)")]
+void bad_root_signature_21() {}
+
+// expected-error at +1 {{invalid value of flags}}
+[RootSignature("DescriptorTable(SRV(t0, flags = descriptor_range_flag_typo)")]
+void bad_root_signature_22() {}
>From 3a4ef78879d8d340d6c67acacc1a46d0cbbfead7 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 17:07:42 +0000
Subject: [PATCH 08/11] extend invalid_token diagnostic to RootFlags enum
---
clang/lib/Parse/ParseHLSLRootSignature.cpp | 9 +++++++++
clang/test/SemaHLSL/RootSignature-err.hlsl | 4 ++++
2 files changed, 13 insertions(+)
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index a5f7daabe367c..07cfbf0111d5d 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -93,6 +93,10 @@ std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
std::optional<llvm::dxbc::RootFlags> Flags = llvm::dxbc::RootFlags::None;
+ // Handle valid empty case
+ if (tryConsumeExpectedToken(TokenKind::pu_r_paren))
+ return Flags;
+
// Handle the edge-case of '0' to specify no flags set
if (tryConsumeExpectedToken(TokenKind::int_literal)) {
if (!verifyZeroFlag()) {
@@ -118,6 +122,11 @@ std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
default:
llvm_unreachable("Switch for consumed enum token was not provided");
}
+ } else {
+ consumeNextToken(); // consume token to point at invalid token
+ reportDiag(diag::err_hlsl_invalid_token)
+ << /*value=*/1 << /*value of*/ TokenKind::kw_RootFlags;
+ return std::nullopt;
}
} while (tryConsumeExpectedToken(TokenKind::pu_or));
}
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index e8abac07ab5a6..98390e29fe1f2 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -99,3 +99,7 @@ void bad_root_signature_21() {}
// expected-error at +1 {{invalid value of flags}}
[RootSignature("DescriptorTable(SRV(t0, flags = descriptor_range_flag_typo)")]
void bad_root_signature_22() {}
+
+// expected-error at +1 {{invalid value of RootFlags}}
+[RootSignature("RootFlags(local_root_signature | root_flag_typo)")]
+void bad_root_signature_23() {}
>From b68cf495c45be44b2275ed4f92e65da657fd8663 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 17:52:05 +0000
Subject: [PATCH 09/11] improve err_expected to err_expected_either at end of
params
---
clang/lib/Parse/ParseHLSLRootSignature.cpp | 21 ++++++++++++-------
clang/test/SemaHLSL/RootSignature-err.hlsl | 4 ++--
.../Parse/ParseHLSLRootSignatureTest.cpp | 14 ++++++-------
3 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 07cfbf0111d5d..870cb88f40963 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -71,7 +71,8 @@ bool RootSignatureParser::parse() {
break;
}
- return consumeExpectedToken(TokenKind::end_of_stream);
+ return consumeExpectedToken(TokenKind::end_of_stream,
+ diag::err_expected_either, TokenKind::pu_comma);
}
template <typename FlagType>
@@ -131,7 +132,8 @@ std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
} while (tryConsumeExpectedToken(TokenKind::pu_or));
}
- if (consumeExpectedToken(TokenKind::pu_r_paren))
+ if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
+ TokenKind::pu_comma))
return std::nullopt;
return Flags;
@@ -151,7 +153,8 @@ std::optional<RootConstants> RootSignatureParser::parseRootConstants() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren))
+ if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
+ TokenKind::pu_comma))
return std::nullopt;
// Check mandatory parameters where provided
@@ -216,7 +219,8 @@ std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren))
+ if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
+ TokenKind::pu_comma))
return std::nullopt;
// Check mandatory parameters were provided
@@ -287,7 +291,8 @@ std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
break;
}
- if (consumeExpectedToken(TokenKind::pu_r_paren))
+ if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
+ TokenKind::pu_comma))
return std::nullopt;
// Fill in optional visibility
@@ -339,7 +344,8 @@ RootSignatureParser::parseDescriptorTableClause() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren))
+ if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
+ TokenKind::pu_comma))
return std::nullopt;
// Check mandatory parameters were provided
@@ -380,7 +386,8 @@ std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
if (!Params.has_value())
return std::nullopt;
- if (consumeExpectedToken(TokenKind::pu_r_paren))
+ if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
+ TokenKind::pu_comma))
return std::nullopt;
// Check mandatory parameters were provided
diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
index 98390e29fe1f2..4b53a127d2adb 100644
--- a/clang/test/SemaHLSL/RootSignature-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -21,7 +21,7 @@ void bad_root_signature_3() {}
[RootSignature("DescriptorTable(), invalid")]
void bad_root_signature_4() {}
-// expected-error at +1 {{expected ')'}}
+// expected-error at +1 {{expected ')' or ','}}
[RootSignature("RootConstants(b0 num32BitConstants = 1)")]
void bad_root_signature_5() {}
@@ -36,7 +36,7 @@ void bad_root_signature_5() {}
[RootSignature(MultiLineRootSignature)]
void bad_root_signature_6() {}
-// expected-error at +1 {{expected end of stream}}
+// expected-error at +1 {{expected end of stream or ','}}
[RootSignature("RootFlags() RootConstants(b0, num32BitConstants = 1)")]
void bad_root_signature_7() {}
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index a16da73a38dbf..597004eaba971 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -843,7 +843,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedTokenTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1258,7 +1258,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootElementMissingCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1285,7 +1285,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableMissingCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1312,7 +1312,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootConstantParamsCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1339,7 +1339,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamsCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1368,7 +1368,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorClauseParamsCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
@@ -1395,7 +1395,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerCommaTest) {
Signature, *PP);
// Test correct diagnostic produced
- Consumer->setExpected(diag::err_expected);
+ Consumer->setExpected(diag::err_expected_either);
ASSERT_TRUE(Parser.parse());
ASSERT_TRUE(Consumer->isSatisfied());
>From 515e4c3b68ec299493d69e2b3c8f74997f6e77df Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 18:05:01 +0000
Subject: [PATCH 10/11] improve unit test coverge of invalid values
---
.../Parse/ParseHLSLRootSignatureTest.cpp | 210 ++++++++++++++++++
1 file changed, 210 insertions(+)
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 597004eaba971..429724ad24f72 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -1428,4 +1428,214 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidVisibilityValueTest) {
ASSERT_TRUE(Consumer->isSatisfied());
}
+TEST_F(ParseHLSLRootSignatureTest, InvalidRegisterValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(
+ b0
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidFilterValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(
+ s0,
+ filter = FILTER_TYPO
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidTextureAddressModeValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(
+ s0,
+ addressU = TEXTURE_ADDRESS_MODE_TYPO
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidComparisonFuncValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(
+ s0,
+ comparisonFunc = COMPARISON_FUNC_TYPO
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidStaticBorderColorValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(
+ s0,
+ borderColor = STATIC_BORDER_COLOR_TYPO
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidRootFlagsValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ RootFlags( ROOT_FLAG_TYPO )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorFlagsValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ CBV( flags = DATA_STATIC | ROOT_DESRIPTOR_FLAG_TYPO )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorRangeFlagsValueTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ DescriptorTable(
+ CBV(
+ flags = DATA_STATIC | DESRIPTOR_RANGE_FLAG_TYPO | DESCRIPTORS_VOLATILE
+ )
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
} // anonymous namespace
>From 8e55607e7ea62ea5f194c0f38de84b783a55622b Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Jul 2025 18:49:46 +0000
Subject: [PATCH 11/11] improve unit test coverage of invalid parameters
---
.../Parse/ParseHLSLRootSignatureTest.cpp | 106 ++++++++++++++++++
1 file changed, 106 insertions(+)
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 429724ad24f72..4b24800489c8e 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -1401,6 +1401,112 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerCommaTest) {
ASSERT_TRUE(Consumer->isSatisfied());
}
+TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ SRV(t0, invalid)
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableParamTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ DescriptorTable(
+ visibility = SHADER_VISIBILITY_ALL,
+ invalid
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableClauseParamTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ DescriptorTable(
+ CBV(invalid)
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
+TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerParamTest) {
+ // This test will check that an error is produced when there is a invalid
+ // value of a parameter
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(
+ s0,
+ filter = FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT,
+ invalid,
+ comparisonFunc = COMPARISON_EQUAL,
+ )
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ SmallVector<RootSignatureElement> Elements;
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
+ Signature, *PP);
+
+ // Test correct diagnostic produced
+ Consumer->setExpected(diag::err_hlsl_invalid_token);
+ ASSERT_TRUE(Parser.parse());
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
TEST_F(ParseHLSLRootSignatureTest, InvalidVisibilityValueTest) {
// This test will check that an error is produced when there is a invalid
// value of a parameter
More information about the cfe-commits
mailing list