mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-09 21:47:47 +00:00
Move VariableDecl validation from Validator to Resolver
Moved tests and fixed now broken tests. Bug: tint:642 Change-Id: Iaa4483abde101f3963ca20e51c1069b2d64bbb5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/46661 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
committed by
Commit Bot service account
parent
2f04dc94ce
commit
09356cc3dc
@@ -81,9 +81,9 @@ TEST_F(ResolverAssignmentValidationTest,
|
||||
create<ast::VariableDeclStatement>(var),
|
||||
create<ast::AssignmentStatement>(Source{{12, 34}}, lhs, rhs),
|
||||
});
|
||||
WrapInFunction(var, body);
|
||||
WrapInFunction(body);
|
||||
|
||||
ASSERT_TRUE(r()->Resolve());
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverAssignmentValidationTest,
|
||||
@@ -101,7 +101,7 @@ TEST_F(ResolverAssignmentValidationTest,
|
||||
create<ast::VariableDeclStatement>(var),
|
||||
create<ast::AssignmentStatement>(Source{{12, 34}}, lhs, rhs),
|
||||
});
|
||||
WrapInFunction(var, block);
|
||||
WrapInFunction(block);
|
||||
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
|
||||
@@ -132,7 +132,7 @@ TEST_F(ResolverAssignmentValidationTest,
|
||||
inner_block,
|
||||
});
|
||||
|
||||
WrapInFunction(var, outer_block);
|
||||
WrapInFunction(outer_block);
|
||||
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
|
||||
|
||||
@@ -224,20 +224,24 @@ bool Resolver::ResolveInternal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateParameter(const ast::Variable* param) {
|
||||
auto* type = variable_to_info_[param]->type;
|
||||
bool Resolver::ValidateVariable(const ast::Variable* var) {
|
||||
auto* type = variable_to_info_[var]->type;
|
||||
if (auto* r = type->UnwrapAll()->As<type::Array>()) {
|
||||
if (r->IsRuntimeArray()) {
|
||||
diagnostics_.add_error(
|
||||
"v-0015",
|
||||
"runtime arrays may only appear as the last member of a struct",
|
||||
param->source());
|
||||
var->source());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateParameter(const ast::Variable* param) {
|
||||
return ValidateVariable(param);
|
||||
}
|
||||
|
||||
bool Resolver::ValidateFunction(const ast::Function* func) {
|
||||
if (symbol_to_function_.find(func->symbol()) != symbol_to_function_.end()) {
|
||||
diagnostics_.add_error("v-0016",
|
||||
@@ -1278,6 +1282,16 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
|
||||
ast::Variable* var = stmt->variable();
|
||||
type::Type* type = var->declared_type();
|
||||
|
||||
bool is_global = false;
|
||||
if (variable_stack_.get(var->symbol(), nullptr, &is_global)) {
|
||||
const char* error_code = is_global ? "v-0013" : "v-0014";
|
||||
diagnostics_.add_error(error_code,
|
||||
"redeclared identifier '" +
|
||||
builder_->Symbols().NameFor(var->symbol()) + "'",
|
||||
stmt->source());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto* ctor = stmt->variable()->constructor()) {
|
||||
if (!Expression(ctor)) {
|
||||
return false;
|
||||
@@ -1304,6 +1318,10 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
|
||||
variable_stack_.set(var->symbol(), info);
|
||||
current_block_->decls.push_back(var);
|
||||
|
||||
if (!ValidateVariable(var)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!var->is_const()) {
|
||||
if (info->storage_class != ast::StorageClass::kFunction) {
|
||||
if (info->storage_class != ast::StorageClass::kNone) {
|
||||
|
||||
@@ -231,6 +231,7 @@ class Resolver {
|
||||
// AST and Type validation methods
|
||||
// Each return true on success, false on failure.
|
||||
bool ValidateBinary(ast::BinaryExpression* expr);
|
||||
bool ValidateVariable(const ast::Variable* param);
|
||||
bool ValidateParameter(const ast::Variable* param);
|
||||
bool ValidateFunction(const ast::Function* func);
|
||||
bool ValidateStructure(const type::Struct* st);
|
||||
|
||||
@@ -26,6 +26,199 @@ namespace {
|
||||
class ResolverTypeValidationTest : public resolver::TestHelper,
|
||||
public testing::Test {};
|
||||
|
||||
TEST_F(ResolverTypeValidationTest,
|
||||
GlobalVariableFunctionVariableNotUnique_Fail) {
|
||||
// var a: f32 = 2.1;
|
||||
// fn my_func -> void {
|
||||
// var a: f32 = 2.0;
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f));
|
||||
|
||||
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f));
|
||||
|
||||
Func("my_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve()) << r()->error();
|
||||
EXPECT_EQ(r()->error(), "12:34 error v-0013: redeclared identifier 'a'");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RedeclaredIdentifier_Fail) {
|
||||
// fn my_func() -> void {
|
||||
// var a :i32 = 2;
|
||||
// var a :f21 = 2.0;
|
||||
// }
|
||||
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||
|
||||
auto* var_a_float = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(0.1f));
|
||||
|
||||
Func("my_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(var),
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_a_float),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve()) << r()->error();
|
||||
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'a'");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScope_Pass) {
|
||||
// {
|
||||
// if (true) { var a : f32 = 2.0; }
|
||||
// var a : f32 = 3.14;
|
||||
// }
|
||||
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f));
|
||||
|
||||
auto* cond = Expr(true);
|
||||
auto* body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(var),
|
||||
});
|
||||
|
||||
auto* var_a_float = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(3.1f));
|
||||
|
||||
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::IfStatement>(cond, body, ast::ElseStatementList{}),
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_a_float),
|
||||
});
|
||||
|
||||
WrapInFunction(outer_body);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve());
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest,
|
||||
DISABLED_RedeclaredIdentifierInnerScope_False) {
|
||||
// TODO(sarahM0): remove DISABLED after implementing ValidateIfStatement
|
||||
// and it should just work
|
||||
// {
|
||||
// var a : f32 = 3.14;
|
||||
// if (true) { var a : f32 = 2.0; }
|
||||
// }
|
||||
auto* var_a_float = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(3.1f));
|
||||
|
||||
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f));
|
||||
|
||||
auto* cond = Expr(true);
|
||||
auto* body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, var),
|
||||
});
|
||||
|
||||
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(var_a_float),
|
||||
create<ast::IfStatement>(cond, body, ast::ElseStatementList{}),
|
||||
});
|
||||
|
||||
WrapInFunction(outer_body);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'a'");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Pass) {
|
||||
// {
|
||||
// { var a : f32; }
|
||||
// var a : f32;
|
||||
// }
|
||||
auto* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* inner = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_inner),
|
||||
});
|
||||
|
||||
auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
|
||||
inner,
|
||||
create<ast::VariableDeclStatement>(var_outer),
|
||||
});
|
||||
|
||||
WrapInFunction(outer_body);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Fail) {
|
||||
// {
|
||||
// var a : f32;
|
||||
// { var a : f32; }
|
||||
// }
|
||||
auto* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* inner = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_inner),
|
||||
});
|
||||
|
||||
auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(var_outer),
|
||||
inner,
|
||||
});
|
||||
|
||||
WrapInFunction(outer_body);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'a'");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest,
|
||||
RedeclaredIdentifierDifferentFunctions_Pass) {
|
||||
// func0 { var a : f32 = 2.0; return; }
|
||||
// func1 { var a : f32 = 3.0; return; }
|
||||
auto* var0 = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f));
|
||||
|
||||
auto* var1 = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(1.0f));
|
||||
|
||||
Func("func0", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var0),
|
||||
create<ast::ReturnStatement>(),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
Func("func1", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{13, 34}},
|
||||
var1),
|
||||
create<ast::ReturnStatement>(),
|
||||
},
|
||||
ast::DecorationList{
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
|
||||
});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RuntimeArrayInFunction_Fail) {
|
||||
/// [[stage(vertex)]]
|
||||
// fn func -> void { var a : array<i32>; }
|
||||
|
||||
auto* var =
|
||||
Var(Source{{12, 34}}, "a", ty.array<i32>(), ast::StorageClass::kNone);
|
||||
|
||||
Func("func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(var),
|
||||
},
|
||||
ast::DecorationList{
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
"12:34 error v-0015: runtime arrays may only appear as the last member "
|
||||
"of a struct");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RuntimeArrayIsLast_Pass) {
|
||||
// [[Block]]
|
||||
// struct Foo {
|
||||
|
||||
Reference in New Issue
Block a user