mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Prevent ordering issues with "builtin" by resolving it early.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -966,9 +966,11 @@ 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;
|
||||
}
|
||||
@@ -976,11 +978,11 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl)
|
||||
/**
|
||||
* 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;
|
||||
@@ -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)
|
||||
{
|
||||
@@ -1006,6 +1009,9 @@ 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;
|
||||
@@ -1013,6 +1019,12 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visib
|
||||
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);
|
||||
@@ -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, ¶m->attributes, NULL, NULL)) return false;
|
||||
if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL)) return false;
|
||||
if (!no_name)
|
||||
{
|
||||
if (try_consume(c, TOKEN_EQ))
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.632"
|
||||
#define COMPILER_VERSION "0.4.633"
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user