mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Fix issue testing if something is global. Remove ScopeId. Adding comments to code.
This commit is contained in:
@@ -35,6 +35,10 @@ Decl *decl_new(DeclKind decl_kind, const char *name, SourceSpan span)
|
||||
return decl;
|
||||
}
|
||||
|
||||
bool decl_is_deprecated(Decl *decl)
|
||||
{
|
||||
return decl->resolved_attributes && decl->attrs_resolved && decl->attrs_resolved->deprecated;
|
||||
}
|
||||
|
||||
// Check if local or parameter $foo/$Foo
|
||||
bool decl_is_ct_var(Decl *decl)
|
||||
@@ -43,12 +47,12 @@ bool decl_is_ct_var(Decl *decl)
|
||||
return decl_var_kind_is_ct(decl->var.kind);
|
||||
}
|
||||
|
||||
Decl *decl_new_with_type(const char *name, SourceSpan loc, DeclKind decl_type)
|
||||
Decl *decl_new_with_type(const char *name, SourceSpan span, DeclKind decl_type)
|
||||
{
|
||||
Decl *decl = decl_calloc();
|
||||
decl->decl_kind = decl_type;
|
||||
decl->name = name;
|
||||
decl->span = loc;
|
||||
decl->span = span;
|
||||
TypeKind kind = TYPE_POISONED;
|
||||
switch (decl_type)
|
||||
{
|
||||
@@ -95,6 +99,7 @@ const char *decl_safe_name(Decl *decl)
|
||||
if (decl->name) return decl->name;
|
||||
return decl_to_name(decl);
|
||||
}
|
||||
|
||||
const char *decl_to_name(Decl *decl)
|
||||
{
|
||||
const char *name = decl_to_a_name(decl);
|
||||
@@ -155,9 +160,9 @@ const char *decl_to_a_name(Decl *decl)
|
||||
}
|
||||
|
||||
|
||||
Decl *decl_new_var(const char *name, SourceSpan loc, TypeInfo *type, VarDeclKind kind)
|
||||
Decl *decl_new_var(const char *name, SourceSpan span, TypeInfo *type, VarDeclKind kind)
|
||||
{
|
||||
Decl *decl = decl_new(DECL_VAR, name, loc);
|
||||
Decl *decl = decl_new(DECL_VAR, name, span);
|
||||
decl->var.kind = kind;
|
||||
decl->var.type_info = type ? type_infoid(type) : 0;
|
||||
return decl;
|
||||
@@ -173,7 +178,7 @@ Decl *decl_new_generated_var(Type *type, VarDeclKind kind, SourceSpan span)
|
||||
decl->var.is_temp = true;
|
||||
decl->type = type;
|
||||
decl->alignment = type ? type_alloca_alignment(type) : 0;
|
||||
ASSERT(!type || !type_is_user_defined(type) || type->decl->resolve_status == RESOLVE_DONE);
|
||||
ASSERT_AT(span, !type || !type_is_user_defined(type) || type->decl->resolve_status == RESOLVE_DONE);
|
||||
decl->var.type_info = type_info_id_new_base(type, span);
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return decl;
|
||||
@@ -292,8 +297,8 @@ AttributeType attribute_by_name(const char *name)
|
||||
return ATTRIBUTE_NONE;
|
||||
}
|
||||
|
||||
|
||||
void decl_append_links_to_global(Decl *decl)
|
||||
// Look for the @link directive, if a decl is codegen then add it to the linking process.
|
||||
void decl_append_links_to_global_during_codegen(Decl *decl)
|
||||
{
|
||||
CompilationUnit *unit = decl->unit;
|
||||
if (unit && unit->links)
|
||||
@@ -310,16 +315,22 @@ void decl_append_links_to_global(Decl *decl)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the expected number of elements needed for an initializer
|
||||
* by folding any anonymous structs and unions.
|
||||
*/
|
||||
int decl_count_elements(Decl *structlike)
|
||||
{
|
||||
int elements = 0;
|
||||
Decl **members = structlike->strukt.members;
|
||||
unsigned member_size = vec_size(members);
|
||||
if (member_size == 0) return 0;
|
||||
// In the case we have a union, we only count the first element.
|
||||
if (structlike->decl_kind == DECL_UNION) member_size = 1;
|
||||
for (unsigned i = 0; i < member_size; i++)
|
||||
{
|
||||
Decl *member = members[i];
|
||||
// Recursively count the anonymous struct/unions
|
||||
if (member->decl_kind != DECL_VAR && !member->name)
|
||||
{
|
||||
elements += decl_count_elements(member);
|
||||
@@ -330,6 +341,7 @@ int decl_count_elements(Decl *structlike)
|
||||
return elements;
|
||||
}
|
||||
|
||||
// This is used to check if a macro folds to a single compile time value.
|
||||
bool ast_is_compile_time(Ast *ast)
|
||||
{
|
||||
switch (ast->ast_kind)
|
||||
@@ -341,6 +353,7 @@ bool ast_is_compile_time(Ast *ast)
|
||||
if (!ast->return_stmt.expr) return true;
|
||||
return expr_is_runtime_const(ast->return_stmt.expr);
|
||||
case AST_EXPR_STMT:
|
||||
// $a; is fine
|
||||
return expr_is_runtime_const(ast->expr_stmt);
|
||||
case AST_CT_COMPOUND_STMT:
|
||||
{
|
||||
@@ -365,14 +378,25 @@ bool ast_is_compile_time(Ast *ast)
|
||||
}
|
||||
}
|
||||
|
||||
// Should this declaration be linked externally
|
||||
bool decl_is_externally_visible(Decl *decl)
|
||||
{
|
||||
return decl->is_external_visible || decl->visibility == VISIBLE_PUBLIC || decl->is_export;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Is this declartion a global of some sort?
|
||||
* In other words a static, thread local, global constant or a global
|
||||
*/
|
||||
bool decl_is_global(Decl *ident)
|
||||
{
|
||||
switch (ident->decl_kind)
|
||||
{
|
||||
case DECL_FUNC: return true;
|
||||
case DECL_VAR: break;
|
||||
default: return false;
|
||||
}
|
||||
switch (ident->var.kind)
|
||||
{
|
||||
case VARDECL_LOCAL:
|
||||
@@ -396,11 +420,13 @@ bool decl_is_global(Decl *ident)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
// Is is @local or is it @private but never imported in some other compilation unit (module)
|
||||
bool decl_is_local(Decl *decl)
|
||||
{
|
||||
return !decl->is_external_visible && decl->visibility != VISIBLE_PUBLIC && !decl->is_export;
|
||||
}
|
||||
|
||||
// Does the decl need to be prefixed, or is it for some reason like a builtin.
|
||||
bool decl_needs_prefix(Decl *decl)
|
||||
{
|
||||
switch (decl->decl_kind)
|
||||
@@ -418,6 +444,7 @@ bool decl_needs_prefix(Decl *decl)
|
||||
}
|
||||
}
|
||||
|
||||
// Find a particular enum by name.
|
||||
Decl *decl_find_enum_constant(Decl *decl, const char *name)
|
||||
{
|
||||
FOREACH(Decl *, enum_constant, decl->enums.values)
|
||||
@@ -427,6 +454,7 @@ Decl *decl_find_enum_constant(Decl *decl, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
AlignSize decl_find_member_offset(Decl *decl, Decl *member)
|
||||
{
|
||||
static const AlignSize NO_MATCH = ~(AlignSize)0;
|
||||
@@ -442,7 +470,7 @@ AlignSize decl_find_member_offset(Decl *decl, Decl *member)
|
||||
default:
|
||||
return NO_MATCH;
|
||||
}
|
||||
ASSERT(members);
|
||||
ASSERT_SPAN(decl, members);
|
||||
unsigned list = vec_size(members);
|
||||
for (unsigned i = 0; i < list; i++)
|
||||
{
|
||||
@@ -460,9 +488,12 @@ AlignSize decl_find_member_offset(Decl *decl, Decl *member)
|
||||
return NO_MATCH;
|
||||
}
|
||||
|
||||
// Is it a for statement, AST_FOREACH should not reach here.
|
||||
bool ast_supports_continue(Ast *stmt)
|
||||
{
|
||||
ASSERT_SPAN(stmt, stmt->ast_kind != AST_FOREACH_STMT);
|
||||
if (stmt->ast_kind != AST_FOR_STMT) return false;
|
||||
// We don't support `continue` in a `do { };` statement.
|
||||
return stmt->for_stmt.cond || !stmt->flow.skip_first;
|
||||
}
|
||||
|
||||
@@ -511,7 +542,7 @@ void scratch_buffer_set_extern_decl_name(Decl *decl, bool clear)
|
||||
}
|
||||
if (decl->visibility == VISIBLE_LOCAL)
|
||||
{
|
||||
assert(module);
|
||||
ASSERT_SPAN(decl, module);
|
||||
scratch_buffer_printf(".%u", (unsigned)declid(decl));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ typedef int32_t IndexDiff;
|
||||
typedef int64_t ArrayIndex;
|
||||
typedef uint16_t StructIndex;
|
||||
typedef uint32_t AlignSize;
|
||||
typedef int32_t ScopeId;
|
||||
typedef uint64_t ArraySize;
|
||||
typedef uint64_t BitSize;
|
||||
typedef uint16_t FileId;
|
||||
@@ -1639,7 +1638,6 @@ typedef struct EndJump_
|
||||
|
||||
typedef struct DynamicScope_
|
||||
{
|
||||
ScopeId scope_id;
|
||||
bool allow_dead_code : 1;
|
||||
bool is_dead : 1;
|
||||
bool is_poisoned : 1;
|
||||
@@ -1789,7 +1787,6 @@ struct SemaContext_
|
||||
CallEnv call_env;
|
||||
Decl *current_macro;
|
||||
InliningSpan *inlined_at;
|
||||
ScopeId scope_id;
|
||||
unsigned macro_call_depth;
|
||||
// Jump tracking
|
||||
JumpTarget break_jump;
|
||||
@@ -2308,7 +2305,7 @@ const char *decl_safe_name(Decl *decl);
|
||||
const char *decl_to_name(Decl *decl);
|
||||
const char *decl_to_a_name(Decl *decl);
|
||||
int decl_count_elements(Decl *structlike);
|
||||
void decl_append_links_to_global(Decl *decl);
|
||||
void decl_append_links_to_global_during_codegen(Decl *decl);
|
||||
|
||||
INLINE bool decl_ok(Decl *decl);
|
||||
INLINE bool decl_poison(Decl *decl);
|
||||
@@ -2319,6 +2316,7 @@ static inline Decl *decl_raw(Decl *decl);
|
||||
static inline DeclKind decl_from_token(TokenType type);
|
||||
static inline bool decl_is_var_local(Decl *decl);
|
||||
bool decl_is_ct_var(Decl *decl);
|
||||
bool decl_is_deprecated(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);
|
||||
|
||||
@@ -541,7 +541,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
|
||||
// Skip real constants.
|
||||
if (!decl->type) return;
|
||||
|
||||
decl_append_links_to_global(decl);
|
||||
decl_append_links_to_global_during_codegen(decl);
|
||||
|
||||
LLVMValueRef init_value;
|
||||
|
||||
|
||||
@@ -673,7 +673,7 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
|
||||
{
|
||||
ASSERT_SPAN(decl, decl->decl_kind == DECL_FUNC);
|
||||
// Resolve function backend type for function.
|
||||
decl_append_links_to_global(decl);
|
||||
decl_append_links_to_global_during_codegen(decl);
|
||||
LLVMValueRef function = llvm_get_ref(c, decl);
|
||||
decl->backend_ref = function;
|
||||
if (decl->attrs_resolved && decl->attrs_resolved->section)
|
||||
|
||||
@@ -201,7 +201,7 @@ INLINE Attr* attr_find_kind(Attr **attrs, AttributeType attr_type)
|
||||
INLINE void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *decl, SourceSpan span)
|
||||
{
|
||||
ASSERT(decl->resolve_status == RESOLVE_DONE);
|
||||
if (!decl->resolved_attributes || !decl->attrs_resolved || !decl->attrs_resolved->deprecated) return;
|
||||
if (!decl_is_deprecated(decl)) return;
|
||||
if (context->call_env.ignore_deprecation) return;
|
||||
const char *msg = decl->attrs_resolved->deprecated;
|
||||
|
||||
|
||||
@@ -659,7 +659,6 @@ void sema_analysis_pass_decls(Module *module)
|
||||
context.active_scope = (DynamicScope)
|
||||
{
|
||||
.depth = 0,
|
||||
.scope_id = 0,
|
||||
.label_start = 0,
|
||||
.current_local = 0,
|
||||
};
|
||||
|
||||
@@ -298,7 +298,7 @@ static inline bool sema_analyse_continue_stmt(SemaContext *context, Ast *stateme
|
||||
// Continue can only be used with "for" statements, skipping the "do { };" statement
|
||||
if (!ast_supports_continue(jump_target.target))
|
||||
{
|
||||
RETURN_SEMA_ERROR(statement, "'continue' may only be used with 'for', 'while' and 'do-while' statements.");
|
||||
RETURN_SEMA_ERROR(statement, "'continue' may only be used with 'for', 'foreach', 'while' and 'do-while' statements.");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3338,8 +3338,10 @@ bool sema_analyse_contracts(SemaContext *context, AstId doc, AstId **asserts, So
|
||||
|
||||
bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
{
|
||||
// Stop if it's already poisoned.
|
||||
if (!decl_ok(func)) return false;
|
||||
|
||||
// Check the signature here we test for variadic raw, since we don't support it.
|
||||
Signature *signature = &func->func_decl.signature;
|
||||
if (signature->variadic == VARIADIC_RAW)
|
||||
{
|
||||
@@ -3347,8 +3349,12 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
" please use typed vaargs on the form 'int... args' or "
|
||||
"untyped vaargs on the form 'args...' instead.");
|
||||
}
|
||||
|
||||
// Pull out the prototype
|
||||
FunctionPrototype *prototype = func->type->function.prototype;
|
||||
ASSERT(prototype);
|
||||
ASSERT_SPAN(func, prototype);
|
||||
|
||||
// Set up the context for analysis
|
||||
context->original_inline_line = 0;
|
||||
context->original_module = NULL;
|
||||
context->call_env = (CallEnv) {
|
||||
@@ -3356,23 +3362,23 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
.is_naked_fn = func->func_decl.attr_naked,
|
||||
.kind = CALL_ENV_FUNCTION,
|
||||
.pure = func->func_decl.signature.attrs.is_pure,
|
||||
.ignore_deprecation = func->allow_deprecated || (func->resolved_attributes && func->attrs_resolved && func->attrs_resolved->deprecated && func->resolved_attributes && func->attrs_resolved->deprecated)
|
||||
.ignore_deprecation = func->allow_deprecated || decl_is_deprecated(func)
|
||||
};
|
||||
|
||||
context->rtype = prototype->rtype;
|
||||
context->macro_call_depth = 0;
|
||||
context->active_scope = (DynamicScope) {
|
||||
.scope_id = 0,
|
||||
.depth = 0,
|
||||
.label_start = 0,
|
||||
.current_local = 0
|
||||
};
|
||||
vec_resize(context->ct_locals, 0);
|
||||
|
||||
// Clear returns
|
||||
vec_resize(context->block_returns, 0);
|
||||
context->scope_id = 0;
|
||||
// Zero out any jumps
|
||||
context->break_jump = context->continue_jump = context->next_jump = (JumpTarget) { .target = NULL };
|
||||
ASSERT(func->func_decl.body);
|
||||
ASSERT_SPAN(func, func->func_decl.body);
|
||||
|
||||
Ast *body = astptr(func->func_decl.body);
|
||||
Decl **lambda_params = NULL;
|
||||
SCOPE_START
|
||||
@@ -3383,6 +3389,8 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
|
||||
}
|
||||
if (func->func_decl.is_lambda)
|
||||
{
|
||||
// If we're a lambda we need to pass on the compile time values that will
|
||||
// be baked into the function.
|
||||
lambda_params = copy_decl_list_single(func->func_decl.lambda_ct_parameters);
|
||||
FOREACH(Decl *, ct_param, lambda_params)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@ void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags)
|
||||
|
||||
unsigned label_start = new_label_scope ? last_local : context->active_scope.label_start;
|
||||
context->active_scope = (DynamicScope) {
|
||||
.scope_id = ++context->scope_id,
|
||||
.allow_dead_code = false,
|
||||
.is_dead = scope_is_dead,
|
||||
.is_poisoned = scope_is_poisoned,
|
||||
@@ -47,10 +46,6 @@ void context_change_scope_with_flags(SemaContext *context, ScopeFlags flags)
|
||||
.defer_start = parent_defer,
|
||||
.flags = flags,
|
||||
};
|
||||
if (context->scope_id == 0)
|
||||
{
|
||||
FATAL_ERROR("Too many scopes.");
|
||||
}
|
||||
}
|
||||
|
||||
const char *context_filename(SemaContext *context)
|
||||
|
||||
7
test/test_suite/expressions/grabbing_function_alias.c3t
Normal file
7
test/test_suite/expressions/grabbing_function_alias.c3t
Normal file
@@ -0,0 +1,7 @@
|
||||
alias c = main;
|
||||
void* e = &c;
|
||||
|
||||
fn int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user