From 4dd5665502ad7a78af3311cd11024d2537f280ea Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Thu, 29 Oct 2020 13:05:52 +0000 Subject: [PATCH] Add tests for all reachable parser errors These are _mostly_ covered in the over various test files, but unlike those, these new tests always parse from the root translation unit. These new tests also use a new testing class which may be extended to verify error output for different error styles (verbosity, colors, etc). Change-Id: I105488f9b16d90279af4cc418a1c845b6e239e9e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31263 Commit-Queue: Ben Clayton Commit-Queue: dan sinclair Reviewed-by: dan sinclair --- BUILD.gn | 1 + src/CMakeLists.txt | 1 + src/reader/wgsl/parser_impl_error_msg_test.cc | 784 ++++++++++++++++++ 3 files changed, 786 insertions(+) create mode 100644 src/reader/wgsl/parser_impl_error_msg_test.cc diff --git a/BUILD.gn b/BUILD.gn index 103c94169b..0e5ccc1681 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -914,6 +914,7 @@ source_set("tint_unittests_wgsl_reader_src") { "src/reader/wgsl/parser_impl_else_stmt_test.cc", "src/reader/wgsl/parser_impl_elseif_stmt_test.cc", "src/reader/wgsl/parser_impl_equality_expression_test.cc", + "src/reader/wgsl/parser_impl_error_msg_test.cc", "src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc", "src/reader/wgsl/parser_impl_for_stmt_test.cc", "src/reader/wgsl/parser_impl_function_decl_test.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7a04fc7333..95f4160baf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -450,6 +450,7 @@ if(${TINT_BUILD_WGSL_READER}) reader/wgsl/parser_impl_else_stmt_test.cc reader/wgsl/parser_impl_elseif_stmt_test.cc reader/wgsl/parser_impl_equality_expression_test.cc + reader/wgsl/parser_impl_error_msg_test.cc reader/wgsl/parser_impl_exclusive_or_expression_test.cc reader/wgsl/parser_impl_for_stmt_test.cc reader/wgsl/parser_impl_function_decl_test.cc diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc new file mode 100644 index 0000000000..075f6562f6 --- /dev/null +++ b/src/reader/wgsl/parser_impl_error_msg_test.cc @@ -0,0 +1,784 @@ +// Copyright 2020 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gtest/gtest.h" +#include "src/reader/wgsl/parser_impl.h" +#include "src/reader/wgsl/parser_impl_test_helper.h" + +namespace tint { +namespace reader { +namespace wgsl { +namespace { + +class ParserImplErrorTest : public ParserImplTest { + public: + void expect(const char* source, const char* expected) { + auto* p = parser(source); + EXPECT_EQ(p->Parse(), false); + EXPECT_EQ(p->has_error(), true); + EXPECT_EQ(p->error(), expected); + } +}; + +TEST_F(ParserImplErrorTest, AdditiveInvalidExpr) { + expect("fn f() -> void { return 1.0 + <; }", + "1:31: unable to parse right side of + expression"); +} + +TEST_F(ParserImplErrorTest, AndInvalidExpr) { + expect("fn f() -> void { return 1 & >; }", + "1:29: unable to parse right side of & expression"); +} + +TEST_F(ParserImplErrorTest, ArrayIndexExprInvalidExpr) { + expect("fn f() -> void { x = y[^]; }", + "1:24: unable to parse expression inside []"); +} + +TEST_F(ParserImplErrorTest, ArrayIndexExprMissingRBracket) { + expect("fn f() -> void { x = y[1; }", "1:25: missing ] for array accessor"); +} + +TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment) { + expect("fn f() -> void { a; }", "1:19: missing = for assignment"); +} + +TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment2) { + expect("fn f() -> void { a : i32; }", "1:20: missing = for assignment"); +} + +TEST_F(ParserImplErrorTest, AssignmentStmtMissingSemicolon) { + expect("fn f() -> void { a = 1 }", "1:24: missing ;"); +} + +TEST_F(ParserImplErrorTest, AssignmentStmtInvalidRHS) { + expect("fn f() -> void { a = >; }", + "1:22: unable to parse right side of assignment"); +} + +TEST_F(ParserImplErrorTest, BitcastExprMissingLessThan) { + expect("fn f() -> void { x = bitcast(y); }", + "1:29: missing < for bitcast expression"); +} + +TEST_F(ParserImplErrorTest, BitcastExprMissingGreaterThan) { + expect("fn f() -> void { x = bitcast for bitcast expression"); +} + +TEST_F(ParserImplErrorTest, BitcastExprMissingType) { + expect("fn f() -> void { x = bitcast<>(y); }", + "1:30: missing type for bitcast expression"); +} + +TEST_F(ParserImplErrorTest, BreakStmtMissingSemicolon) { + expect("fn f() -> void { loop { break } }", "1:31: missing ;"); +} + +TEST_F(ParserImplErrorTest, CallExprMissingRParen) { + expect("fn f() -> void { x = f(1.; }", "1:26: missing ) for call expression"); +} + +TEST_F(ParserImplErrorTest, CallStmtMissingRParen) { + expect("fn f() -> void { f(1.; }", "1:22: missing ) for call statement"); +} + +TEST_F(ParserImplErrorTest, CallStmtInvalidArgument0) { + expect("fn f() -> void { f(<); }", + "1:20: unable to parse argument expression"); +} + +TEST_F(ParserImplErrorTest, CallStmtInvalidArgument1) { + expect("fn f() -> void { f(1.0, <); }", + "1:25: unable to parse argument expression after comma"); +} + +TEST_F(ParserImplErrorTest, CallStmtMissingSemicolon) { + expect("fn f() -> void { f() }", "1:22: missing ;"); +} + +TEST_F(ParserImplErrorTest, ConstructorExprMissingLParen) { + expect("fn f() -> void { x = vec21,2); }", + "1:31: missing ( for type constructor"); +} + +TEST_F(ParserImplErrorTest, ConstructorExprMissingRParen) { + expect("fn f() -> void { x = vec2(1,2; }", + "1:35: missing ) for type constructor"); +} + +TEST_F(ParserImplErrorTest, ConstVarStmtInvalid) { + expect("fn f() -> void { const >; }", + "1:24: unable to parse variable declaration"); +} + +TEST_F(ParserImplErrorTest, ConstVarStmtMissingAssignment) { + expect("fn f() -> void { const a : i32; }", + "1:31: missing = for constant declaration"); +} + +TEST_F(ParserImplErrorTest, ConstVarStmtMissingConstructor) { + expect("fn f() -> void { const a : i32 = >; }", + "1:34: missing constructor for const declaration"); +} + +TEST_F(ParserImplErrorTest, ContinueStmtMissingSemicolon) { + expect("fn f() -> void { loop { continue } }", "1:34: missing ;"); +} + +TEST_F(ParserImplErrorTest, DiscardStmtMissingSemicolon) { + expect("fn f() -> void { discard }", "1:26: missing ;"); +} + +TEST_F(ParserImplErrorTest, EqualityInvalidExpr) { + expect("fn f() -> void { return 1 == >; }", + "1:30: unable to parse right side of == expression"); +} + +TEST_F(ParserImplErrorTest, ForLoopInitializerMissingSemicolon) { + expect("fn f() -> void { for (var i : i32 = 0 i < 8; i=i+1) {} }", + "1:39: missing ';' after initializer in for loop"); +} + +TEST_F(ParserImplErrorTest, ForLoopConditionMissingSemicolon) { + expect("fn f() -> void { for (var i : i32 = 0; i < 8 i=i+1) {} }", + "1:46: missing ';' after condition in for loop"); +} + +TEST_F(ParserImplErrorTest, ForLoopMissingLParen) { + expect("fn f() -> void { for var i : i32 = 0; i < 8; i=i+1) {} }", + "1:22: missing for loop ("); +} + +TEST_F(ParserImplErrorTest, ForLoopMissingRParen) { + expect("fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1 {} }", + "1:53: missing for loop )"); +} + +TEST_F(ParserImplErrorTest, ForLoopMissingLBrace) { + expect("fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1) } }", + "1:54: missing for loop {"); +} + +TEST_F(ParserImplErrorTest, ForLoopMissingRBrace) { + expect("fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1) {", + "1:55: missing for loop }"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclInvalid) { + expect("[[stage(vertex)]] x;", "1:19: error parsing function declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoMissingEnd) { + expect("[[stage(vertex) fn f() -> void {}", + "1:17: missing ]] for function decorations"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoStageMissingLParen) { + expect("[[stage vertex]] fn f() -> void {}", + "1:9: missing ( for stage decoration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoStageMissingRParen) { + expect("[[stage(vertex]] fn f() -> void {}", + "1:15: missing ) for stage decoration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoStageInvalid) { + expect("[[stage(x)]] fn f() -> void {}", + "1:9: invalid value for stage decoration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeMissingLParen) { + expect("[[workgroup_size 1]] fn f() -> void {}", + "1:18: missing ( for workgroup_size"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeMissingRParen) { + expect("[[workgroup_size(1]] fn f() -> void {}", + "1:19: missing ) for workgroup_size"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeXInvalid) { + expect("[[workgroup_size(x)]] fn f() -> void {}", + "1:18: missing x value for workgroup_size"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeXNegative) { + expect("[[workgroup_size(-1)]] fn f() -> void {}", + "1:18: invalid value for workgroup_size x parameter"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeYInvalid) { + expect("[[workgroup_size(1, x)]] fn f() -> void {}", + "1:21: missing y value for workgroup_size"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeYNegative) { + expect("[[workgroup_size(1, -1)]] fn f() -> void {}", + "1:21: invalid value for workgroup_size y parameter"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeZInvalid) { + expect("[[workgroup_size(1, 2, x)]] fn f() -> void {}", + "1:24: missing z value for workgroup_size"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclDecoWorkgroupSizeZNegative) { + expect("[[workgroup_size(1, 2, -1)]] fn f() -> void {}", + "1:24: invalid value for workgroup_size z parameter"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclMissingIdentifier) { + expect("fn () -> void {}", "1:4: missing identifier for function"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclMissingLParen) { + expect("fn f) -> void {}", "1:5: missing ( for function declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclMissingRParen) { + expect("fn f( -> void {}", "1:7: missing ) for function declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclMissingArrow) { + expect("fn f() void {}", "1:8: missing -> for function declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclInvalidReturnType) { + expect("fn f() -> 1 {}", "1:11: unable to determine function return type"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclParamMissingColon) { + expect("fn f(x) -> void {}", "1:7: missing : for identifier declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclParamInvalidType) { + expect("fn f(x : 1) -> void {}", + "1:10: invalid type for identifier declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclParamMissing) { + expect("fn f(x : i32, ) -> void {}", + "1:13: found , but no variable declaration"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclMissingLBrace) { + expect("fn f() -> void }", "1:16: missing {"); +} + +TEST_F(ParserImplErrorTest, FunctionDeclMissingRBrace) { + expect("fn f() -> void {", "1:17: missing }"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstInvalidIdentifier) { + expect("const ^ : i32 = 1;", + "1:7: error parsing constant variable identifier"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstMissingSemicolon) { + expect("const i : i32 = 1", "1:18: missing ';' for constant declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstMissingLParen) { + expect("const i : vec2 = vec2;", + "1:32: missing ( for type constructor"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstMissingRParen) { + expect("const i : vec2 = vec2(1., 2.;", + "1:39: missing ) for type constructor"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstMissingAssignment) { + expect("const i : vec2;", "1:20: missing = for const declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstBadConstLiteral) { + expect("const i : vec2 = vec2(!);", + "1:33: unable to parse const literal"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstExprMaxDepth) { + std::stringstream out; + out << "const i : i32 = "; + for (size_t i = 0; i < 200; i++) { + out << "f32("; + } + out << "1.0"; + for (size_t i = 0; i < 200; i++) { + out << ")"; + } + out << ";"; + expect(out.str().c_str(), "1:533: max const_expr depth reached"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstExprMissingLParen) { + expect("const i : vec2 = vec2 1, 2);", + "1:33: missing ( for type constructor"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclConstExprMissingRParen) { + expect("const i : vec2 = vec2(1, 2;", + "1:37: missing ) for type constructor"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureMissingLessThan) { + expect("var x : texture_sampled_1d;", + "1:28: missing '<' for sampled texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureMissingGreaterThan) { + expect("var x : texture_sampled_1d' for sampled texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureInvalidSubtype) { + expect("var x : texture_sampled_1d<1>;", + "1:28: invalid subtype for sampled texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclMultisampledTextureMissingLessThan) { + expect("var x : texture_multisampled_2d;", + "1:33: missing '<' for multisampled texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclMultisampledTextureMissingGreaterThan) { + expect("var x : texture_multisampled_2d' for multisampled texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclMultisampledTextureInvalidSubtype) { + expect("var x : texture_multisampled_2d<1>;", + "1:33: invalid subtype for multisampled texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingLessThan) { + expect("var x : texture_ro_2d;", + "1:23: missing '<' for storage texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingGreaterThan) { + expect("var x : texture_ro_2d' for storage texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingInvalidSubtype) { + expect("var x : texture_ro_2d<1>;", + "1:23: invalid format for storage texture type"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructDecoMissingStruct) { + expect("[[block]];", "1:10: missing struct declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructDecoMissingEnd) { + expect("[[block struct {};", "1:9: missing ]] for struct decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingIdentifier) { + expect("struct {};", "1:8: missing identifier for struct declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingSemicolon) { + expect("struct S {}", "1:12: missing ';' for struct declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingLBrace) { + expect("struct S };", "1:10: missing { for struct declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingRBrace) { + expect("struct S { i : i32;", "1:20: missing } for struct declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberDecoEmpty) { + expect("struct S { [[]] i : i32; };", + "1:14: empty struct member decoration found"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberDecoMissingEnd) { + expect("struct S { [[ i : i32; };", + "1:15: missing ]] for struct member decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberInvalidIdentifier) { + expect("struct S { 1 : i32; };", "1:12: invalid identifier declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberMissingSemicolon) { + expect("struct S { i : i32 };", "1:20: missing ; for struct member"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberOffsetMissingLParen) { + expect("struct S { [[offset 1)]] i : i32 };", "1:21: missing ( for offset"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberOffsetMissingRParen) { + expect("struct S { [[offset(1]] i : i32 };", "1:22: missing ) for offset"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberOffsetInvaldValue) { + expect("struct S { [[offset(x)]] i : i32 };", + "1:21: invalid value for offset decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclStructMemberOffsetNegativeValue) { + expect("struct S { [[offset(-2)]] i : i32 };", + "1:21: offset value must be >= 0"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclTypeAliasMissingIdentifier) { + expect("type 1 = f32;", "1:6: missing identifier for type alias"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclTypeAliasInvalidType) { + expect("type meow = 1;", "1:13: invalid type alias"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclTypeAliasMissingAssignment) { + expect("type meow f32", "1:11: missing = for type alias"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclTypeAliasMissingSemicolon) { + expect("type meow = f32", "1:16: missing ';' for type alias"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclTypeInvalid) { + expect("var x : fish;", "1:9: unknown constructed type 'fish'"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclTypeDecoInvalid) { + expect("var x : [[]] i32;", "1:9: invalid type for identifier declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingLessThan) { + expect("var i : array;", "1:14: missing < for array declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingGreaterThan) { + expect("var i : array for array declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayDecoNotArray) { + expect("var i : [[stride(1)]] i32;", + "1:23: found array decoration but no array"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayDecoMissingEnd) { + expect("var i : [[stride(1) array;", + "1:21: missing ]] for array decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayDecoStrideMissingLParen) { + expect("var i : [[stride 1)]] array;", + "1:18: missing ( for stride attribute"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayDecoStrideMissingRParen) { + expect("var i : [[stride(1]] array;", + "1:19: missing ) for stride attribute"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayDecoStrideInvalid) { + expect("var i : [[stride(x)]] array;", + "1:18: missing value for stride decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayDecoStrideNegative) { + expect("var i : [[stride(-1)]] array;", + "1:18: invalid stride value: -1"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingType) { + expect("var i : array<1, 3>;", "1:15: invalid type for array declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayInvalidSize) { + expect("var i : array;", "1:20: missing size of array declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarArrayNegativeSize) { + expect("var i : array;", "1:20: invalid size for array declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoListEmpty) { + expect("[[]] var i : i32;", "1:3: empty variable decoration list"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoListInvalid) { + expect("[[location(1), meow]] var i : i32;", + "1:16: missing variable decoration after comma"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoListMissingComma) { + expect("[[location(1) set(2)]] var i : i32;", + "1:15: missing comma in variable decoration list"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoListMissingEnd) { + expect("[[location(1) meow]] var i : i32;", + "1:15: missing ]] for variable decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoLocationMissingLParen) { + expect("[[location 1]] var i : i32;", + "1:12: missing ( for location decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoLocationMissingRParen) { + expect("[[location (1]] var i : i32;", + "1:14: missing ) for location decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoLocationInvalidValue) { + expect("[[location(x)]] var i : i32;", + "1:12: invalid value for location decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBuiltinMissingLParen) { + expect("[[builtin position]] var i : i32;", + "1:11: missing ( for builtin decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBuiltinMissingRParen) { + expect("[[builtin(position]] var i : i32;", + "1:19: missing ) for builtin decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBuiltinInvalidIdentifer) { + expect("[[builtin(1)]] var i : i32;", + "1:11: expected identifier for builtin"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBuiltinInvalidValue) { + expect("[[builtin(x)]] var i : i32;", + "1:11: invalid value for builtin decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBindingMissingLParen) { + expect("[[binding 1]] var i : i32;", + "1:11: missing ( for binding decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBindingMissingRParen) { + expect("[[binding(1]] var i : i32;", + "1:12: missing ) for binding decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBindingInvalidValue) { + expect("[[binding(x)]] var i : i32;", + "1:11: invalid value for binding decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoSetMissingLParen) { + expect("[[set 1]] var i : i32;", "1:7: missing ( for set decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoSetMissingRParen) { + expect("[[set(1]] var i : i32;", "1:8: missing ) for set decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBindingSetValue) { + expect("[[set(x)]] var i : i32;", "1:7: invalid value for set decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarInvalidIdentifier) { + expect("var ^ : mat4x4;", "1:5: invalid identifier declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingLessThan) { + expect("var i : mat4x4;", "1:15: missing < for matrix"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) { + expect("var i : mat4x4 for matrix"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingType) { + expect("var i : mat4x4<1>;", "1:16: unable to determine subtype for matrix"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarMissingSemicolon) { + expect("var i : i32", "1:12: missing ';' for variable declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingLessThan) { + expect("var i : ptr;", "1:12: missing < for ptr declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingGreaterThan) { + expect("var i : ptr for ptr declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingComma) { + expect("var i : ptr;", "1:16: missing , for ptr declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingStorageClass) { + expect("var i : ptr;", + "1:13: missing storage class for ptr declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingType) { + expect("var i : ptr;", "1:17: missing type for ptr declaration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) { + expect("var i : i32", + "1:5: invalid storage class for variable decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclMissingGThan) { + expect("var for variable decoration"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingLessThan) { + expect("var i : vec3;", "1:13: missing < for vector"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingGreaterThan) { + expect("var i : vec3 for vector"); +} + +TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingType) { + expect("var i : vec3<1>;", "1:14: unable to determine subtype for vector"); +} + +TEST_F(ParserImplErrorTest, IfStmtMissingLParen) { + expect("fn f() -> void { if true) {} }", "1:21: expected ("); +} + +TEST_F(ParserImplErrorTest, IfStmtMissingRParen) { + expect("fn f() -> void { if (true {} }", "1:27: expected )"); +} + +TEST_F(ParserImplErrorTest, IfStmtInvalidCond) { + expect("fn f() -> void { if (>) {} }", "1:22: unable to parse expression"); +} + +TEST_F(ParserImplErrorTest, LogicalAndInvalidExpr) { + expect("fn f() -> void { return 1 && >; }", + "1:30: unable to parse right side of && expression"); +} + +TEST_F(ParserImplErrorTest, LogicalOrInvalidExpr) { + expect("fn f() -> void { return 1 || >; }", + "1:30: unable to parse right side of || expression"); +} + +TEST_F(ParserImplErrorTest, LoopMissingLBrace) { + expect("fn f() -> void { loop } }", "1:23: missing { for loop"); +} + +TEST_F(ParserImplErrorTest, LoopMissingRBrace) { + expect("fn f() -> void { loop {", "1:24: missing } for loop"); +} + +TEST_F(ParserImplErrorTest, MemberExprMissingIdentifier) { + expect("fn f() -> void { x = a.; }", + "1:24: missing identifier for member accessor"); +} + +TEST_F(ParserImplErrorTest, MultiplicativeInvalidExpr) { + expect("fn f() -> void { return 1.0 * <; }", + "1:31: unable to parse right side of * expression"); +} + +TEST_F(ParserImplErrorTest, OrInvalidExpr) { + expect("fn f() -> void { return 1 | >; }", + "1:29: unable to parse right side of | expression"); +} + +TEST_F(ParserImplErrorTest, RelationalInvalidExpr) { + expect("fn f() -> void { return 1 < >; }", + "1:29: unable to parse right side of < expression"); +} + +TEST_F(ParserImplErrorTest, ReturnStmtMissingSemicolon) { + expect("fn f() -> void { return }", "1:25: missing ;"); +} + +TEST_F(ParserImplErrorTest, ShiftInvalidExpr) { + expect("fn f() -> void { return 1 << >; }", + "1:30: unable to parse right side of << expression"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtMissingLBrace) { + expect("fn f() -> void { switch(1) }", + "1:28: missing { for switch statement"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtMissingRBrace) { + expect("fn f() -> void { switch(1) {", + "1:29: missing } for switch statement"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtInvalidCase) { + expect("fn f() -> void { switch(1) { case ^: } }", + "1:35: unable to parse case selectors"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtInvalidCase2) { + expect("fn f() -> void { switch(1) { case false: } }", + "1:35: invalid case selector must be an integer value"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingColon) { + expect("fn f() -> void { switch(1) { case 1 {} } }", + "1:37: missing : for case statement"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingLBrace) { + expect("fn f() -> void { switch(1) { case 1: } } }", + "1:38: missing { for case statement"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingRBrace) { + expect("fn f() -> void { switch(1) { case 1: {", + "1:39: missing } for case statement"); +} + +TEST_F(ParserImplErrorTest, SwitchStmtCaseFallthroughMissingSemicolon) { + expect("fn f() -> void { switch(1) { case 1: { fallthrough } case 2: {} } }", + "1:52: missing ;"); +} + +TEST_F(ParserImplErrorTest, VarStmtMissingSemicolon) { + expect("fn f() -> void { var a : u32 }", "1:30: missing ;"); +} + +TEST_F(ParserImplErrorTest, VarStmtInvalidAssignment) { + expect("fn f() -> void { var a : u32 = >; }", + "1:32: missing constructor for variable declaration"); +} + +TEST_F(ParserImplErrorTest, UnaryInvalidExpr) { + expect("fn f() -> void { return !<; }", + "1:26: unable to parse right side of ! expression"); +} + +TEST_F(ParserImplErrorTest, UnexpectedToken) { + expect("unexpected", "1:1: invalid token (kIdentifier) encountered"); +} + +TEST_F(ParserImplErrorTest, XorInvalidExpr) { + expect("fn f() -> void { return 1 ^ >; }", + "1:29: unable to parse right side of ^ expression"); +} + +} // namespace +} // namespace wgsl +} // namespace reader +} // namespace tint