resolver: Don't use ast to_str() methods
These return weird names that love the use of '__' and have little relation to WGSL. Improve the duplicate case error message. Clean up control_block_validation_test.cc by making used of the ProgramBuilder helpers. Bug: tint:1225 Change-Id: I8c4cf3943145cf8372c00d33ae0166c0c0bcbb8b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/66442 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com> Reviewed-by: James Price <jrprice@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
262210f12b
commit
11ed0db30d
|
@ -1105,18 +1105,46 @@ class ProgramBuilder {
|
||||||
/// @return `list`
|
/// @return `list`
|
||||||
ast::ExpressionList ExprList(ast::ExpressionList list) { return list; }
|
ast::ExpressionList ExprList(ast::ExpressionList list) { return list; }
|
||||||
|
|
||||||
|
/// @param source the source location for the literal
|
||||||
|
/// @param val the boolan value
|
||||||
|
/// @return a boolean literal with the given value
|
||||||
|
ast::BoolLiteral* Literal(const Source& source, bool val) {
|
||||||
|
return create<ast::BoolLiteral>(source, val);
|
||||||
|
}
|
||||||
|
|
||||||
/// @param val the boolan value
|
/// @param val the boolan value
|
||||||
/// @return a boolean literal with the given value
|
/// @return a boolean literal with the given value
|
||||||
ast::BoolLiteral* Literal(bool val) { return create<ast::BoolLiteral>(val); }
|
ast::BoolLiteral* Literal(bool val) { return create<ast::BoolLiteral>(val); }
|
||||||
|
|
||||||
|
/// @param source the source location for the literal
|
||||||
|
/// @param val the float value
|
||||||
|
/// @return a float literal with the given value
|
||||||
|
ast::FloatLiteral* Literal(const Source& source, f32 val) {
|
||||||
|
return create<ast::FloatLiteral>(source, val);
|
||||||
|
}
|
||||||
|
|
||||||
/// @param val the float value
|
/// @param val the float value
|
||||||
/// @return a float literal with the given value
|
/// @return a float literal with the given value
|
||||||
ast::FloatLiteral* Literal(f32 val) { return create<ast::FloatLiteral>(val); }
|
ast::FloatLiteral* Literal(f32 val) { return create<ast::FloatLiteral>(val); }
|
||||||
|
|
||||||
|
/// @param source the source location for the literal
|
||||||
|
/// @param val the unsigned int value
|
||||||
|
/// @return a ast::UintLiteral with the given value
|
||||||
|
ast::UintLiteral* Literal(const Source& source, u32 val) {
|
||||||
|
return create<ast::UintLiteral>(source, val);
|
||||||
|
}
|
||||||
|
|
||||||
/// @param val the unsigned int value
|
/// @param val the unsigned int value
|
||||||
/// @return a ast::UintLiteral with the given value
|
/// @return a ast::UintLiteral with the given value
|
||||||
ast::UintLiteral* Literal(u32 val) { return create<ast::UintLiteral>(val); }
|
ast::UintLiteral* Literal(u32 val) { return create<ast::UintLiteral>(val); }
|
||||||
|
|
||||||
|
/// @param source the source location for the literal
|
||||||
|
/// @param val the integer value
|
||||||
|
/// @return the ast::SintLiteral with the given value
|
||||||
|
ast::SintLiteral* Literal(const Source& source, i32 val) {
|
||||||
|
return create<ast::SintLiteral>(source, val);
|
||||||
|
}
|
||||||
|
|
||||||
/// @param val the integer value
|
/// @param val the integer value
|
||||||
/// @return the ast::SintLiteral with the given value
|
/// @return the ast::SintLiteral with the given value
|
||||||
ast::SintLiteral* Literal(i32 val) { return create<ast::SintLiteral>(val); }
|
ast::SintLiteral* Literal(i32 val) { return create<ast::SintLiteral>(val); }
|
||||||
|
@ -2071,16 +2099,44 @@ class ProgramBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ast::SwitchStatement with input expression and cases
|
/// Creates a ast::SwitchStatement with input expression and cases
|
||||||
|
/// @param source the source information
|
||||||
/// @param condition the condition expression initializer
|
/// @param condition the condition expression initializer
|
||||||
/// @param cases case statements
|
/// @param cases case statements
|
||||||
/// @returns the switch statement pointer
|
/// @returns the switch statement pointer
|
||||||
template <typename ExpressionInit, typename... Cases>
|
template <typename ExpressionInit, typename... Cases>
|
||||||
|
ast::SwitchStatement* Switch(const Source& source,
|
||||||
|
ExpressionInit&& condition,
|
||||||
|
Cases&&... cases) {
|
||||||
|
return create<ast::SwitchStatement>(
|
||||||
|
source, Expr(std::forward<ExpressionInit>(condition)),
|
||||||
|
ast::CaseStatementList{std::forward<Cases>(cases)...});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a ast::SwitchStatement with input expression and cases
|
||||||
|
/// @param condition the condition expression initializer
|
||||||
|
/// @param cases case statements
|
||||||
|
/// @returns the switch statement pointer
|
||||||
|
template <typename ExpressionInit,
|
||||||
|
typename... Cases,
|
||||||
|
typename = DisableIfSource<ExpressionInit>>
|
||||||
ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
|
ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
|
||||||
return create<ast::SwitchStatement>(
|
return create<ast::SwitchStatement>(
|
||||||
Expr(std::forward<ExpressionInit>(condition)),
|
Expr(std::forward<ExpressionInit>(condition)),
|
||||||
ast::CaseStatementList{std::forward<Cases>(cases)...});
|
ast::CaseStatementList{std::forward<Cases>(cases)...});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a ast::CaseStatement with input list of selectors, and body
|
||||||
|
/// @param source the source information
|
||||||
|
/// @param selectors list of selectors
|
||||||
|
/// @param body the case body
|
||||||
|
/// @returns the case statement pointer
|
||||||
|
ast::CaseStatement* Case(const Source& source,
|
||||||
|
ast::CaseSelectorList selectors,
|
||||||
|
ast::BlockStatement* body = nullptr) {
|
||||||
|
return create<ast::CaseStatement>(source, std::move(selectors),
|
||||||
|
body ? body : Block());
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a ast::CaseStatement with input list of selectors, and body
|
/// Creates a ast::CaseStatement with input list of selectors, and body
|
||||||
/// @param selectors list of selectors
|
/// @param selectors list of selectors
|
||||||
/// @param body the case body
|
/// @param body the case body
|
||||||
|
@ -2100,6 +2156,15 @@ class ProgramBuilder {
|
||||||
return Case(ast::CaseSelectorList{selector}, body);
|
return Case(ast::CaseSelectorList{selector}, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convenience function that creates a 'default' ast::CaseStatement
|
||||||
|
/// @param source the source information
|
||||||
|
/// @param body the case body
|
||||||
|
/// @returns the case statement pointer
|
||||||
|
ast::CaseStatement* DefaultCase(const Source& source,
|
||||||
|
ast::BlockStatement* body = nullptr) {
|
||||||
|
return Case(source, ast::CaseSelectorList{}, body);
|
||||||
|
}
|
||||||
|
|
||||||
/// Convenience function that creates a 'default' ast::CaseStatement
|
/// Convenience function that creates a 'default' ast::CaseStatement
|
||||||
/// @param body the case body
|
/// @param body the case body
|
||||||
/// @returns the case statement pointer
|
/// @returns the case statement pointer
|
||||||
|
|
|
@ -32,14 +32,8 @@ TEST_F(ResolverControlBlockValidationTest,
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(3.14f));
|
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(3.14f));
|
||||||
|
|
||||||
ast::CaseStatementList body;
|
auto* block = Block(Decl(var), Switch(Expr(Source{{12, 34}}, "a"), //
|
||||||
auto* block_default = Block();
|
DefaultCase()));
|
||||||
body.push_back(
|
|
||||||
create<ast::CaseStatement>(ast::CaseSelectorList{}, block_default));
|
|
||||||
|
|
||||||
auto* block =
|
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(
|
|
||||||
Expr(Source{Source::Location{12, 34}}, "a"), body));
|
|
||||||
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
|
@ -56,15 +50,9 @@ TEST_F(ResolverControlBlockValidationTest, SwitchWithoutDefault_Fail) {
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||||
|
|
||||||
ast::CaseSelectorList csl;
|
auto* block = Block(Decl(var), //
|
||||||
csl.push_back(Literal(1));
|
Switch(Source{{12, 34}}, "a", //
|
||||||
|
Case(Literal(1))));
|
||||||
ast::CaseStatementList body;
|
|
||||||
body.push_back(create<ast::CaseStatement>(csl, Block()));
|
|
||||||
|
|
||||||
auto* block =
|
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(
|
|
||||||
Source{Source::Location{12, 34}}, Expr("a"), body));
|
|
||||||
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
|
@ -82,24 +70,11 @@ TEST_F(ResolverControlBlockValidationTest, SwitchWithTwoDefault_Fail) {
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||||
|
|
||||||
ast::CaseStatementList switch_body;
|
auto* block = Block(Decl(var), //
|
||||||
ast::CaseSelectorList default_csl_1;
|
Switch("a", //
|
||||||
auto* block_default_1 = Block();
|
DefaultCase(), //
|
||||||
switch_body.push_back(
|
Case(Literal(1)), //
|
||||||
create<ast::CaseStatement>(default_csl_1, block_default_1));
|
DefaultCase(Source{{12, 34}})));
|
||||||
|
|
||||||
ast::CaseSelectorList csl_case_1;
|
|
||||||
csl_case_1.push_back(Literal(1));
|
|
||||||
auto* block_case_1 = Block();
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(csl_case_1, block_case_1));
|
|
||||||
|
|
||||||
ast::CaseSelectorList default_csl_2;
|
|
||||||
auto* block_default_2 = Block();
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(
|
|
||||||
Source{Source::Location{12, 34}}, default_csl_2, block_default_2));
|
|
||||||
|
|
||||||
auto* block =
|
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), switch_body));
|
|
||||||
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
|
@ -173,34 +148,36 @@ TEST_F(ResolverControlBlockValidationTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverControlBlockValidationTest, UnreachableCode_break) {
|
TEST_F(ResolverControlBlockValidationTest, UnreachableCode_break) {
|
||||||
// switch (a) {
|
// switch (1) {
|
||||||
// case 1: { break; var a : u32 = 2;}
|
// case 1: { break; var a : u32 = 2;}
|
||||||
// default: {}
|
// default: {}
|
||||||
// }
|
// }
|
||||||
auto* decl = Decl(Source{{12, 34}},
|
auto* decl = Decl(Source{{12, 34}},
|
||||||
Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)));
|
Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)));
|
||||||
|
|
||||||
WrapInFunction(Loop(Block(Switch(
|
WrapInFunction( //
|
||||||
Expr(1), Case(Literal(1), Block(create<ast::BreakStatement>(), decl)),
|
Loop(Block(Switch(1, //
|
||||||
DefaultCase()))));
|
Case(Literal(1), Block(Break(), decl)), //
|
||||||
|
DefaultCase()))));
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(), "12:34 error: code is unreachable");
|
EXPECT_EQ(r()->error(), "12:34 error: code is unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverControlBlockValidationTest, UnreachableCode_break_InBlocks) {
|
TEST_F(ResolverControlBlockValidationTest, UnreachableCode_break_InBlocks) {
|
||||||
// switch (a) {
|
// loop {
|
||||||
// case 1: { {{{break;}}} var a : u32 = 2;}
|
// switch (1) {
|
||||||
// default: {}
|
// case 1: { {{{break;}}} var a : u32 = 2;}
|
||||||
|
// default: {}
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
auto* decl = Decl(Source{{12, 34}},
|
auto* decl = Decl(Source{{12, 34}},
|
||||||
Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)));
|
Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)));
|
||||||
|
|
||||||
WrapInFunction(Loop(Block(Switch(
|
WrapInFunction(Loop(
|
||||||
Expr(1),
|
Block(Switch(1, //
|
||||||
Case(Literal(1),
|
Case(Literal(1), Block(Block(Block(Block(Break()))), decl)),
|
||||||
Block(Block(Block(Block(create<ast::BreakStatement>()))), decl)),
|
DefaultCase()))));
|
||||||
DefaultCase()))));
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(), "12:34 error: code is unreachable");
|
EXPECT_EQ(r()->error(), "12:34 error: code is unreachable");
|
||||||
|
@ -215,18 +192,10 @@ TEST_F(ResolverControlBlockValidationTest,
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||||
|
|
||||||
ast::CaseStatementList switch_body;
|
|
||||||
ast::CaseSelectorList csl;
|
|
||||||
csl.push_back(create<ast::UintLiteral>(1u));
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(
|
|
||||||
Source{Source::Location{12, 34}}, csl, Block()));
|
|
||||||
|
|
||||||
ast::CaseSelectorList default_csl;
|
|
||||||
auto* block_default = Block();
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(default_csl, block_default));
|
|
||||||
|
|
||||||
auto* block =
|
auto* block =
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), switch_body));
|
Block(Decl(var), Switch("a", //
|
||||||
|
Case(Source{{12, 34}}, {Literal(1u)}), //
|
||||||
|
DefaultCase()));
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
@ -244,18 +213,10 @@ TEST_F(ResolverControlBlockValidationTest,
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.u32(), ast::StorageClass::kNone, Expr(2u));
|
auto* var = Var("a", ty.u32(), ast::StorageClass::kNone, Expr(2u));
|
||||||
|
|
||||||
ast::CaseStatementList switch_body;
|
auto* block = Block(Decl(var), //
|
||||||
ast::CaseSelectorList csl;
|
Switch("a", //
|
||||||
csl.push_back(Literal(-1));
|
Case(Source{{12, 34}}, {Literal(-1)}), //
|
||||||
switch_body.push_back(create<ast::CaseStatement>(
|
DefaultCase()));
|
||||||
Source{Source::Location{12, 34}}, csl, Block()));
|
|
||||||
|
|
||||||
ast::CaseSelectorList default_csl;
|
|
||||||
auto* block_default = Block();
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(default_csl, block_default));
|
|
||||||
|
|
||||||
auto* block =
|
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), switch_body));
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
@ -268,72 +229,55 @@ TEST_F(ResolverControlBlockValidationTest,
|
||||||
NonUniqueCaseSelectorValueUint_Fail) {
|
NonUniqueCaseSelectorValueUint_Fail) {
|
||||||
// var a : u32 = 3;
|
// var a : u32 = 3;
|
||||||
// switch (a) {
|
// switch (a) {
|
||||||
// case 0: {}
|
// case 0u: {}
|
||||||
// case 2, 2: {}
|
// case 2u, 3u, 2u: {}
|
||||||
// default: {}
|
// default: {}
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.u32(), ast::StorageClass::kNone, Expr(3u));
|
auto* var = Var("a", ty.u32(), ast::StorageClass::kNone, Expr(3u));
|
||||||
|
|
||||||
ast::CaseStatementList switch_body;
|
auto* block = Block(Decl(var), //
|
||||||
ast::CaseSelectorList csl_1;
|
Switch("a", //
|
||||||
csl_1.push_back(create<ast::UintLiteral>(0u));
|
Case(Literal(0u)),
|
||||||
switch_body.push_back(create<ast::CaseStatement>(csl_1, Block()));
|
Case({
|
||||||
|
Literal(Source{{12, 34}}, 2u),
|
||||||
ast::CaseSelectorList csl_2;
|
Literal(3u),
|
||||||
csl_2.push_back(create<ast::UintLiteral>(2u));
|
Literal(Source{{56, 78}}, 2u),
|
||||||
csl_2.push_back(create<ast::UintLiteral>(2u));
|
}),
|
||||||
switch_body.push_back(create<ast::CaseStatement>(
|
DefaultCase()));
|
||||||
Source{Source::Location{12, 34}}, csl_2, Block()));
|
|
||||||
|
|
||||||
ast::CaseSelectorList default_csl;
|
|
||||||
auto* block_default = Block();
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(default_csl, block_default));
|
|
||||||
|
|
||||||
auto* block =
|
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), switch_body));
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
"12:34 error: a literal value must not appear more than once in "
|
"56:78 error: duplicate switch case '2'\n"
|
||||||
"the case selectors for a switch statement: '2u'");
|
"12:34 note: previous case declared here");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverControlBlockValidationTest,
|
TEST_F(ResolverControlBlockValidationTest,
|
||||||
NonUniqueCaseSelectorValueSint_Fail) {
|
NonUniqueCaseSelectorValueSint_Fail) {
|
||||||
// var a : i32 = 2;
|
// var a : i32 = 2;
|
||||||
// switch (a) {
|
// switch (a) {
|
||||||
// case 10: {}
|
// case -10: {}
|
||||||
// case 0,1,2,10: {}
|
// case 0,1,2,-10: {}
|
||||||
// default: {}
|
// default: {}
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||||
|
|
||||||
ast::CaseStatementList switch_body;
|
auto* block = Block(Decl(var), //
|
||||||
ast::CaseSelectorList csl_1;
|
Switch("a", //
|
||||||
csl_1.push_back(Literal(10));
|
Case(Literal(Source{{12, 34}}, -10)),
|
||||||
switch_body.push_back(create<ast::CaseStatement>(csl_1, Block()));
|
Case({
|
||||||
|
Literal(0),
|
||||||
ast::CaseSelectorList csl_2;
|
Literal(1),
|
||||||
csl_2.push_back(Literal(0));
|
Literal(2),
|
||||||
csl_2.push_back(Literal(1));
|
Literal(Source{{56, 78}}, -10),
|
||||||
csl_2.push_back(Literal(2));
|
}),
|
||||||
csl_2.push_back(Literal(10));
|
DefaultCase()));
|
||||||
switch_body.push_back(create<ast::CaseStatement>(
|
|
||||||
Source{Source::Location{12, 34}}, csl_2, Block()));
|
|
||||||
|
|
||||||
ast::CaseSelectorList default_csl;
|
|
||||||
auto* block_default = Block();
|
|
||||||
switch_body.push_back(create<ast::CaseStatement>(default_csl, block_default));
|
|
||||||
|
|
||||||
auto* block =
|
|
||||||
Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), switch_body));
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
"12:34 error: a literal value must not appear more than once in "
|
"56:78 error: duplicate switch case '-10'\n"
|
||||||
"the case selectors for a switch statement: '10'");
|
"12:34 note: previous case declared here");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverControlBlockValidationTest,
|
TEST_F(ResolverControlBlockValidationTest,
|
||||||
|
@ -343,14 +287,10 @@ TEST_F(ResolverControlBlockValidationTest,
|
||||||
// default: { fallthrough; }
|
// default: { fallthrough; }
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||||
|
auto* fallthrough = create<ast::FallthroughStatement>(Source{{12, 34}});
|
||||||
ast::CaseSelectorList default_csl;
|
auto* block = Block(Decl(var), //
|
||||||
auto* block_default = Block(
|
Switch("a", //
|
||||||
create<ast::FallthroughStatement>(Source{Source::Location{12, 34}}));
|
DefaultCase(Block(fallthrough))));
|
||||||
ast::CaseStatementList body;
|
|
||||||
body.push_back(create<ast::CaseStatement>(default_csl, block_default));
|
|
||||||
|
|
||||||
auto* block = Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), body));
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
@ -367,17 +307,10 @@ TEST_F(ResolverControlBlockValidationTest, SwitchCase_Pass) {
|
||||||
// }
|
// }
|
||||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||||
|
|
||||||
ast::CaseSelectorList default_csl;
|
auto* block = Block(Decl(var), //
|
||||||
auto* block_default = Block();
|
Switch("a", //
|
||||||
ast::CaseStatementList body;
|
DefaultCase(Source{{12, 34}}), //
|
||||||
body.push_back(create<ast::CaseStatement>(Source{Source::Location{12, 34}},
|
Case(Literal(5))));
|
||||||
default_csl, block_default));
|
|
||||||
ast::CaseSelectorList case_csl;
|
|
||||||
case_csl.push_back(Literal(5));
|
|
||||||
auto* block_case = Block();
|
|
||||||
body.push_back(create<ast::CaseStatement>(case_csl, block_case));
|
|
||||||
|
|
||||||
auto* block = Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), body));
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
@ -392,14 +325,8 @@ TEST_F(ResolverControlBlockValidationTest, SwitchCaseAlias_Pass) {
|
||||||
|
|
||||||
auto* my_int = Alias("MyInt", ty.u32());
|
auto* my_int = Alias("MyInt", ty.u32());
|
||||||
auto* var = Var("a", ty.Of(my_int), ast::StorageClass::kNone, Expr(2u));
|
auto* var = Var("a", ty.Of(my_int), ast::StorageClass::kNone, Expr(2u));
|
||||||
|
auto* block = Block(Decl(var), //
|
||||||
ast::CaseSelectorList default_csl;
|
Switch("a", DefaultCase(Source{{12, 34}})));
|
||||||
auto* block_default = Block();
|
|
||||||
ast::CaseStatementList body;
|
|
||||||
body.push_back(create<ast::CaseStatement>(Source{Source::Location{12, 34}},
|
|
||||||
default_csl, block_default));
|
|
||||||
|
|
||||||
auto* block = Block(Decl(var), create<ast::SwitchStatement>(Expr("a"), body));
|
|
||||||
|
|
||||||
WrapInFunction(block);
|
WrapInFunction(block);
|
||||||
|
|
||||||
|
|
|
@ -273,12 +273,10 @@ bool Resolver::ResolveInternal() {
|
||||||
bool result = true;
|
bool result = true;
|
||||||
for (auto* node : builder_->ASTNodes().Objects()) {
|
for (auto* node : builder_->ASTNodes().Objects()) {
|
||||||
if (marked_.count(node) == 0) {
|
if (marked_.count(node) == 0) {
|
||||||
TINT_ICE(Resolver, diagnostics_)
|
TINT_ICE(Resolver, diagnostics_) << "AST node '" << node->TypeInfo().name
|
||||||
<< "AST node '" << node->TypeInfo().name
|
<< "' was not reached by the resolver\n"
|
||||||
<< "' was not reached by the resolver\n"
|
<< "At: " << node->source() << "\n"
|
||||||
<< "At: " << node->source() << "\n"
|
<< "Pointer: " << node;
|
||||||
<< "Content: " << builder_->str(node) << "\n"
|
|
||||||
<< "Pointer: " << node;
|
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2123,9 +2121,9 @@ bool Resolver::Statement(ast::Statement* stmt) {
|
||||||
return VariableDeclStatement(v);
|
return VariableDeclStatement(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddError(
|
AddError("unknown statement type for type determination: " +
|
||||||
"unknown statement type for type determination: " + builder_->str(stmt),
|
std::string(stmt->TypeInfo().name),
|
||||||
stmt->source());
|
stmt->source());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4389,7 +4387,7 @@ bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_default = false;
|
bool has_default = false;
|
||||||
std::unordered_set<uint32_t> selector_set;
|
std::unordered_map<uint32_t, Source> selectors;
|
||||||
|
|
||||||
for (auto* case_stmt : s->body()) {
|
for (auto* case_stmt : s->body()) {
|
||||||
if (case_stmt->IsDefault()) {
|
if (case_stmt->IsDefault()) {
|
||||||
|
@ -4412,15 +4410,16 @@ bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto v = selector->value_as_u32();
|
auto v = selector->value_as_u32();
|
||||||
if (selector_set.find(v) != selector_set.end()) {
|
auto it = selectors.find(v);
|
||||||
AddError(
|
if (it != selectors.end()) {
|
||||||
"a literal value must not appear more than once in "
|
auto val = selector->Is<ast::IntLiteral>()
|
||||||
"the case selectors for a switch statement: '" +
|
? std::to_string(selector->value_as_i32())
|
||||||
builder_->str(selector) + "'",
|
: std::to_string(selector->value_as_u32());
|
||||||
case_stmt->source());
|
AddError("duplicate switch case '" + val + "'", selector->source());
|
||||||
|
AddNote("previous case declared here", it->second);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
selector_set.emplace(v);
|
selectors.emplace(v, selector->source());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4659,7 +4658,6 @@ void Resolver::Mark(const ast::Node* node) {
|
||||||
<< "AST node '" << node->TypeInfo().name
|
<< "AST node '" << node->TypeInfo().name
|
||||||
<< "' was encountered twice in the same AST of a Program\n"
|
<< "' was encountered twice in the same AST of a Program\n"
|
||||||
<< "At: " << node->source() << "\n"
|
<< "At: " << node->source() << "\n"
|
||||||
<< "Content: " << builder_->str(node) << "\n"
|
|
||||||
<< "Pointer: " << node;
|
<< "Pointer: " << node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,9 @@ namespace {
|
||||||
|
|
||||||
using ResolverValidationTest = ResolverTest;
|
using ResolverValidationTest = ResolverTest;
|
||||||
|
|
||||||
class FakeStmt : public ast::Statement {
|
class FakeStmt : public Castable<FakeStmt, ast::Statement> {
|
||||||
public:
|
public:
|
||||||
FakeStmt(ProgramID program_id, Source source)
|
FakeStmt(ProgramID program_id, Source source) : Base(program_id, source) {}
|
||||||
: ast::Statement(program_id, source) {}
|
|
||||||
FakeStmt* Clone(CloneContext*) const override { return nullptr; }
|
FakeStmt* Clone(CloneContext*) const override { return nullptr; }
|
||||||
void to_str(const sem::Info&, std::ostream& out, size_t) const override {
|
void to_str(const sem::Info&, std::ostream& out, size_t) const override {
|
||||||
out << "Fake";
|
out << "Fake";
|
||||||
|
@ -118,7 +117,8 @@ TEST_F(ResolverValidationTest, Error_WithEmptySource) {
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
"error: unknown statement type for type determination: Fake");
|
"error: unknown statement type for type determination: "
|
||||||
|
"tint::resolver::FakeStmt");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverValidationTest, Stmt_Error_Unknown) {
|
TEST_F(ResolverValidationTest, Stmt_Error_Unknown) {
|
||||||
|
@ -128,7 +128,8 @@ TEST_F(ResolverValidationTest, Stmt_Error_Unknown) {
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
"2:30 error: unknown statement type for type determination: Fake");
|
"2:30 error: unknown statement type for type determination: "
|
||||||
|
"tint::resolver::FakeStmt");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverValidationTest, Stmt_If_NonBool) {
|
TEST_F(ResolverValidationTest, Stmt_If_NonBool) {
|
||||||
|
@ -1057,4 +1058,5 @@ TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) {
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
||||||
|
TINT_INSTANTIATE_TYPEINFO(tint::resolver::FakeStmt);
|
||||||
TINT_INSTANTIATE_TYPEINFO(tint::resolver::FakeExpr);
|
TINT_INSTANTIATE_TYPEINFO(tint::resolver::FakeExpr);
|
||||||
|
|
Loading…
Reference in New Issue