Better type determiner errors.

This CL adds the source info into the type determiner errors so they
will include line and column number if available. If the line number is
0 then it's considered the source info is missing and it is not emitted.

Add line and colummn to type determiner errors

Change-Id: I18764a71db80082fd31c8509c5e9b193800f1d95
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/19105
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-04-08 19:58:35 +00:00 committed by dan sinclair
parent d5dea224e0
commit 7456f4258a
3 changed files with 59 additions and 13 deletions

View File

@ -49,13 +49,19 @@
namespace tint { namespace tint {
TypeDeterminer::TypeDeterminer(Context* ctx) : ctx_(*ctx) { TypeDeterminer::TypeDeterminer(Context* ctx) : ctx_(*ctx) {}
// TODO(dsinclair): Temporary usage to avoid compiler warning
static_cast<void>(ctx_.type_mgr());
}
TypeDeterminer::~TypeDeterminer() = default; TypeDeterminer::~TypeDeterminer() = default;
void TypeDeterminer::set_error(const Source& src, const std::string& msg) {
error_ = "";
if (src.line > 0) {
error_ +=
std::to_string(src.line) + ":" + std::to_string(src.column) + ": ";
}
error_ += msg;
}
bool TypeDeterminer::Determine(ast::Module* mod) { bool TypeDeterminer::Determine(ast::Module* mod) {
for (const auto& var : mod->global_variables()) { for (const auto& var : mod->global_variables()) {
variable_stack_.set_global(var->name(), var.get()); variable_stack_.set_global(var->name(), var.get());
@ -209,7 +215,7 @@ bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
return DetermineResultType(v->variable()->constructor()); return DetermineResultType(v->variable()->constructor());
} }
error_ = "unknown statement type for type determination"; set_error(stmt->source(), "unknown statement type for type determination");
return false; return false;
} }
@ -253,7 +259,7 @@ bool TypeDeterminer::DetermineResultType(ast::Expression* expr) {
return DetermineUnaryOp(expr->AsUnaryOp()); return DetermineUnaryOp(expr->AsUnaryOp());
} }
error_ = "unknown expression for type determination"; set_error(expr->source(), "unknown expression for type determination");
return false; return false;
} }
@ -272,7 +278,7 @@ bool TypeDeterminer::DetermineArrayAccessor(
expr->set_result_type(ctx_.type_mgr().Get( expr->set_result_type(ctx_.type_mgr().Get(
std::make_unique<ast::type::VectorType>(m->type(), m->rows()))); std::make_unique<ast::type::VectorType>(m->type(), m->rows())));
} else { } else {
error_ = "invalid parent type in array accessor"; set_error(expr->source(), "invalid parent type in array accessor");
return false; return false;
} }
return true; return true;
@ -308,7 +314,7 @@ bool TypeDeterminer::DetermineConstructor(ast::ConstructorExpression* expr) {
bool TypeDeterminer::DetermineIdentifier(ast::IdentifierExpression* expr) { bool TypeDeterminer::DetermineIdentifier(ast::IdentifierExpression* expr) {
if (expr->name().size() > 1) { if (expr->name().size() > 1) {
// TODO(dsinclair): Handle imports // TODO(dsinclair): Handle imports
error_ = "imports not handled in type determination"; set_error(expr->source(), "imports not handled in type determination");
return false; return false;
} }
@ -348,7 +354,7 @@ bool TypeDeterminer::DetermineMemberAccessor(
return true; return true;
} }
error_ = "struct member not found"; set_error(expr->source(), "struct member not found");
return false; return false;
} }
if (data_type->IsVector()) { if (data_type->IsVector()) {
@ -363,7 +369,7 @@ bool TypeDeterminer::DetermineMemberAccessor(
return true; return true;
} }
error_ = "invalid type in member accessor"; set_error(expr->source(), "invalid type in member accessor");
return false; return false;
} }
@ -470,7 +476,7 @@ bool TypeDeterminer::DetermineUnaryMethod(ast::UnaryMethodExpression* expr) {
case ast::UnaryMethod::kIsFinite: case ast::UnaryMethod::kIsFinite:
case ast::UnaryMethod::kIsNormal: { case ast::UnaryMethod::kIsNormal: {
if (expr->params().empty()) { if (expr->params().empty()) {
error_ = "incorrect number of parameters"; set_error(expr->source(), "incorrect number of parameters");
return false; return false;
} }
@ -493,13 +499,14 @@ bool TypeDeterminer::DetermineUnaryMethod(ast::UnaryMethodExpression* expr) {
} }
case ast::UnaryMethod::kOuterProduct: { case ast::UnaryMethod::kOuterProduct: {
if (expr->params().size() != 2) { if (expr->params().size() != 2) {
error_ = "incorrect number of parameters for outer product"; set_error(expr->source(),
"incorrect number of parameters for outer product");
return false; return false;
} }
auto param0_type = expr->params()[0]->result_type(); auto param0_type = expr->params()[0]->result_type();
auto param1_type = expr->params()[1]->result_type(); auto param1_type = expr->params()[1]->result_type();
if (!param0_type->IsVector() || !param1_type->IsVector()) { if (!param0_type->IsVector() || !param1_type->IsVector()) {
error_ = "invalid parameter type for outer product"; set_error(expr->source(), "invalid parameter type for outer product");
return false; return false;
} }
expr->set_result_type( expr->set_result_type(

View File

@ -83,6 +83,8 @@ class TypeDeterminer {
bool DetermineVariableStorageClass(ast::Statement* stmt); bool DetermineVariableStorageClass(ast::Statement* stmt);
private: private:
void set_error(const Source& src, const std::string& msg);
bool DetermineArrayAccessor(ast::ArrayAccessorExpression* expr); bool DetermineArrayAccessor(ast::ArrayAccessorExpression* expr);
bool DetermineAs(ast::AsExpression* expr); bool DetermineAs(ast::AsExpression* expr);
bool DetermineBinary(ast::BinaryExpression* expr); bool DetermineBinary(ast::BinaryExpression* expr);

View File

@ -58,6 +58,18 @@
namespace tint { namespace tint {
namespace { namespace {
class FakeStmt : public ast::Statement {
public:
bool IsValid() const override { return true; }
void to_str(std::ostream&, size_t) const override {}
};
class FakeExpr : public ast::Expression {
public:
bool IsValid() const override { return true; }
void to_str(std::ostream&, size_t) const override {}
};
class TypeDeterminerTest : public testing::Test { class TypeDeterminerTest : public testing::Test {
public: public:
void SetUp() { td_ = std::make_unique<TypeDeterminer>(&ctx_); } void SetUp() { td_ = std::make_unique<TypeDeterminer>(&ctx_); }
@ -69,6 +81,23 @@ class TypeDeterminerTest : public testing::Test {
std::unique_ptr<TypeDeterminer> td_; std::unique_ptr<TypeDeterminer> td_;
}; };
TEST_F(TypeDeterminerTest, Error_WithEmptySource) {
FakeStmt s;
s.set_source(Source{0, 0});
EXPECT_FALSE(td()->DetermineResultType(&s));
EXPECT_EQ(td()->error(), "unknown statement type for type determination");
}
TEST_F(TypeDeterminerTest, Stmt_Error_Unknown) {
FakeStmt s;
s.set_source(Source{2, 30});
EXPECT_FALSE(td()->DetermineResultType(&s));
EXPECT_EQ(td()->error(),
"2:30: unknown statement type for type determination");
}
TEST_F(TypeDeterminerTest, Stmt_Assign) { TEST_F(TypeDeterminerTest, Stmt_Assign) {
ast::type::F32Type f32; ast::type::F32Type f32;
ast::type::I32Type i32; ast::type::I32Type i32;
@ -410,6 +439,14 @@ TEST_F(TypeDeterminerTest, Stmt_VariableDecl) {
EXPECT_TRUE(init_ptr->result_type()->IsI32()); EXPECT_TRUE(init_ptr->result_type()->IsI32());
} }
TEST_F(TypeDeterminerTest, Expr_Error_Unknown) {
FakeExpr e;
e.set_source(Source{2, 30});
EXPECT_FALSE(td()->DetermineResultType(&e));
EXPECT_EQ(td()->error(), "2:30: unknown expression for type determination");
}
TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array) { TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array) {
ast::type::I32Type i32; ast::type::I32Type i32;
ast::type::F32Type f32; ast::type::F32Type f32;