From 15dcd8fb15f31f742f0c248424a052d4d18ab3d3 Mon Sep 17 00:00:00 2001 From: James Price Date: Tue, 16 Mar 2021 22:08:13 +0000 Subject: [PATCH] [validator] Fix return statement type validation for aliases Unwrap type aliases from the function return type before comparing to the return value. Add additional test coverage for aliased and non-aliased cases. Change-Id: I4aa43f681468cd2c68e84da71222aea952117c1a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44923 Commit-Queue: Antonio Maiorano Auto-Submit: James Price Reviewed-by: Antonio Maiorano --- src/validator/validator_function_test.cc | 64 ++++++++++++++++++++++++ src/validator/validator_impl.cc | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/validator/validator_function_test.cc b/src/validator/validator_function_test.cc index e939da4de8..aa4706036e 100644 --- a/src/validator/validator_function_test.cc +++ b/src/validator/validator_function_test.cc @@ -122,6 +122,24 @@ TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementType_fail) { "return type, returned '__i32', expected '__void'"); } +TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementTypeF32_pass) { + // fn func -> f32 { return 2.0; } + Func("func", ast::VariableList{}, ty.f32(), + ast::StatementList{ + create(Source{Source::Location{12, 34}}, + Expr(2.f)), + }, + ast::DecorationList{}); + Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{}, + ast::DecorationList{ + create(ast::PipelineStage::kVertex), + }); + + ValidatorImpl& v = Build(); + + EXPECT_TRUE(v.Validate()); +} + TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementTypeF32_fail) { // fn func -> f32 { return 2; } Func("func", ast::VariableList{}, ty.f32(), @@ -140,6 +158,52 @@ TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementTypeF32_fail) { "return type, returned '__i32', expected '__f32'"); } +TEST_F(ValidateFunctionTest, + FunctionTypeMustMatchReturnStatementTypeF32Alias_pass) { + // type myf32 = f32; + // fn func -> myf32 { return 2.0; } + auto* myf32 = ty.alias("myf32", ty.f32()); + Func("func", ast::VariableList{}, myf32, + ast::StatementList{ + create(Source{Source::Location{12, 34}}, + Expr(2.f)), + }, + ast::DecorationList{}); + Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{}, + ast::DecorationList{ + create(ast::PipelineStage::kVertex), + }); + + ValidatorImpl& v = Build(); + + EXPECT_TRUE(v.Validate()); +} + +TEST_F(ValidateFunctionTest, + FunctionTypeMustMatchReturnStatementTypeF32Alias_fail) { + // type myf32 = f32; + // fn func -> myf32 { return 2; } + auto* myf32 = ty.alias("myf32", ty.f32()); + Func("func", ast::VariableList{}, myf32, + ast::StatementList{ + create(Source{Source::Location{12, 34}}, + Expr(2u)), + }, + ast::DecorationList{}); + Func("main", ast::VariableList{}, ty.void_(), ast::StatementList{}, + ast::DecorationList{ + create(ast::PipelineStage::kVertex), + }); + + ValidatorImpl& v = Build(); + + EXPECT_FALSE(v.Validate()); + EXPECT_EQ( + v.error(), + "12:34 v-000y: return statement type must match its function " + "return type, returned '__u32', expected '__alias_tint_symbol_1__f32'"); +} + TEST_F(ValidateFunctionTest, FunctionNamesMustBeUnique_fail) { // fn func -> i32 { return 2; } // fn func -> i32 { return 2; } diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc index 3a957d4ee8..add2fc1c41 100644 --- a/src/validator/validator_impl.cc +++ b/src/validator/validator_impl.cc @@ -287,7 +287,7 @@ bool ValidatorImpl::ValidateReturnStatement(const ast::ReturnStatement* ret) { ? program_->Sem().Get(ret->value())->Type()->UnwrapAll() : &void_type; - if (func_type->type_name() != ret_type->type_name()) { + if (func_type->UnwrapAll()->type_name() != ret_type->type_name()) { add_error(ret->source(), "v-000y", "return statement type must match its function return " "type, returned '" +