tint: Fix ICE in ast::TemplatedIdentifier ctor

Invalid programs could attempt to construct an ast::TemplatedIdentifier with no template arguments.
In this situation an ast::Identifier should be constructed instead.

Bug: chromium:1417465
Change-Id: Id1516cd83679947b5346c69ce5453d72f4f93b49
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/120841
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2023-02-21 22:01:48 +00:00 committed by Dawn LUCI CQ
parent 2f689a7efe
commit 60d3738102
3 changed files with 31 additions and 18 deletions

View File

@ -26,21 +26,25 @@ using TemplatedIdentifierTest = TestHelper;
TEST_F(TemplatedIdentifierTest, Creation) { TEST_F(TemplatedIdentifierTest, Creation) {
auto* i = Ident("ident", 1_a, Add("x", "y"), false, "x"); auto* i = Ident("ident", 1_a, Add("x", "y"), false, "x");
EXPECT_EQ(i->symbol, Symbols().Get("ident")); EXPECT_EQ(i->symbol, Symbols().Get("ident"));
ASSERT_EQ(i->arguments.Length(), 4u); auto* t = i->As<TemplatedIdentifier>();
EXPECT_TRUE(i->arguments[0]->Is<ast::IntLiteralExpression>()); ASSERT_NE(t, nullptr);
EXPECT_TRUE(i->arguments[1]->Is<ast::BinaryExpression>()); ASSERT_EQ(t->arguments.Length(), 4u);
EXPECT_TRUE(i->arguments[2]->Is<ast::BoolLiteralExpression>()); EXPECT_TRUE(t->arguments[0]->Is<IntLiteralExpression>());
EXPECT_TRUE(i->arguments[3]->Is<ast::IdentifierExpression>()); EXPECT_TRUE(t->arguments[1]->Is<BinaryExpression>());
EXPECT_TRUE(t->arguments[2]->Is<BoolLiteralExpression>());
EXPECT_TRUE(t->arguments[3]->Is<IdentifierExpression>());
} }
TEST_F(TemplatedIdentifierTest, Creation_WithSource) { TEST_F(TemplatedIdentifierTest, Creation_WithSource) {
auto* i = Ident(Source{{20, 2}}, "ident", 1_a, Add("x", "y"), false, "x"); auto* i = Ident(Source{{20, 2}}, "ident", 1_a, Add("x", "y"), false, "x");
EXPECT_EQ(i->symbol, Symbols().Get("ident")); EXPECT_EQ(i->symbol, Symbols().Get("ident"));
ASSERT_EQ(i->arguments.Length(), 4u); auto* t = i->As<TemplatedIdentifier>();
EXPECT_TRUE(i->arguments[0]->Is<ast::IntLiteralExpression>()); ASSERT_NE(t, nullptr);
EXPECT_TRUE(i->arguments[1]->Is<ast::BinaryExpression>()); ASSERT_EQ(t->arguments.Length(), 4u);
EXPECT_TRUE(i->arguments[2]->Is<ast::BoolLiteralExpression>()); EXPECT_TRUE(t->arguments[0]->Is<IntLiteralExpression>());
EXPECT_TRUE(i->arguments[3]->Is<ast::IdentifierExpression>()); EXPECT_TRUE(t->arguments[1]->Is<BinaryExpression>());
EXPECT_TRUE(t->arguments[2]->Is<BoolLiteralExpression>());
EXPECT_TRUE(t->arguments[3]->Is<IdentifierExpression>());
auto src = i->source; auto src = i->source;
EXPECT_EQ(src.range.begin.line, 20u); EXPECT_EQ(src.range.begin.line, 20u);

View File

@ -1496,23 +1496,24 @@ class ProgramBuilder {
/// @param identifier the identifier symbol /// @param identifier the identifier symbol
/// @param args the templated identifier arguments /// @param args the templated identifier arguments
/// @return an ast::TemplatedIdentifier with the given symbol and template arguments /// @return an ast::Identifier with the given symbol and template arguments
template <typename IDENTIFIER, typename... ARGS, typename = DisableIfSource<IDENTIFIER>> template <typename IDENTIFIER, typename... ARGS, typename = DisableIfSource<IDENTIFIER>>
const ast::TemplatedIdentifier* Ident(IDENTIFIER&& identifier, ARGS&&... args) { const ast::Identifier* Ident(IDENTIFIER&& identifier, ARGS&&... args) {
return Ident(source_, std::forward<IDENTIFIER>(identifier), std::forward<ARGS>(args)...); return Ident(source_, std::forward<IDENTIFIER>(identifier), std::forward<ARGS>(args)...);
} }
/// @param source the source information /// @param source the source information
/// @param identifier the identifier symbol /// @param identifier the identifier symbol
/// @param args the templated identifier arguments /// @param args the templated identifier arguments
/// @return an ast::TemplatedIdentifier with the given symbol and template arguments /// @return an ast::Identifier with the given symbol and template arguments
template <typename IDENTIFIER, typename... ARGS> template <typename IDENTIFIER, typename... ARGS>
const ast::TemplatedIdentifier* Ident(const Source& source, const ast::Identifier* Ident(const Source& source, IDENTIFIER&& identifier, ARGS&&... args) {
IDENTIFIER&& identifier, auto arg_exprs = ExprList(std::forward<ARGS>(args)...);
ARGS&&... args) { if (arg_exprs.IsEmpty()) {
return create<ast::Identifier>(source, Sym(std::forward<IDENTIFIER>(identifier)));
}
return create<ast::TemplatedIdentifier>(source, Sym(std::forward<IDENTIFIER>(identifier)), return create<ast::TemplatedIdentifier>(source, Sym(std::forward<IDENTIFIER>(identifier)),
ExprList(std::forward<ARGS>(args)...), std::move(arg_exprs), utils::Empty);
utils::Empty);
} }
/// @param expr the expression /// @param expr the expression

View File

@ -1111,5 +1111,13 @@ TEST_F(ParserImplErrorTest, InvalidUTF8) {
"fn fu\xD0nc() {}\n"); "fn fu\xD0nc() {}\n");
} }
TEST_F(ParserImplErrorTest, Bug_Chromium_1417465) {
EXPECT("var<workgroup> vec4_data: array<mat4x4<f@32>, 256>;",
R"(test.wgsl:1:41 error: expected ',' for template argument list
var<workgroup> vec4_data: array<mat4x4<f@32>, 256>;
^
)");
}
} // namespace } // namespace
} // namespace tint::reader::wgsl } // namespace tint::reader::wgsl