https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147800
>From 95166f5e2bfb2816ce39d3abd1823486742109bd Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 fd8e5c3c6ad87..a4c524544be12 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1860,8 +1860,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 6c27ea22a2167..28ac35b614755 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 50807d611e91a..7e300e5cb8718 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@+1 {{expected ')' to denote end of parameters, or, another valid parameter of RootConstants}} +// expected-error@+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@+1 {{expected ')' to denote end of parameters, or, another valid parameter of RootConstants}} +// expected-error@+1 {{expected ')'}} [RootSignature(MultiLineRootSignature)] void bad_root_signature_6() {} -// expected-error@+1 {{expected end of stream to denote end of parameters, or, another valid parameter of RootSignature}} +// expected-error@+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 24a2bea7fa745f3909f632369e8f8aaa7fff0b2a Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 a4c524544be12..4671b3aad303c 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1860,6 +1860,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 28ac35b614755..41c1fb24614f7 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(RootSignatureElement(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 7e300e5cb8718..188cf6de182fa 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@+1 {{invalid parameter of RootSignature}} +[RootSignature("DescriptorTable(), invalid")] void bad_root_signature_4() {} -// expected-error@+1 {{expected ')'}} +// expected-error@+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@+1 {{expected ')'}} +// CHECK-NEXT: | ^ +// expected-error@+1 {{invalid parameter of RootConstants}} [RootSignature(MultiLineRootSignature)] void bad_root_signature_6() {} // expected-error@+1 {{expected end of stream}} [RootSignature("RootFlags() RootConstants(b0, num32BitConstants = 1))")] void bad_root_signature_7() {} + +// expected-error@+1 {{invalid parameter of RootConstants}} +[RootSignature("RootConstants(b0, num32BitConstantsTypo = 1))")] +void bad_root_signature_8() {} + +// expected-error@+1 {{invalid parameter of UAV}} +[RootSignature("UAV(b3")] +void bad_root_signature_9() {} + +// expected-error@+1 {{invalid parameter of SRV}} +[RootSignature("DescriptorTable(SRV(s1, invalid))")] +void bad_root_signature_10() {} + +// expected-error@+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 4edb7fa000026935accfd993ff4ca1f4eed68c2e Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 188cf6de182fa..0fff28ec57970 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@+1 {{invalid parameter of RootConstants}} -[RootSignature("RootConstants(b0, num32BitConstants = 1, invalid)")] +// expected-error@+1 {{expected ')'}} +[RootSignature("RootConstants(b0 num32BitConstants = 1)")] void bad_root_signature_5() {} #define MultiLineRootSignature \ >From b17b40c5b6f8e68a83f8ad7cedc3c0a51589c945 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 41c1fb24614f7..028e21b8a6bf2 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 0fff28ec57970..8c5fdc016234c 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@+1 {{invalid parameter of DescriptorTable}} [RootSignature("DescriptorTable(invalid))")] void bad_root_signature_11() {} + +// expected-error@+1 {{expected integer literal after '+'}} +[RootSignature("CBV(space = +invalid))")] +void bad_root_signature_12() {} + +// expected-error@+1 {{expected integer literal after '='}} +[RootSignature("CBV(space = invalid))")] +void bad_root_signature_13() {} + +// expected-error@+1 {{expected '(' after UAV}} +[RootSignature("UAV invalid")] +void bad_root_signature_14() {} >From bbd8921c962a6982f10881257a3ec37d6f2d2b90 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 4671b3aad303c..becca29c12dc0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1860,7 +1860,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 028e21b8a6bf2..9d63c8f65040c 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -61,8 +61,8 @@ bool RootSignatureParser::parse() { Elements.emplace_back(RootSignatureElement(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 c3a4642c5869324a88b70ed867b0ee62da4ff8e7 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 9d63c8f65040c..16f2426e3d006 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 8c5fdc016234c..060514fb232a1 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@+1 {{expected '(' after UAV}} [RootSignature("UAV invalid")] void bad_root_signature_14() {} + +// expected-error@+1 {{invalid value of visibility}} +[RootSignature("StaticSampler(s0, visibility = visibility_typo)")] +void bad_root_signature_15() {} + +// expected-error@+1 {{invalid value of filter}} +[RootSignature("StaticSampler(s0, filter = filter_typo)")] +void bad_root_signature_16() {} + +// expected-error@+1 {{invalid value of addressU}} +[RootSignature("StaticSampler(s0, addressU = addressU_typo)")] +void bad_root_signature_17() {} + +// expected-error@+1 {{invalid value of addressV}} +[RootSignature("StaticSampler(s0, addressV = addressV_typo)")] +void bad_root_signature_18() {} + +// expected-error@+1 {{invalid value of comparisonFunc}} +[RootSignature("StaticSampler(s0, comparisonFunc = comparisonFunc_typo)")] +void bad_root_signature_19() {} + +// expected-error@+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 b32343063a62681e3aefd46d1b21018c84476e26 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 16f2426e3d006..06564e32d3be9 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 060514fb232a1..d96b594b858c2 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@+1 {{invalid value of borderColor}} [RootSignature("StaticSampler(s0, borderColor = borderColor_typo)")] void bad_root_signature_20() {} + +// expected-error@+1 {{invalid value of flags}} +[RootSignature("CBV(b0, flags = DATA_VOLATILE | root_descriptor_flag_typo)")] +void bad_root_signature_21() {} + +// expected-error@+1 {{invalid value of flags}} +[RootSignature("DescriptorTable(SRV(t0, flags = descriptor_range_flag_typo)")] +void bad_root_signature_22() {} >From 8187a65789e8776513e9b3ea9756da62fddd4ad7 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 06564e32d3be9..8a6324155046a 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 d96b594b858c2..be68b7059aa8e 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@+1 {{invalid value of flags}} [RootSignature("DescriptorTable(SRV(t0, flags = descriptor_range_flag_typo)")] void bad_root_signature_22() {} + +// expected-error@+1 {{invalid value of RootFlags}} +[RootSignature("RootFlags(local_root_signature | root_flag_typo)")] +void bad_root_signature_23() {} >From 6d48044edf53d679d9c6a36d88219b401d05944d Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 8a6324155046a..87de627a98fb7 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 be68b7059aa8e..b69807132e795 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@+1 {{expected ')'}} +// expected-error@+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@+1 {{expected end of stream}} +// expected-error@+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 522b08467c40282feb8566b648b8c16f86232942 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 70448a3e3daae9ebac71df5b995bc93025b7a644 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@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 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits