diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc index b2dfcbcd44..1110f5cd33 100644 --- a/src/tint/reader/wgsl/parser_impl.cc +++ b/src/tint/reader/wgsl/parser_impl.cc @@ -38,6 +38,7 @@ #include "src/tint/ast/variable_decl_statement.h" #include "src/tint/ast/vector.h" #include "src/tint/ast/workgroup_attribute.h" +#include "src/tint/reader/wgsl/classify_template_args.h" #include "src/tint/reader/wgsl/lexer.h" #include "src/tint/type/depth_texture.h" #include "src/tint/type/external_texture.h" @@ -319,6 +320,7 @@ Source ParserImpl::last_source() const { void ParserImpl::InitializeLex() { Lexer l{file_}; tokens_ = l.Lex(); + ClassifyTemplateArguments(tokens_); } bool ParserImpl::Parse() { @@ -731,7 +733,7 @@ Maybe ParserImpl::texture_and_sampler_types() { if (dim.matched) { const char* use = "sampled texture type"; - auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); }); + auto subtype = expect_template_arg_block(use, [&] { return expect_type(use); }); if (subtype.errored) { return Failure::kErrored; } @@ -743,7 +745,7 @@ Maybe ParserImpl::texture_and_sampler_types() { if (ms_dim.matched) { const char* use = "multisampled texture type"; - auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); }); + auto subtype = expect_template_arg_block(use, [&] { return expect_type(use); }); if (subtype.errored) { return Failure::kErrored; } @@ -755,7 +757,7 @@ Maybe ParserImpl::texture_and_sampler_types() { if (storage.matched) { const char* use = "storage texture type"; using StorageTextureInfo = std::pair; - auto params = expect_lt_gt_block(use, [&]() -> Expect { + auto params = expect_template_arg_block(use, [&]() -> Expect { auto format = expect_texel_format(use); if (format.errored) { return Failure::kErrored; @@ -1129,7 +1131,8 @@ Maybe ParserImpl::type_specifier_without_ident() { return builder_.ty.u32(t.source()); } - if (t.Is(Token::Type::kArray) && peek_is(Token::Type::kLessThan, 1)) { + if (t.Is(Token::Type::kArray) && + (peek_is(Token::Type::kTemplateArgsLeft, 1) || peek_is(Token::Type::kLessThan, 1))) { if (match(Token::Type::kArray)) { return expect_type_specifier_array(t.source()); } @@ -1143,14 +1146,16 @@ Maybe ParserImpl::type_specifier_without_ident() { return expect_type_specifier_pointer(t.source()); } - if (t.IsMatrix() && peek_is(Token::Type::kLessThan, 1)) { + if (t.IsMatrix() && + (peek_is(Token::Type::kTemplateArgsLeft, 1) || peek_is(Token::Type::kLessThan, 1))) { auto mat = mat_prefix(); if (mat.matched) { return expect_type_specifier_matrix(t.source(), mat.value); } } - if (t.IsVector() && peek_is(Token::Type::kLessThan, 1)) { + if (t.IsVector() && + (peek_is(Token::Type::kTemplateArgsLeft, 1) || peek_is(Token::Type::kLessThan, 1))) { auto vec = vec_prefix(); if (vec.matched) { return expect_type_specifier_vector(t.source(), vec.value); @@ -1259,7 +1264,7 @@ Expect ParserImpl::expect_type_specifier_pointer(const Source& auto address_space = type::AddressSpace::kNone; auto access = type::Access::kUndefined; - auto subtype = expect_lt_gt_block(use, [&]() -> Expect { + auto subtype = expect_template_arg_block(use, [&]() -> Expect { auto sc = expect_address_space(use); if (sc.errored) { return Failure::kErrored; @@ -1297,7 +1302,7 @@ Expect ParserImpl::expect_type_specifier_pointer(const Source& Expect ParserImpl::expect_type_specifier_atomic(const Source& s) { const char* use = "atomic declaration"; - auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); }); + auto subtype = expect_template_arg_block(use, [&] { return expect_type(use); }); if (subtype.errored) { return Failure::kErrored; } @@ -1308,7 +1313,7 @@ Expect ParserImpl::expect_type_specifier_atomic(const Source& // LESS_THAN type_specifier GREATER_THAN Expect ParserImpl::expect_type_specifier_vector(const Source& s, uint32_t count) { const char* use = "vector"; - auto ty = expect_lt_gt_block(use, [&] { return expect_type(use); }); + auto ty = expect_template_arg_block(use, [&] { return expect_type(use); }); if (ty.errored) { return Failure::kErrored; } @@ -1325,11 +1330,7 @@ Expect ParserImpl::expect_type_specifier_array(const Source& s const ast::Expression* size = nullptr; }; - if (!peek_is(Token::Type::kLessThan)) { - return add_error(peek(), "expected < for array"); - } - - auto type_size = expect_lt_gt_block(use, [&]() -> Expect { + auto type_size = expect_template_arg_block(use, [&]() -> Expect { auto type = expect_type(use); if (type.errored) { return Failure::kErrored; @@ -1361,7 +1362,7 @@ Expect ParserImpl::expect_type_specifier_array(const Source& s Expect ParserImpl::expect_type_specifier_matrix(const Source& s, const MatrixDimensions& dims) { const char* use = "matrix"; - auto ty = expect_lt_gt_block(use, [&] { return expect_type(use); }); + auto ty = expect_template_arg_block(use, [&] { return expect_type(use); }); if (ty.errored) { return Failure::kErrored; } @@ -2555,7 +2556,7 @@ Maybe ParserImpl::primary_expression() { if (match(Token::Type::kBitcast)) { const char* use = "bitcast expression"; - auto type = expect_lt_gt_block(use, [&] { return expect_type(use); }); + auto type = expect_template_arg_block(use, [&] { return expect_type(use); }); if (type.errored) { return Failure::kErrored; } @@ -2592,6 +2593,14 @@ Maybe ParserImpl::primary_expression() { if (t.IsIdentifier()) { next(); + if (Source source; match(Token::Type::kTemplateArgsLeft, &source)) { + return add_error( + source, + "'<' treated as the start of a template argument list, which is not supported for " + "user-declared types or functions. If you intended less-than, wrap the expression " + "in parentheses"); + } + auto* ident = create(t.source(), builder_.Symbols().Register(t.to_str())); @@ -3733,7 +3742,11 @@ bool ParserImpl::expect(std::string_view use, Token::Type tok) { } std::stringstream err; - err << "expected '" << Token::TypeToName(tok) << "'"; + if (tok == Token::Type::kTemplateArgsLeft && t.type() == Token::Type::kLessThan) { + err << "missing closing '>'"; + } else { + err << "expected '" << Token::TypeToName(tok) << "'"; + } if (!use.empty()) { err << " for " << use; } @@ -3842,6 +3855,12 @@ T ParserImpl::expect_lt_gt_block(std::string_view use, F&& body) { std::forward(body)); } +template +T ParserImpl::expect_template_arg_block(std::string_view use, F&& body) { + return expect_block(Token::Type::kTemplateArgsLeft, Token::Type::kTemplateArgsRight, use, + std::forward(body)); +} + template T ParserImpl::sync(Token::Type tok, F&& body) { if (parse_depth_ >= kMaxParseDepth) { diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h index 84238072a7..ed7c226ea6 100644 --- a/src/tint/reader/wgsl/parser_impl.h +++ b/src/tint/reader/wgsl/parser_impl.h @@ -799,6 +799,16 @@ class ParserImpl { /// an Expect with error state. template > T expect_lt_gt_block(std::string_view use, F&& body); + /// A convenience function that calls `expect_block` passing + /// `Token::Type::kTemplateArgsLeft` and `Token::Type::kTemplateArgsRight` for the `start` and + /// `end` arguments, respectively. + /// @param use a description of what was being parsed if an error was raised + /// @param body a function or lambda that is called to parse the lexical block body, with the + /// signature: `Expect()` or `Maybe()`. + /// @return the value returned by `body` if no errors are raised, otherwise an Expect with error + /// state. + template > + T expect_template_arg_block(std::string_view use, F&& body); /// sync() calls the function `func`, and attempts to resynchronize the /// parser to the next found resynchronization token if `func` fails. If the diff --git a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc index c93604e293..ce3628811b 100644 --- a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc +++ b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc @@ -120,8 +120,9 @@ fn f() { a = >; } } TEST_F(ParserImplErrorTest, BitcastExprMissingLessThan) { - EXPECT("fn f() { x = bitcast(y); }", - R"(test.wgsl:1:21 error: expected '<' for bitcast expression + EXPECT( + "fn f() { x = bitcast(y); }", + R"(test.wgsl:1:21 error: expected '< (opening template argument list)' for bitcast expression fn f() { x = bitcast(y); } ^ )"); @@ -129,9 +130,9 @@ fn f() { x = bitcast(y); } TEST_F(ParserImplErrorTest, BitcastExprMissingGreaterThan) { EXPECT("fn f() { x = bitcast' for bitcast expression + R"(test.wgsl:1:21 error: missing closing '>' for bitcast expression fn f() { x = bitcast' for sampled texture type + R"(test.wgsl:1:19 error: missing closing '>' for sampled texture type var x : texture_1d; } TEST_F(ParserImplErrorTest, GlobalDeclMultisampledTextureMissingLessThan) { - EXPECT("var x : texture_multisampled_2d;", - R"(test.wgsl:1:32 error: expected '<' for multisampled texture type + EXPECT( + "var x : texture_multisampled_2d;", + R"(test.wgsl:1:32 error: expected '< (opening template argument list)' for multisampled texture type var x : texture_multisampled_2d; ^ )"); @@ -692,9 +695,9 @@ var x : texture_multisampled_2d; TEST_F(ParserImplErrorTest, GlobalDeclMultisampledTextureMissingGreaterThan) { EXPECT("var x : texture_multisampled_2d' for multisampled texture type + R"(test.wgsl:1:32 error: missing closing '>' for multisampled texture type var x : texture_multisampled_2d' for storage texture type + R"(test.wgsl:1:27 error: missing closing '>' for storage texture type var x : texture_storage_2d' for array declaration + R"(test.wgsl:1:14 error: missing closing '>' for array declaration var i : array' for matrix + EXPECT("var i : mat4x4' for matrix var i : mat4x4' for ptr declaration + R"(test.wgsl:1:12 error: missing closing '>' for ptr declaration var i : ptr; } TEST_F(ParserImplErrorTest, GlobalDeclVarAtomicMissingLessThan) { - EXPECT("var i : atomic;", - R"(test.wgsl:1:15 error: expected '<' for atomic declaration + EXPECT( + "var i : atomic;", + R"(test.wgsl:1:15 error: expected '< (opening template argument list)' for atomic declaration var i : atomic; ^ )"); @@ -1246,9 +1252,9 @@ var i : atomic; TEST_F(ParserImplErrorTest, GlobalDeclVarAtomicMissingGreaterThan) { EXPECT("var i : atomic' for atomic declaration + R"(test.wgsl:1:15 error: missing closing '>' for atomic declaration var i : atomic' for vector + EXPECT("var i : vec3' for vector var i : vec3 Cases() { std::vector out; for (auto& lhs_op : kBinaryOperators) { for (auto& rhs_op : kBinaryOperators) { - bool should_parse = lhs_op.can_follow_without_paren & rhs_op.bit; + bool should_parse = (lhs_op.can_follow_without_paren & rhs_op.bit) && + !ParsedAsTemplateArgumentList(lhs_op, rhs_op); out.push_back({lhs_op, rhs_op, should_parse}); } } @@ -494,8 +498,14 @@ TEST_P(ParserImplMixedBinaryOpTest, Test) { EXPECT_EQ(e.value, nullptr); EXPECT_TRUE(p->has_error()); std::stringstream expected; - expected << "1:3: mixing '" << GetParam().lhs_op.symbol << "' and '" - << GetParam().rhs_op.symbol << "' requires parenthesis"; + if (ParsedAsTemplateArgumentList(GetParam().lhs_op, GetParam().rhs_op)) { + expected << "1:3: '<' treated as the start of a template argument list, which is not " + "supported for user-declared types or functions. If you intended " + "less-than, wrap the expression in parentheses"; + } else { + expected << "1:3: mixing '" << GetParam().lhs_op.symbol << "' and '" + << GetParam().rhs_op.symbol << "' requires parenthesis"; + } EXPECT_EQ(p->error(), expected.str()); } } diff --git a/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc b/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc index f7f9a87f89..ec6561f1b5 100644 --- a/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc +++ b/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc @@ -266,7 +266,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) { EXPECT_TRUE(e.errored); EXPECT_EQ(e.value, nullptr); ASSERT_TRUE(p->has_error()); - EXPECT_EQ(p->error(), "1:12: expected '>' for bitcast expression"); + EXPECT_EQ(p->error(), "1:8: missing closing '>' for bitcast expression"); } TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingType) { @@ -319,5 +319,18 @@ TEST_F(ParserImplTest, PrimaryExpression_bitcast_InvalidExpression) { EXPECT_EQ(p->error(), "1:14: unable to parse expression"); } +TEST_F(ParserImplTest, PrimaryExpression_Template) { + auto p = parser("a()"); + auto e = p->primary_expression(); + EXPECT_FALSE(e.matched); + EXPECT_TRUE(e.errored); + EXPECT_EQ(e.value, nullptr); + ASSERT_TRUE(p->has_error()); + EXPECT_EQ(p->error(), + "1:2: '<' treated as the start of a template argument list, which is not supported " + "for user-declared types or functions. If you intended less-than, wrap the " + "expression in parentheses"); +} + } // namespace } // namespace tint::reader::wgsl diff --git a/src/tint/reader/wgsl/parser_impl_test.cc b/src/tint/reader/wgsl/parser_impl_test.cc index 21efd2f4f2..6df73c4d66 100644 --- a/src/tint/reader/wgsl/parser_impl_test.cc +++ b/src/tint/reader/wgsl/parser_impl_test.cc @@ -154,7 +154,7 @@ TEST_F(ParserImplTest, Peek_PastPlaceholder) { auto& n = p->next(); ASSERT_TRUE(n.Is(Token::Type::kGreaterThanEqual)); EXPECT_TRUE(p->peek_is(Token::Type::kVec2)) << "expected: vec2 got: " << p->peek().to_name(); - EXPECT_TRUE(p->peek_is(Token::Type::kLessThan, 1)) + EXPECT_TRUE(p->peek_is(Token::Type::kTemplateArgsLeft, 1)) << "expected: < got: " << p->peek(1).to_name(); } @@ -163,10 +163,10 @@ TEST_F(ParserImplTest, Peek_MultiplePlaceholder) { auto& n = p->next(); ASSERT_TRUE(n.Is(Token::Type::kGreaterThanEqual)); EXPECT_TRUE(p->peek_is(Token::Type::kGreaterThanEqual)) - << "expected: <= got: " << p->peek().to_name(); + << "expected: >= got: " << p->peek().to_name(); EXPECT_TRUE(p->peek_is(Token::Type::kVec2, 1)) << "expected: vec2 got: " << p->peek(1).to_name(); - EXPECT_TRUE(p->peek_is(Token::Type::kLessThan, 2)) + EXPECT_TRUE(p->peek_is(Token::Type::kTemplateArgsLeft, 2)) << "expected: < got: " << p->peek(2).to_name(); } diff --git a/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc b/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc index 43d4ada208..5db4e48cca 100644 --- a/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc +++ b/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc @@ -126,7 +126,8 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) { EXPECT_EQ(t.value, nullptr); EXPECT_FALSE(t.matched); EXPECT_TRUE(t.errored); - EXPECT_EQ(p->error(), "1:11: expected '<' for sampled texture type"); + EXPECT_EQ(p->error(), + "1:11: expected '< (opening template argument list)' for sampled texture type"); } TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) { @@ -136,7 +137,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) { EXPECT_EQ(t.value, nullptr); EXPECT_FALSE(t.matched); EXPECT_TRUE(t.errored); - EXPECT_EQ(p->error(), "1:15: expected '>' for sampled texture type"); + EXPECT_EQ(p->error(), "1:11: missing closing '>' for sampled texture type"); } TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_I32) { @@ -169,7 +170,8 @@ TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingLessThan) EXPECT_EQ(t.value, nullptr); EXPECT_FALSE(t.matched); EXPECT_TRUE(t.errored); - EXPECT_EQ(p->error(), "1:24: expected '<' for multisampled texture type"); + EXPECT_EQ(p->error(), + "1:24: expected '< (opening template argument list)' for multisampled texture type"); } TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingGreaterThan) { @@ -178,7 +180,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingGreaterTha EXPECT_EQ(t.value, nullptr); EXPECT_FALSE(t.matched); EXPECT_TRUE(t.errored); - EXPECT_EQ(p->error(), "1:28: expected '>' for multisampled texture type"); + EXPECT_EQ(p->error(), "1:24: missing closing '>' for multisampled texture type"); } TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dRg32Float) { @@ -261,7 +263,8 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan) { EXPECT_EQ(t.value, nullptr); EXPECT_FALSE(t.matched); EXPECT_TRUE(t.errored); - EXPECT_EQ(p->error(), "1:19: expected '<' for storage texture type"); + EXPECT_EQ(p->error(), + "1:19: expected '< (opening template argument list)' for storage texture type"); } TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingGreaterThan) { @@ -270,7 +273,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingGreaterThan) { EXPECT_EQ(t.value, nullptr); EXPECT_FALSE(t.matched); EXPECT_TRUE(t.errored); - EXPECT_EQ(p->error(), "1:33: expected '>' for storage texture type"); + EXPECT_EQ(p->error(), "1:19: missing closing '>' for storage texture type"); } } // namespace diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc index 1d5425503b..9787d5e202 100644 --- a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc +++ b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc @@ -139,7 +139,7 @@ TEST_P(VecMissingGreaterThanTest, Handles_Missing_GreaterThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:9: expected '>' for vector"); + ASSERT_EQ(p->error(), "1:5: missing closing '>' for vector"); } INSTANTIATE_TEST_SUITE_P(ParserImplTest, VecMissingGreaterThanTest, @@ -222,7 +222,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration"); + ASSERT_EQ(p->error(), "1:5: expected '< (opening template argument list)' for ptr declaration"); } TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterType) { @@ -232,7 +232,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterType) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration"); + ASSERT_EQ(p->error(), "1:4: missing closing '>' for ptr declaration"); } TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterAccess) { @@ -242,7 +242,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterAccess) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration"); + ASSERT_EQ(p->error(), "1:4: missing closing '>' for ptr declaration"); } TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAddressSpace) { @@ -262,7 +262,8 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAccess) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration"); + ASSERT_EQ(p->error(), + "1:19: expected '> (closing template argument list)' for ptr declaration"); } TEST_F(ParserImplTest, TypeDecl_Ptr_MissingAddressSpace) { @@ -370,7 +371,8 @@ TEST_F(ParserImplTest, TypeDecl_Atomic_MissingLessThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:8: expected '<' for atomic declaration"); + ASSERT_EQ(p->error(), + "1:8: expected '< (opening template argument list)' for atomic declaration"); } TEST_F(ParserImplTest, TypeDecl_Atomic_MissingGreaterThan) { @@ -380,7 +382,7 @@ TEST_F(ParserImplTest, TypeDecl_Atomic_MissingGreaterThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:11: expected '>' for atomic declaration"); + ASSERT_EQ(p->error(), "1:7: missing closing '>' for atomic declaration"); } TEST_F(ParserImplTest, TypeDecl_Atomic_MissingType) { @@ -561,7 +563,7 @@ TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:10: expected '>' for array declaration"); + ASSERT_EQ(p->error(), "1:6: missing closing '>' for array declaration"); } TEST_F(ParserImplTest, TypeDecl_Array_MissingComma) { @@ -571,7 +573,8 @@ TEST_F(ParserImplTest, TypeDecl_Array_MissingComma) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:11: expected '>' for array declaration"); + ASSERT_EQ(p->error(), + "1:11: expected '> (closing template argument list)' for array declaration"); } struct MatrixData { @@ -623,7 +626,7 @@ TEST_P(MatrixMissingGreaterThanTest, Handles_Missing_GreaterThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:11: expected '>' for matrix"); + ASSERT_EQ(p->error(), "1:7: missing closing '>' for matrix"); } INSTANTIATE_TEST_SUITE_P(ParserImplTest, MatrixMissingGreaterThanTest, diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc index f2ab1725c0..2714bf8237 100644 --- a/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc +++ b/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc @@ -130,7 +130,7 @@ TEST_P(TypeDeclWithoutIdent_VecMissingGreaterThanTest, Handles_Missing_GreaterTh EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:9: expected '>' for vector"); + ASSERT_EQ(p->error(), "1:5: missing closing '>' for vector"); } INSTANTIATE_TEST_SUITE_P(ParserImplTest, TypeDeclWithoutIdent_VecMissingGreaterThanTest, @@ -213,7 +213,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingLessThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration"); + ASSERT_EQ(p->error(), "1:5: expected '< (opening template argument list)' for ptr declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingGreaterThanAfterType) { @@ -223,7 +223,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingGreaterThanAfterType) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration"); + ASSERT_EQ(p->error(), "1:4: missing closing '>' for ptr declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingGreaterThanAfterAccess) { @@ -233,7 +233,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingGreaterThanAfterAccess) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration"); + ASSERT_EQ(p->error(), "1:4: missing closing '>' for ptr declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterAddressSpace) { @@ -253,7 +253,8 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterAccess) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration"); + ASSERT_EQ(p->error(), + "1:19: expected '> (closing template argument list)' for ptr declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingAddressSpace) { @@ -361,7 +362,8 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Atomic_MissingLessThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:8: expected '<' for atomic declaration"); + ASSERT_EQ(p->error(), + "1:8: expected '< (opening template argument list)' for atomic declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Atomic_MissingGreaterThan) { @@ -371,7 +373,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Atomic_MissingGreaterThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:11: expected '>' for atomic declaration"); + ASSERT_EQ(p->error(), "1:7: missing closing '>' for atomic declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Atomic_MissingType) { @@ -552,7 +554,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Array_MissingGreaterThan) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:10: expected '>' for array declaration"); + ASSERT_EQ(p->error(), "1:6: missing closing '>' for array declaration"); } TEST_F(ParserImplTest, TypeDeclWithoutIdent_Array_MissingComma) { @@ -562,7 +564,8 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Array_MissingComma) { EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:11: expected '>' for array declaration"); + ASSERT_EQ(p->error(), + "1:11: expected '> (closing template argument list)' for array declaration"); } struct MatrixData { @@ -615,7 +618,7 @@ TEST_P(TypeDeclWithoutIdent_MatrixMissingGreaterThanTest, Handles_Missing_Greate EXPECT_FALSE(t.matched); ASSERT_EQ(t.value, nullptr); ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:11: expected '>' for matrix"); + ASSERT_EQ(p->error(), "1:7: missing closing '>' for matrix"); } INSTANTIATE_TEST_SUITE_P(ParserImplTest, TypeDeclWithoutIdent_MatrixMissingGreaterThanTest,