tint/reader/wgsl: Use ClassifyTemplateArguments()

For parsing.

Bug: tint:1810
Change-Id: I189d06136e79615d39c842aaa9ad58595f80283e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/117210
Kokoro: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2023-01-24 19:28:14 +00:00 committed by Dawn LUCI CQ
parent ef5434dcd1
commit 355b70d2be
9 changed files with 147 additions and 80 deletions

View File

@ -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<const ast::Type*> 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<const ast::Type*> 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<const ast::Type*> ParserImpl::texture_and_sampler_types() {
if (storage.matched) {
const char* use = "storage texture type";
using StorageTextureInfo = std::pair<tint::type::TexelFormat, tint::type::Access>;
auto params = expect_lt_gt_block(use, [&]() -> Expect<StorageTextureInfo> {
auto params = expect_template_arg_block(use, [&]() -> Expect<StorageTextureInfo> {
auto format = expect_texel_format(use);
if (format.errored) {
return Failure::kErrored;
@ -1129,7 +1131,8 @@ Maybe<const ast::Type*> 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<const ast::Type*> 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<const ast::Type*> 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<const ast::Type*> {
auto subtype = expect_template_arg_block(use, [&]() -> Expect<const ast::Type*> {
auto sc = expect_address_space(use);
if (sc.errored) {
return Failure::kErrored;
@ -1297,7 +1302,7 @@ Expect<const ast::Type*> ParserImpl::expect_type_specifier_pointer(const Source&
Expect<const ast::Type*> 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<const ast::Type*> ParserImpl::expect_type_specifier_atomic(const Source&
// LESS_THAN type_specifier GREATER_THAN
Expect<const ast::Type*> 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<const ast::Type*> 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<TypeAndSize> {
auto type_size = expect_template_arg_block(use, [&]() -> Expect<TypeAndSize> {
auto type = expect_type(use);
if (type.errored) {
return Failure::kErrored;
@ -1361,7 +1362,7 @@ Expect<const ast::Type*> ParserImpl::expect_type_specifier_array(const Source& s
Expect<const ast::Type*> 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<const ast::Expression*> 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<const ast::Expression*> 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<ast::IdentifierExpression>(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<F>(body));
}
template <typename F, typename T>
T ParserImpl::expect_template_arg_block(std::string_view use, F&& body) {
return expect_block(Token::Type::kTemplateArgsLeft, Token::Type::kTemplateArgsRight, use,
std::forward<F>(body));
}
template <typename F, typename T>
T ParserImpl::sync(Token::Type tok, F&& body) {
if (parse_depth_ >= kMaxParseDepth) {

View File

@ -799,6 +799,16 @@ class ParserImpl {
/// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
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<Result>()` or `Maybe<Result>()`.
/// @return the value returned by `body` if no errors are raised, otherwise an Expect with error
/// state.
template <typename F, typename T = ReturnType<F>>
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

View File

@ -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<u32(y); }",
R"(test.wgsl:1:25 error: expected '>' for bitcast expression
R"(test.wgsl:1:21 error: missing closing '>' for bitcast expression
fn f() { x = bitcast<u32(y); }
^
^
)");
}
@ -659,8 +660,9 @@ TEST_F(ParserImplErrorTest, GlobalDeclInvalidAttribute) {
}
TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureMissingLessThan) {
EXPECT("var x : texture_1d;",
R"(test.wgsl:1:19 error: expected '<' for sampled texture type
EXPECT(
"var x : texture_1d;",
R"(test.wgsl:1:19 error: expected '< (opening template argument list)' for sampled texture type
var x : texture_1d;
^
)");
@ -668,9 +670,9 @@ var x : texture_1d;
TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureMissingGreaterThan) {
EXPECT("var x : texture_1d<f32;",
R"(test.wgsl:1:23 error: expected '>' for sampled texture type
R"(test.wgsl:1:19 error: missing closing '>' for sampled texture type
var x : texture_1d<f32;
^
^
)");
}
@ -683,8 +685,9 @@ var x : texture_1d<1>;
}
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<f32;",
R"(test.wgsl:1:36 error: expected '>' for multisampled texture type
R"(test.wgsl:1:32 error: missing closing '>' for multisampled texture type
var x : texture_multisampled_2d<f32;
^
^
)");
}
@ -830,8 +833,9 @@ static_assert true static_assert true;
}
TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingLessThan) {
EXPECT("var x : texture_storage_2d;",
R"(test.wgsl:1:27 error: expected '<' for storage texture type
EXPECT(
"var x : texture_storage_2d;",
R"(test.wgsl:1:27 error: expected '< (opening template argument list)' for storage texture type
var x : texture_storage_2d;
^
)");
@ -839,9 +843,9 @@ var x : texture_storage_2d;
TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingGreaterThan) {
EXPECT("var x : texture_storage_2d<r32uint, read;",
R"(test.wgsl:1:41 error: expected '>' for storage texture type
R"(test.wgsl:1:27 error: missing closing '>' for storage texture type
var x : texture_storage_2d<r32uint, read;
^
^
)");
}
@ -993,9 +997,9 @@ type meow = f32
TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingGreaterThan) {
EXPECT("var i : array<u32, 3;",
R"(test.wgsl:1:21 error: expected '>' for array declaration
R"(test.wgsl:1:14 error: missing closing '>' for array declaration
var i : array<u32, 3;
^
^
)");
}
@ -1174,9 +1178,9 @@ var ^ : mat4x4;
}
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) {
EXPECT("var i : mat4x4<u32;", R"(test.wgsl:1:19 error: expected '>' for matrix
EXPECT("var i : mat4x4<u32;", R"(test.wgsl:1:15 error: missing closing '>' for matrix
var i : mat4x4<u32;
^
^
)");
}
@ -1196,8 +1200,9 @@ var i : i32
}
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingLessThan) {
EXPECT("var i : ptr;",
R"(test.wgsl:1:12 error: expected '<' for ptr declaration
EXPECT(
"var i : ptr;",
R"(test.wgsl:1:12 error: expected '< (opening template argument list)' for ptr declaration
var i : ptr;
^
)");
@ -1205,9 +1210,9 @@ var i : ptr;
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingGreaterThan) {
EXPECT("var i : ptr<private, u32;",
R"(test.wgsl:1:25 error: expected '>' for ptr declaration
R"(test.wgsl:1:12 error: missing closing '>' for ptr declaration
var i : ptr<private, u32;
^
^
)");
}
@ -1237,8 +1242,9 @@ var i : ptr<private, 1>;
}
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<u32 x;",
R"(test.wgsl:1:20 error: expected '>' for atomic declaration
R"(test.wgsl:1:15 error: missing closing '>' for atomic declaration
var i : atomic<u32 x;
^
^
)");
}
@ -1270,9 +1276,9 @@ var<private i : i32
}
TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingGreaterThan) {
EXPECT("var i : vec3<u32;", R"(test.wgsl:1:17 error: expected '>' for vector
EXPECT("var i : vec3<u32;", R"(test.wgsl:1:13 error: missing closing '>' for vector
var i : vec3<u32;
^
^
)");
}

View File

@ -463,6 +463,9 @@ struct Case {
bool should_parse;
};
static bool ParsedAsTemplateArgumentList(BinaryOperatorInfo lhs_op, BinaryOperatorInfo rhs_op) {
return lhs_op.bit == kOpLt && rhs_op.bit & (kOpGt | kOpGe | kOpShr);
}
static std::ostream& operator<<(std::ostream& o, const Case& c) {
return o << "a " << c.lhs_op.symbol << " b " << c.rhs_op.symbol << " c ";
}
@ -471,7 +474,8 @@ static std::vector<Case> Cases() {
std::vector<Case> 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());
}
}

View File

@ -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<b>()");
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

View File

@ -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();
}

View File

@ -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

View File

@ -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,

View File

@ -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,