diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 60600470f..41dc23462 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -586,6 +586,7 @@ typedef struct Decl_ bool no_scope : 1; bool escaping : 1; bool is_value : 1; + bool is_autoimport : 1; union { void *backend_ref; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 6e3e39a33..29441ce71 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -654,6 +654,7 @@ typedef enum ATTRIBUTE_REGCALL, ATTRIBUTE_FASTCALL, ATTRIBUTE_OVERLAP, + ATTRIBUTE_AUTOIMPORT, ATTRIBUTE_NONE, NUMBER_OF_ATTRIBUTES = ATTRIBUTE_NONE, } AttributeType; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 8c0ec88d9..c405e576c 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1157,6 +1157,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute [ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT, [ATTRIBUTE_NOSCOPE] = ATTR_MACRO, [ATTRIBUTE_ESCAPING] = ATTR_MACRO, + [ATTRIBUTE_AUTOIMPORT] = ATTR_MACRO | ATTR_FUNC, }; if ((attribute_domain[type] & domain) != domain) @@ -1481,6 +1482,9 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl) case ATTRIBUTE_NORETURN: SET_ATTR(attr_noreturn); case ATTRIBUTE_WEAK: SET_ATTR(attr_weak); case ATTRIBUTE_NAKED: SET_ATTR(attr_naked); + case ATTRIBUTE_AUTOIMPORT: + decl->is_autoimport = true; + break; default: UNREACHABLE } @@ -1571,6 +1575,9 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) had = decl->escaping; decl->escaping = true; break; + case ATTRIBUTE_AUTOIMPORT: + decl->is_autoimport = true; + break; default: UNREACHABLE } diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 4a0b423bf..7b741ce27 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -883,10 +883,28 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, // Already handled if (!decl_ok(decl)) return false; - if (decl->decl_kind == DECL_FUNC && !expr->identifier_expr.path && decl->module != context->unit->module) + if (decl->decl_kind == DECL_FUNC || decl->decl_kind == DECL_MACRO || decl->decl_kind == DECL_GENERIC) { - SEMA_ERROR(expr, "Functions from other modules, must be prefixed with the module name"); - return false; + if (decl->module != context->unit->module && !decl->is_autoimport && !expr->identifier_expr.path) + { + const char *message; + switch (decl->decl_kind) + { + case DECL_FUNC: + message = "Functions from other modules must be prefixed with the module name."; + break; + case DECL_MACRO: + message = "Macros from other modules must be prefixed with the module name."; + break; + case DECL_GENERIC: + message = "Generic functions from other modules must be prefixed with the module name."; + break; + default: + UNREACHABLE + } + SEMA_ERROR(expr, message); + return false; + } } if (decl->resolve_status != RESOLVE_DONE) { diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 39967c565..e7ef9cd79 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -214,6 +214,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_REGCALL] = KW_DEF("regcall"); attribute_list[ATTRIBUTE_FASTCALL] = KW_DEF("fastcall"); attribute_list[ATTRIBUTE_OVERLAP] = KW_DEF("overlap"); + attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("autoimport"); for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++) { diff --git a/test/test_suite/import/autoimport.c3 b/test/test_suite/import/autoimport.c3 new file mode 100644 index 000000000..9c089b497 --- /dev/null +++ b/test/test_suite/import/autoimport.c3 @@ -0,0 +1,36 @@ +module foo; + +fn int test() @autoimport +{ + return 1; +} + +macro int testm() @autoimport +{ + return 1; +} + +fn int test1() +{ + return 1; +} + +macro int testm1() +{ + return 1; +} + +module bar; +import foo; + +fn void main() +{ + @testm(); + test(); +} + +fn void main2() +{ + @testm1(); // #error: Macros from other modules must be prefixed with the module nam + test1(); // #error: Functions from other modules must be prefixed with the module nam +} \ No newline at end of file diff --git a/test/test_suite/macros/macro_import_res_private.c3t b/test/test_suite/macros/macro_import_res_private.c3t index 620e3e1b1..4b64c8f29 100644 --- a/test/test_suite/macros/macro_import_res_private.c3t +++ b/test/test_suite/macros/macro_import_res_private.c3t @@ -14,7 +14,7 @@ module baz; import bar; fn void test() { - @bar1(); + @bar::bar1(); } /* #expect: baz.ll