diff --git a/src/source.h b/src/source.h index b77fa022d0..9b6e74ce16 100644 --- a/src/source.h +++ b/src/source.h @@ -114,9 +114,19 @@ class Source { /// @param content the source file content inline Source(const Range& rng, const std::string& path, - FileContent* content = nullptr) + const FileContent* content = nullptr) : range(rng), file_path(path), file_content(content) {} + /// @returns a Source that points to the begin range of this Source. + inline Source Begin() const { + return Source(Range{range.begin}, file_path, file_content); + } + + /// @returns a Source that points to the end range of this Source. + inline Source End() const { + return Source(Range{range.end}, file_path, file_content); + } + /// range is the span of text this source refers to in #file_path Range range; /// file is the optional file path this source refers to diff --git a/src/type_determiner.cc b/src/type_determiner.cc index 5bce843bbb..fd334c255a 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -406,9 +406,6 @@ bool TypeDeterminer::DetermineBitcast(ast::BitcastExpression* expr) { } bool TypeDeterminer::DetermineCall(ast::CallExpression* call) { - if (!DetermineResultType(call->func())) { - return false; - } if (!DetermineResultType(call->params())) { return false; } @@ -436,8 +433,8 @@ bool TypeDeterminer::DetermineCall(ast::CallExpression* call) { auto callee_func_it = symbol_to_function_.find(ident->symbol()); if (callee_func_it == symbol_to_function_.end()) { - diagnostics_.add_error("unable to find called function: " + name, - call->source()); + diagnostics_.add_error( + "v-0006: unable to find called function: " + name, call->source()); return false; } auto* callee_func = callee_func_it->second; @@ -558,14 +555,16 @@ bool TypeDeterminer::DetermineIdentifier(ast::IdentifierExpression* expr) { auto iter = symbol_to_function_.find(symbol); if (iter != symbol_to_function_.end()) { - // Identifier is to a function, which has no type (currently). - return true; + diagnostics_.add_error("missing '(' for function call", + expr->source().End()); + return false; } std::string name = builder_->Symbols().NameFor(symbol); if (MatchIntrinsicType(name) != IntrinsicType::kNone) { - // Identifier is to an intrinsic function, which has no type (currently). - return true; + diagnostics_.add_error("missing '(' for intrinsic call", + expr->source().End()); + return false; } diagnostics_.add_error( diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc index 3fd39515c9..801260d4f9 100644 --- a/src/type_determiner_test.cc +++ b/src/type_determiner_test.cc @@ -396,9 +396,8 @@ TEST_F(TypeDeterminerTest, Stmt_Call_undeclared) { EXPECT_FALSE(td()->Determine()); - EXPECT_EQ( - td()->error(), - "12:34 error: v-0006: identifier must be declared before use: func"); + EXPECT_EQ(td()->error(), + "12:34 error: v-0006: unable to find called function: func"); } TEST_F(TypeDeterminerTest, Stmt_VariableDecl) { @@ -692,6 +691,27 @@ TEST_F(TypeDeterminerTest, Expr_Call_Intrinsic) { EXPECT_TRUE(TypeOf(call)->Is()); } +TEST_F(TypeDeterminerTest, Expr_DontCall_Function) { + Func("func", {}, ty.void_(), {}, {}); + auto* ident = create( + Source{{Source::Location{3, 3}, Source::Location{3, 8}}}, + Symbols().Register("func")); + WrapInFunction(ident); + + EXPECT_FALSE(td()->Determine()); + EXPECT_EQ(td()->error(), "3:8 error: missing '(' for function call"); +} + +TEST_F(TypeDeterminerTest, Expr_DontCall_Intrinsic) { + auto* ident = create( + Source{{Source::Location{3, 3}, Source::Location{3, 8}}}, + Symbols().Register("round")); + WrapInFunction(ident); + + EXPECT_FALSE(td()->Determine()); + EXPECT_EQ(td()->error(), "3:8 error: missing '(' for intrinsic call"); +} + TEST_F(TypeDeterminerTest, Expr_Cast) { Global("name", ty.f32(), ast::StorageClass::kPrivate);