Skip to content

Commit

Permalink
Reject function prototypes without &cxxname.
Browse files Browse the repository at this point in the history
  • Loading branch information
evantypanski committed Mar 6, 2025
1 parent 8966228 commit 7be4020
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 33 deletions.
6 changes: 5 additions & 1 deletion hilti/toolchain/src/compiler/validator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,18 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn {
void operator()(Function* n) final {
checkNodeAttributes(n->nodeTag(), n->attributes(), "function");

auto is_hook = n->ftype()->flavor() == type::function::Flavor::Hook;
if ( auto attrs = n->attributes() ) {
if ( auto prio = attrs->find(hilti::attribute::Kind::Priority) ) {
if ( n->ftype()->flavor() != type::function::Flavor::Hook )
if ( ! is_hook )
error("only hooks can have priorities", n);

else if ( auto x = prio->valueAsInteger(); ! x )
error(x.error(), n);
}

if ( ! n->body() && ! is_hook && ! attrs->has(hilti::attribute::Kind::Cxxname) )
error(fmt("function '%s' must have a body or be declared with &cxxname", n->id()), n);
}
}

Expand Down
52 changes: 26 additions & 26 deletions tests/Baseline/hilti.ast.imported-id/output
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
[debug/compiler] [HILTI] building scopes
[debug/compiler] [HILTI] resolving AST
[debug/resolver] -> [T11] type::Bool <no-type-id> | bool (foo.hlt:6:20-6:23)
[debug/resolver] [foo.hlt:9:20-9:23] type::Name "Foo1" -> set resolved type to T11
[debug/resolver] [foo.hlt:9:21-9:24] type::Name "Foo1" -> set resolved type to T11
[debug/resolver] -> [T12] type::Vector <no-type-id> | vector<bytes> (hilti.hlt:16:24-16:36)
[debug/resolver] [hilti.hlt:20:12-20:19] type::Name "Captures" -> set resolved type to T12
[debug/resolver] -> [T13] type::Library <no-type-id> | __library_type("::hilti::rt::Profiler") (hilti.hlt:17:24-17:60)
Expand All @@ -47,16 +47,16 @@
[debug/resolver] [foo.hlt:6:20-6:23] type::Bool "bool" -> set type's declaration to D1
[debug/resolver] [foo.hlt:7:1-7:29] declaration::Type "public type Foo2 = Bar::Bar1;" -> set declaration's canonical ID to Foo::Foo2
[debug/resolver] [foo.hlt:7:1-7:29] declaration::Type "public type Foo2 = Bar::Bar1;" -> set declaration's fully qualified ID to Foo::Foo2
[debug/resolver] [foo.hlt:9:20-9:27] declaration::Parameter "bool foo" -> set declaration's canonical ID to Foo::foo
[debug/resolver] [foo.hlt:9:20-9:27] declaration::Parameter "bool foo" -> set declaration's fully qualified ID to foo
[debug/resolver] [foo.hlt:9:30-9:42] declaration::Parameter "Bar::Bar1 bar" -> set declaration's canonical ID to Foo::bar
[debug/resolver] [foo.hlt:9:30-9:42] declaration::Parameter "Bar::Bar1 bar" -> set declaration's fully qualified ID to bar
[debug/resolver] [foo.hlt:9:1-9:44] declaration::Function "declare function string foo(bool foo, Bar::Bar1 bar);" -> set declaration's canonical ID to Foo::foo_2
[debug/resolver] [foo.hlt:9:1-9:44] declaration::Function "declare function string foo(bool foo, Bar::Bar1 bar);" -> set declaration's fully qualified ID to Foo::foo
[debug/resolver] [foo.hlt:2:1-11:1] declaration::Module "module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; declare function string foo(bool foo, Bar::Bar1 bar); }" -> set declaration's fully qualified ID to Foo
[debug/resolver] [foo.hlt:2:1-11:1] declaration::Module "module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; declare function string foo(bool foo, Bar::Bar1 bar); }" -> set module's canonical ID to Foo
[debug/resolver] -> [D2] declaration::Module Foo | module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; declare function string foo(bool foo, Bar::Bar1 bar); } (foo.hlt:2:1-11:1)
[debug/resolver] [foo.hlt:2:1-11:1] declaration::Module "module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; declare function string foo(bool foo, Bar::Bar1 bar); }" -> set module's declaration index to D2
[debug/resolver] [foo.hlt:9:21-9:28] declaration::Parameter "bool foo" -> set declaration's canonical ID to Foo::foo
[debug/resolver] [foo.hlt:9:21-9:28] declaration::Parameter "bool foo" -> set declaration's fully qualified ID to foo
[debug/resolver] [foo.hlt:9:31-9:43] declaration::Parameter "Bar::Bar1 bar" -> set declaration's canonical ID to Foo::bar
[debug/resolver] [foo.hlt:9:31-9:43] declaration::Parameter "Bar::Bar1 bar" -> set declaration's fully qualified ID to bar
[debug/resolver] [foo.hlt:9:1-9:47] declaration::Function "function string foo(bool foo, Bar::Bar1 bar) { }" -> set declaration's canonical ID to Foo::foo_2
[debug/resolver] [foo.hlt:9:1-9:47] declaration::Function "function string foo(bool foo, Bar::Bar1 bar) { }" -> set declaration's fully qualified ID to Foo::foo
[debug/resolver] [foo.hlt:2:1-11:1] declaration::Module "module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; function string foo(bool foo, Bar::Bar1 bar) { } }" -> set declaration's fully qualified ID to Foo
[debug/resolver] [foo.hlt:2:1-11:1] declaration::Module "module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; function string foo(bool foo, Bar::Bar1 bar) { } }" -> set module's canonical ID to Foo
[debug/resolver] -> [D2] declaration::Module Foo | module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; function string foo(bool foo, Bar::Bar1 bar) { } } (foo.hlt:2:1-11:1)
[debug/resolver] [foo.hlt:2:1-11:1] declaration::Module "module Foo { import Bar; public type Foo1 = bool; public type Foo2 = Bar::Bar1; function string foo(bool foo, Bar::Bar1 bar) { } }" -> set module's declaration index to D2
[debug/resolver] [hilti.hlt:6:1-6:21] declaration::Property "" -> set declaration's canonical ID to hilti::%skip-implementation
[debug/resolver] [hilti.hlt:6:1-6:21] declaration::Property "" -> set declaration's fully qualified ID to hilti::%skip-implementation
[debug/resolver] [hilti.hlt:8:24-8:42] declaration::Constant "const enum { LSB0 = 0, MSB0 = 1 } LSB0 = <anon-enum>::LSB0;" -> set declaration's canonical ID to hilti::LSB0
Expand Down Expand Up @@ -304,16 +304,16 @@
[debug/resolver] [bar.hlt:6:20-6:25] type::String "string" -> set type's declaration to D21
[debug/resolver] [bar.hlt:7:1-7:29] declaration::Type "public type Bar2 = Foo::Foo1;" -> set declaration's canonical ID to Bar::Bar2
[debug/resolver] [bar.hlt:7:1-7:29] declaration::Type "public type Bar2 = Foo::Foo1;" -> set declaration's fully qualified ID to Bar::Bar2
[debug/resolver] [bar.hlt:9:20-9:27] declaration::Parameter "Bar1 bar" -> set declaration's canonical ID to Bar::bar
[debug/resolver] [bar.hlt:9:20-9:27] declaration::Parameter "Bar1 bar" -> set declaration's fully qualified ID to bar
[debug/resolver] [bar.hlt:9:30-9:42] declaration::Parameter "Foo::Foo1 foo" -> set declaration's canonical ID to Bar::foo
[debug/resolver] [bar.hlt:9:30-9:42] declaration::Parameter "Foo::Foo1 foo" -> set declaration's fully qualified ID to foo
[debug/resolver] [bar.hlt:9:1-9:44] declaration::Function "declare function string bar(Bar1 bar, Foo::Foo1 foo);" -> set declaration's canonical ID to Bar::bar_2
[debug/resolver] [bar.hlt:9:1-9:44] declaration::Function "declare function string bar(Bar1 bar, Foo::Foo1 foo);" -> set declaration's fully qualified ID to Bar::bar
[debug/resolver] [bar.hlt:2:1-11:1] declaration::Module "module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; declare function string bar(Bar1 bar, Foo::Foo1 foo); }" -> set declaration's fully qualified ID to Bar
[debug/resolver] [bar.hlt:2:1-11:1] declaration::Module "module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; declare function string bar(Bar1 bar, Foo::Foo1 foo); }" -> set module's canonical ID to Bar
[debug/resolver] -> [D22] declaration::Module Bar | module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; declare function string bar(Bar1 bar, Foo::Foo1 foo); } (bar.hlt:2:1-11:1)
[debug/resolver] [bar.hlt:2:1-11:1] declaration::Module "module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; declare function string bar(Bar1 bar, Foo::Foo1 foo); }" -> set module's declaration index to D22
[debug/resolver] [bar.hlt:9:21-9:28] declaration::Parameter "Bar1 bar" -> set declaration's canonical ID to Bar::bar
[debug/resolver] [bar.hlt:9:21-9:28] declaration::Parameter "Bar1 bar" -> set declaration's fully qualified ID to bar
[debug/resolver] [bar.hlt:9:31-9:43] declaration::Parameter "Foo::Foo1 foo" -> set declaration's canonical ID to Bar::foo
[debug/resolver] [bar.hlt:9:31-9:43] declaration::Parameter "Foo::Foo1 foo" -> set declaration's fully qualified ID to foo
[debug/resolver] [bar.hlt:9:1-9:47] declaration::Function "function string bar(Bar1 bar, Foo::Foo1 foo) { }" -> set declaration's canonical ID to Bar::bar_2
[debug/resolver] [bar.hlt:9:1-9:47] declaration::Function "function string bar(Bar1 bar, Foo::Foo1 foo) { }" -> set declaration's fully qualified ID to Bar::bar
[debug/resolver] [bar.hlt:2:1-11:1] declaration::Module "module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; function string bar(Bar1 bar, Foo::Foo1 foo) { } }" -> set declaration's fully qualified ID to Bar
[debug/resolver] [bar.hlt:2:1-11:1] declaration::Module "module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; function string bar(Bar1 bar, Foo::Foo1 foo) { } }" -> set module's canonical ID to Bar
[debug/resolver] -> [D22] declaration::Module Bar | module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; function string bar(Bar1 bar, Foo::Foo1 foo) { } } (bar.hlt:2:1-11:1)
[debug/resolver] [bar.hlt:2:1-11:1] declaration::Module "module Bar { import Foo; public type Bar1 = string; public type Bar2 = Foo::Foo1; function string bar(Bar1 bar, Foo::Foo1 foo) { } }" -> set module's declaration index to D22
[debug/compiler] -> modified
[debug/compiler] processing ASTs, round 2
[debug/compiler] [HILTI] building scopes
Expand All @@ -322,11 +322,11 @@
[debug/compiler] [HILTI] resolving AST
[debug/resolver] -> [T17] type::String Bar::Bar1 | string (bar.hlt:6:20-6:25)
[debug/resolver] [foo.hlt:7:20-7:28] type::Name "Bar::Bar1" -> set resolved type to T17
[debug/resolver] [foo.hlt:9:30-9:38] type::Name "Bar::Bar1" -> set resolved type to T17
[debug/resolver] [foo.hlt:9:31-9:39] type::Name "Bar::Bar1" -> set resolved type to T17
[debug/resolver] [bar.hlt:7:20-7:28] type::Name "Foo::Foo1" -> set resolved type to T11
[debug/resolver] [bar.hlt:9:20-9:23] type::Name "Bar1" -> set resolved type to T17
[debug/resolver] [bar.hlt:9:30-9:38] type::Name "Foo::Foo1" -> set resolved type to T11
[debug/resolver] [foo.hlt:9:1-9:44] declaration::Function "declare function string foo(bool foo, string bar);" -> creating function call operator
[debug/resolver] [bar.hlt:9:21-9:24] type::Name "Bar1" -> set resolved type to T17
[debug/resolver] [bar.hlt:9:31-9:39] type::Name "Foo::Foo1" -> set resolved type to T11
[debug/resolver] [foo.hlt:9:1-9:47] declaration::Function "function string foo(bool foo, string bar) { }" -> creating function call operator
[debug/resolver] [hilti.hlt:8:24-8:42] declaration::Constant "const hilti::BitOrder LSB0 = hilti::BitOrder::LSB0;" -> set declaration's fully qualified ID to hilti::BitOrder::LSB0
[debug/resolver] [hilti.hlt:8:24-8:42] declaration::Constant "const hilti::BitOrder MSB0 = hilti::BitOrder::MSB0;" -> set declaration's fully qualified ID to hilti::BitOrder::MSB0
[debug/resolver] [hilti.hlt:8:24-8:42] declaration::Constant "const hilti::BitOrder Undef = hilti::BitOrder::Undef;" -> set declaration's fully qualified ID to hilti::BitOrder::Undef
Expand Down Expand Up @@ -364,7 +364,7 @@
[debug/resolver] [hilti.hlt:25:5-25:29] declaration::Field "uint<64> num_data_chunks;" -> set declaration's fully qualified ID to hilti::StreamStatistics::num_data_chunks
[debug/resolver] [hilti.hlt:26:5-26:27] declaration::Field "uint<64> num_gap_bytes;" -> set declaration's fully qualified ID to hilti::StreamStatistics::num_gap_bytes
[debug/resolver] [hilti.hlt:27:5-27:28] declaration::Field "uint<64> num_gap_chunks;" -> set declaration's fully qualified ID to hilti::StreamStatistics::num_gap_chunks
[debug/resolver] [bar.hlt:9:1-9:44] declaration::Function "declare function string bar(string bar, bool foo);" -> creating function call operator
[debug/resolver] [bar.hlt:9:1-9:47] declaration::Function "function string bar(string bar, bool foo) { }" -> creating function call operator
[debug/compiler] -> modified
[debug/compiler] processing ASTs, round 3
[debug/compiler] [HILTI] building scopes
Expand Down
3 changes: 3 additions & 0 deletions tests/Baseline/hilti.validation.function-proto-fail/output
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
[error] <...>/function-proto-fail.hlt:8:9-8:19: function 'fail' must have a body or be declared with &cxxname
[error] hiltic: aborting after errors
3 changes: 2 additions & 1 deletion tests/Baseline/spicy.tools.doc-strings/output
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ global int<32> g2 = int32(2);
global int<32> g3;

## Function 1.
declare function void foo1();
function void foo1() {
}

## Function 2.
function void foo2() {
Expand Down
2 changes: 1 addition & 1 deletion tests/hilti/ast/basic-module.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ module Foo {

type X = bool;

declare string foo(real bar);
function string foo(real bar) {}

}
4 changes: 2 additions & 2 deletions tests/hilti/ast/imported-id.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Bar;
public type Foo1 = bool;
public type Foo2 = Bar::Bar1;

declare string foo(Foo1 foo, Bar::Bar1 bar);
function string foo(Foo1 foo, Bar::Bar1 bar) {}

}

Expand All @@ -27,7 +27,7 @@ import Foo;
public type Bar1 = string;
public type Bar2 = Foo::Foo1;

declare string bar(Bar1 bar, Foo::Foo1 foo);
function string bar(Bar1 bar, Foo::Foo1 foo) {}

}

Expand Down
2 changes: 1 addition & 1 deletion tests/hilti/hiltic/jit/broken-hilti-linking.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# compiler, we just check for a keyword being in there.
module Test {

declare public time does_not_exist();
declare public time does_not_exist() &cxxname="does_not_exist";

does_not_exist();

Expand Down
10 changes: 10 additions & 0 deletions tests/hilti/validation/function-proto-fail.hlt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# @TEST-EXEC-FAIL: ${HILTIC} -j %INPUT > output 2>&1
# @TEST-EXEC: btest-diff output
#
# @TEST-DOC: Tests that function prototypes must have &cxxname

module Foo {

declare void fail();

}
2 changes: 1 addition & 1 deletion tests/spicy/tools/doc-strings.spicy
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const c1 = 1;
const c2: int32 = 2;

## Function 1.
function foo1();
function foo1() {}

## Function 2.
function foo2() {}

0 comments on commit 7be4020

Please sign in to comment.