Skip to content

Commit

Permalink
Prevent ordering issues with "builtin" by resolving it early.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Sep 5, 2023
1 parent f8fa9a0 commit cfe5c64
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 20 deletions.
13 changes: 13 additions & 0 deletions src/compiler/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,19 @@ bool decl_is_local(Decl *decl)
return !decl->is_external_visible && decl->visibility != VISIBLE_PUBLIC && !decl->is_export;
}

bool decl_needs_prefix(Decl *decl)
{
switch (decl->decl_kind)
{
case DECL_VAR:
case DECL_FUNC:
case DECL_MACRO:
return !decl->is_autoimport;
default:
return false;
}
}

Decl *decl_find_enum_constant(Decl *decl, const char *name)
{
VECEACH(decl->enums.values, i)
Expand Down
1 change: 1 addition & 0 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,7 @@ static inline DeclKind decl_from_token(TokenType type);
static inline bool decl_is_var_local(Decl *decl);
bool decl_is_ct_var(Decl *decl);
Decl *decl_find_enum_constant(Decl *decl, const char *name);
bool decl_needs_prefix(Decl *decl);
AlignSize decl_find_member_offset(Decl *decl, Decl *member);
bool decl_is_externally_visible(Decl *decl);
bool decl_is_local(Decl *decl);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parse_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ static Expr *parse_lambda(ParseContext *c, Expr *left)
sig->params = decls;
sig->rtype = return_type ? type_infoid(return_type) : 0;
sig->variadic = variadic;
if (!parse_attributes(c, &func->attributes, NULL, NULL)) return poisoned_expr;
if (!parse_attributes(c, &func->attributes, NULL, NULL, NULL)) return poisoned_expr;

if (tok_is(c, TOKEN_IMPLIES))
{
Expand Down
34 changes: 23 additions & 11 deletions src/compiler/parse_global.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ bool parse_module(ParseContext *c, AstId contracts)
Visibility visibility = VISIBLE_PUBLIC;
Attr** attrs = NULL;
bool is_cond;
if (!parse_attributes(c, &attrs, &visibility, &is_cond)) return false;
if (!parse_attributes(c, &attrs, &visibility, NULL, &is_cond)) return false;
FOREACH_BEGIN(Attr *attr, attrs)
if (attr->is_custom) RETURN_SEMA_ERROR(attr, "Custom attributes cannot be used with 'module'.");
switch (attr->attr_kind)
Expand Down Expand Up @@ -732,7 +732,7 @@ Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type)
Decl *decl = decl_new_var_current(c, type, VARDECL_LOCAL);
advance(c);

if (!parse_attributes(c, &decl->attributes, NULL, NULL)) return poisoned_decl;
if (!parse_attributes(c, &decl->attributes, NULL, NULL, NULL)) return poisoned_decl;
if (tok_is(c, TOKEN_EQ))
{
if (!decl)
Expand Down Expand Up @@ -796,7 +796,7 @@ Decl *parse_const_declaration(ParseContext *c, bool is_global)
}
else
{
if (!parse_attributes(c, &decl->attributes, NULL, NULL)) return poisoned_decl;
if (!parse_attributes(c, &decl->attributes, NULL, NULL, NULL)) return poisoned_decl;
}

// Required initializer
Expand Down Expand Up @@ -966,21 +966,23 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl)
if (decl->decl_kind == DECL_FUNC) decl->func_decl.attr_test = c->unit->test_by_default;
if (decl->decl_kind == DECL_FUNC) decl->func_decl.attr_benchmark = c->unit->benchmark_by_default;
decl->is_export = c->unit->export_by_default;
bool is_builtin = false;
bool is_cond;
if (!parse_attributes(c, &decl->attributes, &visibility, &is_cond)) return false;
if (!parse_attributes(c, &decl->attributes, &visibility, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond)) return false;
decl->is_cond = is_cond;
decl->is_autoimport = is_builtin;
decl->visibility = visibility;
return true;
}

/**
* attribute_list ::= attribute*
*
* Patch visibility attributes immediately.
* Patch visibility and builtin attributes immediately.
*
* @return true if parsing succeeded, false if recovery is needed
*/
bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *cond_ref)
bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref)
{
Visibility visibility = -1;
if (cond_ref) *cond_ref = false;
Expand All @@ -989,6 +991,7 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib
Attr *attr;
if (!parse_attribute(c, &attr, false)) return false;
if (!attr) return true;
bool parsed_builtin = false;
Visibility parsed_visibility = -1;
if (!attr->is_custom)
{
Expand All @@ -1006,13 +1009,22 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib
case ATTRIBUTE_LOCAL:
parsed_visibility = VISIBLE_LOCAL;
break;
case ATTRIBUTE_BUILTIN:
parsed_builtin = true;
break;
case ATTRIBUTE_IF:
if (!cond_ref) RETURN_SEMA_ERROR(attr, "'%s' cannot be used here.", attr->name);
*cond_ref = true;
break;
default:
break;
}
if (parsed_builtin)
{
if (!builtin_ref) RETURN_SEMA_ERROR(attr, "'@builtin' cannot be used here.");
*builtin_ref = true;
continue;
}
if (parsed_visibility != -1)
{
if (!visibility_ref) RETURN_SEMA_ERROR(attr, "'%s' cannot be used here.", attr->name);
Expand Down Expand Up @@ -1358,7 +1370,7 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params,
}
Decl *param = decl_new_var(name, span, type, param_kind);
param->var.type_info = type;
if (!parse_attributes(c, &param->attributes, NULL, NULL)) return false;
if (!parse_attributes(c, &param->attributes, NULL, NULL, NULL)) return false;
if (!no_name)
{
if (try_consume(c, TOKEN_EQ))
Expand Down Expand Up @@ -1457,7 +1469,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent)
else
{
bool is_cond;
if (!parse_attributes(c, &member->attributes, NULL, &is_cond)) return false;
if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond)) return false;
member->is_cond = true;
if (!parse_struct_body(c, member)) return decl_poison(parent);
}
Expand Down Expand Up @@ -1499,7 +1511,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent)
}
advance(c);
bool is_cond;
if (!parse_attributes(c, &member->attributes, NULL, &is_cond)) return false;
if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond)) return false;
member->is_cond = true;
if (!try_consume(c, TOKEN_COMMA)) break;
if (was_inline)
Expand Down Expand Up @@ -1930,7 +1942,7 @@ static inline Decl *parse_def_attribute(ParseContext *c)
CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl);

bool is_cond;
if (!parse_attributes(c, &attributes, NULL, &is_cond)) return poisoned_decl;
if (!parse_attributes(c, &attributes, NULL, NULL, &is_cond)) return poisoned_decl;
CONSUME_OR_RET(TOKEN_RBRACE, poisoned_decl);
decl->attr_decl.attrs = attributes;
decl->is_cond = is_cond;
Expand Down Expand Up @@ -2311,7 +2323,7 @@ static inline Decl *parse_static_top_level(ParseContext *c)
advance(c);
Attr *attr = NULL;
bool is_cond;
if (!parse_attributes(c, &init->attributes, NULL, &is_cond)) return poisoned_decl;
if (!parse_attributes(c, &init->attributes, NULL, NULL, &is_cond)) return poisoned_decl;
init->is_cond = is_cond;
ASSIGN_ASTID_OR_RET(init->xxlizer.init, parse_compound_stmt(c), poisoned_decl);
RANGE_EXTEND_PREV(init);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos)

bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos);

bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *cond_ref);
bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref);

bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type);
Expr *parse_ct_expression_list(ParseContext *c, bool allow_decl);
Expand Down
4 changes: 1 addition & 3 deletions src/compiler/sema_decls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
case ATTRIBUTE_PRIVATE:
case ATTRIBUTE_PUBLIC:
case ATTRIBUTE_LOCAL:
case ATTRIBUTE_BUILTIN:
// These are pseudo-attributes.
UNREACHABLE;
case ATTRIBUTE_DEPRECATED:
Expand Down Expand Up @@ -1929,9 +1930,6 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
assert(domain == ATTR_FUNC);
decl->func_decl.attr_naked = true;
break;
case ATTRIBUTE_BUILTIN:
decl->is_autoimport = true;
break;
case ATTRIBUTE_OVERLAP:
decl->bitstruct.overlap = true;
break;
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/sema_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,10 +908,10 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
return false;
}

if (decl->decl_kind == DECL_VAR || decl->decl_kind == DECL_FUNC || decl->decl_kind == DECL_MACRO)
if (decl_needs_prefix(decl))
{
if (!sema_analyse_decl(context, decl)) return false;
if (decl->unit->module != context->unit->module && !decl->is_autoimport && !expr->identifier_expr.path)
if (decl->unit->module != context->unit->module && !expr->identifier_expr.path)
{
const char *message;
switch (decl->decl_kind)
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/sema_name_resolution.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ static void sema_report_error_on_decl(Decl *found, NameResolve *name_resolve)
}
else
{
if (decl_needs_prefix(found))
{
sema_error_at(span, "The %s needs a path prefix (e.g. '%s::%s').", symbol_type, found_path, symbol);
return;
}
sema_error_at(span,
"The %s '%s' is defined in both '%s' and '%s', please use either "
"%s::%s or %s::%s to resolve the ambiguity.",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/sema_passes.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ void sema_process_includes(CompilationUnit *unit)
void sema_analysis_pass_register_global_declarations(Module *module)
{
DEBUG_LOG("Pass: Register globals for module '%s'.", module->name->module);
if (str_eq("std::core::env", module->name->module))
{
printf("");
}
VECEACH(module->units, index)
{
CompilationUnit *unit = module->units[index];
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define COMPILER_VERSION "0.4.632"
#define COMPILER_VERSION "0.4.633"
2 changes: 1 addition & 1 deletion test/test_suite/visibility/ambiguous_var.c3t
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ fn void test2()
c = foo::b;
c = bar::b;
c = foo::a;
c = b; // #error: global variable 'b' is defined in both 'foo' and 'bar', please use either foo::b or bar::b to resolve the ambiguity
c = b; // #error: global variable needs a path prefix (e.g. 'foo::b')
}

0 comments on commit cfe5c64

Please sign in to comment.