mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-14 23:56:16 +00:00
resolver: Remove rule that call statements to functions must return void
Fixed: tint:1256 Change-Id: Ibff78a1009d57afd7af8867952a9444daaf13a9c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/67201 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
committed by
Tint LUCI CQ
parent
38ed53ce8f
commit
72789de9f5
@@ -986,7 +986,7 @@ TEST_P(FloatAllMatching, Scalar) {
|
||||
params.push_back(Expr(1.0f));
|
||||
}
|
||||
auto* builtin = Call(name, params);
|
||||
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(builtin)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
@@ -1002,7 +1002,7 @@ TEST_P(FloatAllMatching, Vec2) {
|
||||
params.push_back(vec2<f32>(1.0f, 1.0f));
|
||||
}
|
||||
auto* builtin = Call(name, params);
|
||||
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(builtin)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
@@ -1018,7 +1018,7 @@ TEST_P(FloatAllMatching, Vec3) {
|
||||
params.push_back(vec3<f32>(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
auto* builtin = Call(name, params);
|
||||
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(builtin)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
@@ -1034,7 +1034,7 @@ TEST_P(FloatAllMatching, Vec4) {
|
||||
params.push_back(vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
auto* builtin = Call(name, params);
|
||||
Func("func", {}, ty.void_(), {Ignore(builtin)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(builtin)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
@@ -33,7 +33,7 @@ TEST_F(ResolverCallValidationTest, Recursive_Invalid) {
|
||||
|
||||
Func("main", params0, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::CallStatement>(call_expr),
|
||||
CallStmt(call_expr),
|
||||
},
|
||||
ast::DecorationList{
|
||||
Stage(ast::PipelineStage::kVertex),
|
||||
@@ -56,7 +56,7 @@ TEST_F(ResolverCallValidationTest, Undeclared_Invalid) {
|
||||
|
||||
Func("main", params0, ty.f32(),
|
||||
ast::StatementList{
|
||||
create<ast::CallStatement>(call_expr),
|
||||
CallStmt(call_expr),
|
||||
Return(),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
@@ -109,23 +109,19 @@ TEST_F(ResolverCallValidationTest, MismatchedArgs) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverCallValidationTest, UnusedRetval) {
|
||||
// fn func() -> f32 { return 1.0; }
|
||||
// fn main() {func(); return; }
|
||||
// fn func() { return; }
|
||||
|
||||
Func("func", {}, ty.f32(), {Return(Expr(1.0f))}, {});
|
||||
|
||||
Func("main", {}, ty.f32(),
|
||||
Func("main", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::CallStatement>(Source{{12, 34}}, Call("func")),
|
||||
CallStmt(Source{{12, 34}}, Call("func")),
|
||||
Return(),
|
||||
},
|
||||
{});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: result of called function was not used. If this was "
|
||||
"intentional wrap the function call in ignore()");
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverCallValidationTest, PointerArgument_VariableIdentExpr) {
|
||||
@@ -139,8 +135,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_VariableIdentExpr) {
|
||||
Func("main", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
Decl(Var("z", ty.i32(), Expr(1))),
|
||||
create<ast::CallStatement>(
|
||||
Call("foo", AddressOf(Source{{12, 34}}, Expr("z")))),
|
||||
CallStmt(Call("foo", AddressOf(Source{{12, 34}}, Expr("z")))),
|
||||
});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
@@ -157,8 +152,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_ConstIdentExpr) {
|
||||
Func("main", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
Decl(Const("z", ty.i32(), Expr(1))),
|
||||
create<ast::CallStatement>(
|
||||
Call("foo", AddressOf(Expr(Source{{12, 34}}, "z")))),
|
||||
CallStmt(Call("foo", AddressOf(Expr(Source{{12, 34}}, "z")))),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
@@ -178,7 +172,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_NotIdentExprVar) {
|
||||
Func("main", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
Decl(Var("v", ty.Of(S))),
|
||||
create<ast::CallStatement>(Call(
|
||||
CallStmt(Call(
|
||||
"foo", AddressOf(Source{{12, 34}}, MemberAccessor("v", "m")))),
|
||||
});
|
||||
|
||||
@@ -201,9 +195,8 @@ TEST_F(ResolverCallValidationTest, PointerArgument_AddressOfMemberAccessor) {
|
||||
Func("main", {}, ty.void_(),
|
||||
ast::StatementList{
|
||||
Decl(Const("v", ty.Of(S), Construct(ty.Of(S)))),
|
||||
create<ast::CallStatement>(Call(
|
||||
"foo",
|
||||
AddressOf(Expr(Source{{12, 34}}, MemberAccessor("v", "m"))))),
|
||||
CallStmt(Call("foo", AddressOf(Expr(Source{{12, 34}},
|
||||
MemberAccessor("v", "m"))))),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
@@ -218,8 +211,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParam) {
|
||||
Func("foo", {Param("p", ty.pointer<i32>(ast::StorageClass::kFunction))},
|
||||
ty.void_(), {});
|
||||
Func("bar", {Param("p", ty.pointer<i32>(ast::StorageClass::kFunction))},
|
||||
ty.void_(),
|
||||
ast::StatementList{create<ast::CallStatement>(Call("foo", Expr("p")))});
|
||||
ty.void_(), ast::StatementList{CallStmt(Call("foo", Expr("p")))});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
@@ -237,12 +229,11 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParamWithMain) {
|
||||
Func("foo", {Param("p", ty.pointer<i32>(ast::StorageClass::kFunction))},
|
||||
ty.void_(), {});
|
||||
Func("bar", {Param("p", ty.pointer<i32>(ast::StorageClass::kFunction))},
|
||||
ty.void_(),
|
||||
ast::StatementList{create<ast::CallStatement>(Call("foo", Expr("p")))});
|
||||
ty.void_(), ast::StatementList{CallStmt(Call("foo", Expr("p")))});
|
||||
Func("main", ast::VariableList{}, ty.void_(),
|
||||
{
|
||||
Decl(Var("v", ty.i32(), Expr(1))),
|
||||
create<ast::CallStatement>(Call("foo", AddressOf(Expr("v")))),
|
||||
CallStmt(Call("foo", AddressOf(Expr("v")))),
|
||||
},
|
||||
{
|
||||
Stage(ast::PipelineStage::kFragment),
|
||||
|
||||
@@ -399,7 +399,7 @@ TEST_F(ResolverFunctionValidationTest, CannotCallEntryPoint) {
|
||||
|
||||
Func("func", ast::VariableList{}, ty.void_(),
|
||||
{
|
||||
create<ast::CallStatement>(Call(Source{{12, 34}}, "entrypoint")),
|
||||
CallStmt(Call(Source{{12, 34}}, "entrypoint")),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
@@ -506,7 +506,7 @@ TEST_P(ResolverIntrinsicTest_Barrier, InferType) {
|
||||
auto param = GetParam();
|
||||
|
||||
auto* call = Call(param.name);
|
||||
WrapInFunction(create<ast::CallStatement>(call));
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
ASSERT_NE(TypeOf(call), nullptr);
|
||||
@@ -517,7 +517,7 @@ TEST_P(ResolverIntrinsicTest_Barrier, Error_TooManyParams) {
|
||||
auto param = GetParam();
|
||||
|
||||
auto* call = Call(param.name, vec4<f32>(1.f, 2.f, 3.f, 4.f), 1.0f);
|
||||
WrapInFunction(create<ast::CallStatement>(call));
|
||||
WrapInFunction(CallStmt(call));
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
@@ -1943,9 +1943,7 @@ TEST_P(ResolverIntrinsicTest_Texture, Call) {
|
||||
param.BuildSamplerVariable(this);
|
||||
|
||||
auto* call = Call(param.function, param.args(this));
|
||||
auto* stmt = ast::intrinsic::test::ReturnsVoid(param.overload)
|
||||
? create<ast::CallStatement>(call)
|
||||
: Ignore(call);
|
||||
auto* stmt = CallStmt(call);
|
||||
Func("func", {}, ty.void_(), {stmt}, {Stage(ast::PipelineStage::kFragment)});
|
||||
|
||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
@@ -40,7 +40,8 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
|
||||
|
||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||
ast::ExpressionList{Expr(1.0f)});
|
||||
Func(Source{{1, 2}}, "func", ast::VariableList{}, ty.void_(), {Ignore(dpdx)},
|
||||
Func(Source{{1, 2}}, "func", ast::VariableList{}, ty.void_(),
|
||||
{CallStmt(dpdx)},
|
||||
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
@@ -56,16 +57,13 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
|
||||
|
||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||
ast::ExpressionList{Expr(1.0f)});
|
||||
Func(Source{{1, 2}}, "f0", {}, ty.void_(), {Ignore(dpdx)});
|
||||
Func(Source{{1, 2}}, "f0", {}, ty.void_(), {CallStmt(dpdx)});
|
||||
|
||||
Func(Source{{3, 4}}, "f1", {}, ty.void_(),
|
||||
{create<ast::CallStatement>(Call("f0"))});
|
||||
Func(Source{{3, 4}}, "f1", {}, ty.void_(), {CallStmt(Call("f0"))});
|
||||
|
||||
Func(Source{{5, 6}}, "f2", {}, ty.void_(),
|
||||
{create<ast::CallStatement>(Call("f1"))});
|
||||
Func(Source{{5, 6}}, "f2", {}, ty.void_(), {CallStmt(Call("f1"))});
|
||||
|
||||
Func(Source{{7, 8}}, "main", {}, ty.void_(),
|
||||
{create<ast::CallStatement>(Call("f2"))},
|
||||
Func(Source{{7, 8}}, "main", {}, ty.void_(), {CallStmt(Call("f2"))},
|
||||
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
@@ -141,7 +139,7 @@ TEST_P(IntrinsicTextureSamplerValidationTest, ConstExpr) {
|
||||
}
|
||||
|
||||
auto* call = Call(param.function, args);
|
||||
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(call)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
|
||||
if (offset.is_valid) {
|
||||
@@ -175,7 +173,7 @@ TEST_P(IntrinsicTextureSamplerValidationTest, ConstExprOfConstExpr) {
|
||||
Construct(ty.vec2<i32>(), offset.y, offset.z)));
|
||||
}
|
||||
auto* call = Call(param.function, args);
|
||||
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(call)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
if (offset.is_valid) {
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
@@ -206,7 +204,7 @@ TEST_P(IntrinsicTextureSamplerValidationTest, EmptyVectorConstructor) {
|
||||
}
|
||||
|
||||
auto* call = Call(param.function, args);
|
||||
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(call)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
@@ -232,7 +230,7 @@ TEST_P(IntrinsicTextureSamplerValidationTest, GlobalConst) {
|
||||
}
|
||||
|
||||
auto* call = Call(param.function, args);
|
||||
Func("func", {}, ty.void_(), {Ignore(call)},
|
||||
Func("func", {}, ty.void_(), {CallStmt(call)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
std::stringstream err;
|
||||
@@ -261,7 +259,7 @@ TEST_P(IntrinsicTextureSamplerValidationTest, ScalarConst) {
|
||||
}
|
||||
|
||||
auto* call = Call(param.function, args);
|
||||
Func("func", {}, ty.void_(), {Decl(x), Ignore(call)},
|
||||
Func("func", {}, ty.void_(), {Decl(x), CallStmt(call)},
|
||||
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
std::stringstream err;
|
||||
|
||||
@@ -2475,21 +2475,7 @@ bool Resolver::ValidateCall(const ast::CallExpression* call) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateCallStatement(const ast::CallStatement* stmt) {
|
||||
const sem::Type* return_type = TypeOf(stmt->expr);
|
||||
if (!return_type->Is<sem::Void>()) {
|
||||
// https://gpuweb.github.io/gpuweb/wgsl/#function-call-statement
|
||||
// A function call statement executes a function call where the called
|
||||
// function does not return a value. If the called function returns a value,
|
||||
// that value must be consumed either through assignment, evaluation in
|
||||
// another expression or through use of the ignore built-in function (see
|
||||
// § 16.13 Value-steering functions).
|
||||
AddError(
|
||||
"result of called function was not used. If this was intentional wrap "
|
||||
"the function call in ignore()",
|
||||
stmt->source);
|
||||
return false;
|
||||
}
|
||||
bool Resolver::ValidateCallStatement(const ast::CallStatement*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ TEST_F(ResolverTest, Stmt_Call) {
|
||||
|
||||
auto* expr = Call("my_func");
|
||||
|
||||
auto* call = create<ast::CallStatement>(expr);
|
||||
auto* call = CallStmt(expr);
|
||||
WrapInFunction(call);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
@@ -1947,22 +1947,22 @@ TEST_F(ResolverTest, Function_EntryPoints_LinearTime) {
|
||||
for (int i = levels - 1; i >= 0; i--) {
|
||||
Func(fn_a(i), {}, ty.void_(),
|
||||
{
|
||||
create<ast::CallStatement>(Call(fn_a(i + 1))),
|
||||
create<ast::CallStatement>(Call(fn_b(i + 1))),
|
||||
CallStmt(Call(fn_a(i + 1))),
|
||||
CallStmt(Call(fn_b(i + 1))),
|
||||
},
|
||||
{});
|
||||
Func(fn_b(i), {}, ty.void_(),
|
||||
{
|
||||
create<ast::CallStatement>(Call(fn_a(i + 1))),
|
||||
create<ast::CallStatement>(Call(fn_b(i + 1))),
|
||||
CallStmt(Call(fn_a(i + 1))),
|
||||
CallStmt(Call(fn_b(i + 1))),
|
||||
},
|
||||
{});
|
||||
}
|
||||
|
||||
Func("main", {}, ty.void_(),
|
||||
{
|
||||
create<ast::CallStatement>(Call(fn_a(0))),
|
||||
create<ast::CallStatement>(Call(fn_b(0))),
|
||||
CallStmt(Call(fn_a(0))),
|
||||
CallStmt(Call(fn_b(0))),
|
||||
},
|
||||
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
|
||||
|
||||
|
||||
@@ -90,10 +90,8 @@ TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInFragmentStage) {
|
||||
auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
|
||||
|
||||
Func(Source{{5, 6}}, "f2", {}, ty.void_(), {stmt});
|
||||
Func(Source{{7, 8}}, "f1", {}, ty.void_(),
|
||||
{create<ast::CallStatement>(Call("f2"))});
|
||||
Func(Source{{9, 10}}, "f0", {}, ty.void_(),
|
||||
{create<ast::CallStatement>(Call("f1"))},
|
||||
Func(Source{{7, 8}}, "f1", {}, ty.void_(), {CallStmt(Call("f2"))});
|
||||
Func(Source{{9, 10}}, "f0", {}, ty.void_(), {CallStmt(Call("f1"))},
|
||||
ast::DecorationList{Stage(ast::PipelineStage::kFragment)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
Reference in New Issue
Block a user