mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fixes to debug info in function pointer declarations. Incorrect x64 ABI code for structs by val. Change "Compiler" to "GlobalContext" storage of all types inside. Call debug symbol correct.
This commit is contained in:
@@ -23,8 +23,8 @@ ABIArgInfo *abi_arg_new_direct_coerce(AbiType *target_type);
|
||||
ABIArgInfo *abi_arg_new_expand_coerce(AbiType *target_type, unsigned offset);
|
||||
ABIArgInfo *abi_arg_new_expand_coerce_pair(AbiType *first_element, unsigned initial_offset, AbiType *second_element, unsigned padding, bool is_packed);
|
||||
ABIArgInfo *abi_arg_new_expand_padded(Type *padding);
|
||||
ABIArgInfo *abi_arg_new_indirect_realigned(unsigned alignment);
|
||||
ABIArgInfo *abi_arg_new_indirect_by_val(void);
|
||||
ABIArgInfo *abi_arg_new_indirect_realigned(unsigned alignment, Type *by_val_type);
|
||||
ABIArgInfo *abi_arg_new_indirect_by_val(Type *by_val_type);
|
||||
ABIArgInfo *abi_arg_new_indirect_not_by_val(void);
|
||||
|
||||
ByteSize abi_type_abi_alignment(AbiType *type);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "../build/build_options.h"
|
||||
#include <unistd.h>
|
||||
|
||||
Compiler compiler;
|
||||
GlobalContext global_context;
|
||||
BuildTarget active_target;
|
||||
|
||||
Vmem ast_arena;
|
||||
@@ -22,8 +22,8 @@ void compiler_init(const char *std_lib_dir)
|
||||
// Skip library detection.
|
||||
//compiler.lib_dir = find_lib_dir();
|
||||
//DEBUG_LOG("Found std library: %s", compiler.lib_dir);
|
||||
stable_init(&compiler.modules, 64);
|
||||
stable_init(&compiler.global_symbols, 0x1000);
|
||||
stable_init(&global_context.modules, 64);
|
||||
stable_init(&global_context.global_symbols, 0x1000);
|
||||
vmem_init(&ast_arena, 4 * 1024);
|
||||
vmem_init(&expr_arena, 4 * 1024);
|
||||
vmem_init(&decl_arena, 1024);
|
||||
@@ -37,20 +37,20 @@ void compiler_init(const char *std_lib_dir)
|
||||
(void) tokdata_calloc();
|
||||
if (std_lib_dir)
|
||||
{
|
||||
compiler.lib_dir = std_lib_dir;
|
||||
global_context.lib_dir = std_lib_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
compiler.lib_dir = find_lib_dir();
|
||||
global_context.lib_dir = find_lib_dir();
|
||||
}
|
||||
}
|
||||
|
||||
static void compiler_lex(void)
|
||||
{
|
||||
VECEACH(compiler.sources, i)
|
||||
VECEACH(global_context.sources, i)
|
||||
{
|
||||
bool loaded = false;
|
||||
File *file = source_file_load(compiler.sources[i], &loaded);
|
||||
File *file = source_file_load(global_context.sources[i], &loaded);
|
||||
if (loaded) continue;
|
||||
Lexer lexer;
|
||||
lexer_init_with_file(&lexer, file);
|
||||
@@ -68,10 +68,10 @@ static void compiler_lex(void)
|
||||
|
||||
void compiler_parse(void)
|
||||
{
|
||||
VECEACH(compiler.sources, i)
|
||||
VECEACH(global_context.sources, i)
|
||||
{
|
||||
bool loaded = false;
|
||||
File *file = source_file_load(compiler.sources[i], &loaded);
|
||||
File *file = source_file_load(global_context.sources[i], &loaded);
|
||||
if (loaded) continue;
|
||||
diag_setup(active_target.test_output);
|
||||
Context *context = context_create(file);
|
||||
@@ -85,19 +85,19 @@ void compiler_compile(void)
|
||||
{
|
||||
Context **contexts = NULL;
|
||||
diag_setup(active_target.test_output);
|
||||
if (compiler.lib_dir)
|
||||
if (global_context.lib_dir)
|
||||
{
|
||||
vec_add(compiler.sources, strformat("%s/std/runtime.c3", compiler.lib_dir));
|
||||
vec_add(compiler.sources, strformat("%s/std/builtin.c3", compiler.lib_dir));
|
||||
vec_add(compiler.sources, strformat("%s/std/io.c3", compiler.lib_dir));
|
||||
vec_add(compiler.sources, strformat("%s/std/mem.c3", compiler.lib_dir));
|
||||
vec_add(compiler.sources, strformat("%s/std/array.c3", compiler.lib_dir));
|
||||
vec_add(compiler.sources, strformat("%s/std/math.c3", compiler.lib_dir));
|
||||
vec_add(global_context.sources, strformat("%s/std/runtime.c3", global_context.lib_dir));
|
||||
vec_add(global_context.sources, strformat("%s/std/builtin.c3", global_context.lib_dir));
|
||||
vec_add(global_context.sources, strformat("%s/std/io.c3", global_context.lib_dir));
|
||||
vec_add(global_context.sources, strformat("%s/std/mem.c3", global_context.lib_dir));
|
||||
vec_add(global_context.sources, strformat("%s/std/array.c3", global_context.lib_dir));
|
||||
vec_add(global_context.sources, strformat("%s/std/math.c3", global_context.lib_dir));
|
||||
}
|
||||
VECEACH(compiler.sources, i)
|
||||
VECEACH(global_context.sources, i)
|
||||
{
|
||||
bool loaded = false;
|
||||
File *file = source_file_load(compiler.sources[i], &loaded);
|
||||
File *file = source_file_load(global_context.sources[i], &loaded);
|
||||
if (loaded) continue;
|
||||
Context *context = context_create(file);
|
||||
vec_add(contexts, context);
|
||||
@@ -272,7 +272,7 @@ void compile_file_list(BuildOptions *options)
|
||||
|
||||
void compile()
|
||||
{
|
||||
compiler.sources = active_target.sources;
|
||||
global_context.sources = active_target.sources;
|
||||
symtab_init(active_target.symtab_size ? active_target.symtab_size : 64 * 1024);
|
||||
target_expand_source_names(&active_target);
|
||||
target_setup(&active_target);
|
||||
@@ -294,19 +294,19 @@ void compile()
|
||||
|
||||
Decl *compiler_find_symbol(const char *string)
|
||||
{
|
||||
return stable_get(&compiler.global_symbols, string);
|
||||
return stable_get(&global_context.global_symbols, string);
|
||||
}
|
||||
|
||||
void compiler_add_type(Type *type)
|
||||
void global_context_add_type(Type *type)
|
||||
{
|
||||
DEBUG_LOG("Created type %s.", type->name);
|
||||
assert(type_ok(type));
|
||||
VECADD(compiler.type, type);
|
||||
VECADD(global_context.type, type);
|
||||
}
|
||||
|
||||
Module *compiler_find_or_create_module(Path *module_name)
|
||||
{
|
||||
Module *module = stable_get(&compiler.modules, module_name->module);
|
||||
Module *module = stable_get(&global_context.modules, module_name->module);
|
||||
|
||||
if (module)
|
||||
{
|
||||
@@ -324,7 +324,7 @@ Module *compiler_find_or_create_module(Path *module_name)
|
||||
module = CALLOCS(Module);
|
||||
module->name = module_name;
|
||||
stable_init(&module->symbols, 0x10000);
|
||||
stable_set(&compiler.modules, module_name->module, module);
|
||||
stable_set(&global_context.modules, module_name->module, module);
|
||||
// Now find the possible parent array:
|
||||
Path *parent_path = path_find_parent_path(NULL, module_name);
|
||||
if (parent_path)
|
||||
@@ -339,15 +339,15 @@ Module *compiler_find_or_create_module(Path *module_name)
|
||||
void compiler_register_public_symbol(Decl *decl)
|
||||
{
|
||||
assert(decl->name);
|
||||
Decl *prev = stable_get(&compiler.global_symbols, decl->name);
|
||||
Decl *prev = stable_get(&global_context.global_symbols, decl->name);
|
||||
// If the previous symbol was already declared globally, remove it.
|
||||
stable_set(&compiler.global_symbols, decl->name, prev ? poisoned_decl : decl);
|
||||
STable *sub_module_space = stable_get(&compiler.qualified_symbols, decl->module->name->module);
|
||||
stable_set(&global_context.global_symbols, decl->name, prev ? poisoned_decl : decl);
|
||||
STable *sub_module_space = stable_get(&global_context.qualified_symbols, decl->module->name->module);
|
||||
if (!sub_module_space)
|
||||
{
|
||||
sub_module_space = malloc_arena(sizeof(*sub_module_space));
|
||||
stable_init(sub_module_space, 0x100);
|
||||
stable_set(&compiler.qualified_symbols, decl->module->name->module, sub_module_space);
|
||||
stable_set(&global_context.qualified_symbols, decl->module->name->module, sub_module_space);
|
||||
}
|
||||
prev = stable_get(sub_module_space, decl->name);
|
||||
stable_set(sub_module_space, decl->name, prev ? poisoned_decl : decl);
|
||||
|
||||
@@ -206,6 +206,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
struct _FunctionSignature *signature;
|
||||
const char *mangled_function_signature;
|
||||
} TypeFunc;
|
||||
|
||||
struct _Type
|
||||
@@ -354,7 +355,6 @@ typedef struct _FunctionSignature
|
||||
struct ABIArgInfo_ *ret_abi_info;
|
||||
struct ABIArgInfo_ *failable_abi_info;
|
||||
Decl** params;
|
||||
const char *mangled_signature;
|
||||
} FunctionSignature;
|
||||
|
||||
typedef struct
|
||||
@@ -1287,7 +1287,7 @@ typedef struct
|
||||
Type **type;
|
||||
const char *lib_dir;
|
||||
const char **sources;
|
||||
} Compiler;
|
||||
} GlobalContext;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -1370,13 +1370,13 @@ typedef struct ABIArgInfo_
|
||||
{
|
||||
// We may request a certain alignment of the parameters.
|
||||
AlignSize realignment;
|
||||
bool by_val : 1;
|
||||
Type *by_val_type;
|
||||
} indirect;
|
||||
};
|
||||
|
||||
} ABIArgInfo;
|
||||
|
||||
extern Compiler compiler;
|
||||
extern GlobalContext global_context;
|
||||
extern BuildTarget active_target;
|
||||
extern Ast *poisoned_ast;
|
||||
extern Decl *poisoned_decl;
|
||||
@@ -1489,7 +1489,7 @@ void llvm_codegen_setup();
|
||||
|
||||
void header_gen(Context *context);
|
||||
|
||||
void compiler_add_type(Type *type);
|
||||
void global_context_add_type(Type *type);
|
||||
Decl *compiler_find_symbol(const char *name);
|
||||
Module *compiler_find_or_create_module(Path *module_name);
|
||||
void compiler_register_public_symbol(Decl *decl);
|
||||
@@ -1850,7 +1850,7 @@ static inline Type *type_new(TypeKind kind, const char *name)
|
||||
type->type_kind = kind;
|
||||
assert(name);
|
||||
type->name = name;
|
||||
compiler_add_type(type);
|
||||
global_context_add_type(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,26 +84,26 @@ bool abi_arg_is_indirect(ABIArgInfo *info)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_indirect_realigned(unsigned alignment)
|
||||
ABIArgInfo *abi_arg_new_indirect_realigned(unsigned alignment, Type *by_val_type)
|
||||
{
|
||||
assert(alignment > 0);
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_INDIRECT);
|
||||
info->indirect.realignment = alignment;
|
||||
info->indirect.by_val = true;
|
||||
info->indirect.by_val_type = by_val_type;
|
||||
return info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_indirect_by_val(void)
|
||||
ABIArgInfo *abi_arg_new_indirect_by_val(Type *by_val_type)
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_INDIRECT);
|
||||
info->indirect.by_val = true;
|
||||
info->indirect.by_val_type = by_val_type;
|
||||
return info;
|
||||
}
|
||||
|
||||
ABIArgInfo *abi_arg_new_indirect_not_by_val(void)
|
||||
{
|
||||
ABIArgInfo *info = abi_arg_new(ABI_ARG_INDIRECT);
|
||||
info->indirect.by_val = false;
|
||||
info->indirect.by_val_type = NULL;
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -221,9 +221,9 @@ ABIArgInfo *c_abi_classify_argument_type_default(Type *type)
|
||||
type = type_lowering(type);
|
||||
|
||||
// Struct-likes are returned by sret
|
||||
if (type_is_abi_aggregate(type)) return abi_arg_new_indirect_by_val();
|
||||
if (type_is_abi_aggregate(type)) return abi_arg_new_indirect_by_val(type);
|
||||
|
||||
if (type_is_int128(type) && !platform_target.int128) return abi_arg_new_indirect_by_val();
|
||||
if (type_is_int128(type) && !platform_target.int128) return abi_arg_new_indirect_by_val(type);
|
||||
|
||||
// Otherwise do we have a type that needs promotion?
|
||||
if (type_is_promotable_integer(type)) return abi_arg_new_direct_int_ext(type);
|
||||
|
||||
@@ -134,7 +134,7 @@ ABIArgInfo *aarch64_classify_return_type(Type *type, bool variadic)
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(aligned_size * 8));
|
||||
}
|
||||
|
||||
return abi_arg_new_indirect_by_val();
|
||||
return abi_arg_new_indirect_by_val(type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -113,16 +113,16 @@ ABIArgInfo *x64_indirect_result(Type *type, unsigned free_int_regs)
|
||||
if (!free_int_regs)
|
||||
{
|
||||
unsigned size = type_size(type);
|
||||
if (align == 8 && size <= 8)
|
||||
if (align <= 8 && size <= 8)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(size * 8));
|
||||
}
|
||||
}
|
||||
if (align < 8)
|
||||
{
|
||||
return abi_arg_new_indirect_realigned(8);
|
||||
return abi_arg_new_indirect_realigned(8, type);
|
||||
}
|
||||
return abi_arg_new_direct();
|
||||
return abi_arg_new_indirect_by_val(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -794,7 +794,7 @@ static ABIArgInfo *x64_classify_argument_type(Type *type, unsigned free_int_regs
|
||||
{
|
||||
X64Class hi_class;
|
||||
X64Class lo_class;
|
||||
x64_classify(type, 0, &lo_class, &hi_class, NAMED);
|
||||
x64_classify(type, 0, &lo_class, &hi_class, is_named);
|
||||
|
||||
// Invariants
|
||||
assert(hi_class != CLASS_MEMORY || lo_class == CLASS_MEMORY);
|
||||
|
||||
@@ -72,10 +72,10 @@ static ABIArgInfo *x86_create_indirect_result(Regs *regs, Type *type, ByVal by_v
|
||||
// Realign if alignment is greater.
|
||||
if (alignment > stack_alignment)
|
||||
{
|
||||
return abi_arg_new_indirect_realigned(stack_alignment);
|
||||
return abi_arg_new_indirect_realigned(stack_alignment, type);
|
||||
}
|
||||
|
||||
return abi_arg_new_indirect_by_val();
|
||||
return abi_arg_new_indirect_by_val(type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -470,7 +470,7 @@ static LLVMMetadataRef llvm_debug_typedef_type(GenContext *c, Type *type)
|
||||
NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
Type *original_type = type->type_kind == TYPE_TYPEDEF ? decl->typedef_decl.type_info->type : decl->distinct_decl.base_type;
|
||||
Type *original_type = type->type_kind == TYPE_TYPEDEF ? type->canonical : decl->distinct_decl.base_type;
|
||||
|
||||
SourceLocation *location = TOKLOC(decl->span.loc);
|
||||
// Use forward references in case we haven't resolved the original type, since we could have this:
|
||||
|
||||
@@ -2790,7 +2790,9 @@ void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
}
|
||||
}
|
||||
|
||||
// 10. Create the actual call
|
||||
|
||||
// 10. Create the actual call (remember to emit a loc, because we might have shifted loc emitting the params)
|
||||
EMIT_LOC(c, expr);
|
||||
LLVMValueRef call_value = LLVMBuildCall2(c->builder, func_type, func, values, vec_size(values), "");
|
||||
|
||||
// 11. Process the return value.
|
||||
|
||||
@@ -507,8 +507,11 @@ static void llvm_emit_param_attributes(GenContext *context, LLVMValueRef functio
|
||||
else
|
||||
{
|
||||
// TODO then type attributes are added to LLVM-C, use that for byval.
|
||||
if (info->indirect.by_val) llvm_attribute_add(context, function, attribute_byval, index);
|
||||
llvm_attribute_add(context, function, attribute_noalias, index);
|
||||
if (info->indirect.by_val_type) llvm_attribute_add(context, function, attribute_byval, index);
|
||||
if (!info->indirect.realignment)
|
||||
{
|
||||
llvm_attribute_add_int(context, function, attribute_align, type_abi_alignment(info->indirect.by_val_type), index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <llvm-c/Comdat.h>
|
||||
#include "dwarf.h"
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BE_VALUE,
|
||||
@@ -45,11 +47,6 @@ typedef struct
|
||||
LLVMBasicBlockRef next_block;
|
||||
} BreakContinue;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned runtime_version : 8;
|
||||
|
||||
@@ -65,9 +65,10 @@ void gencontext_begin_module(GenContext *c)
|
||||
c->block_global_unique_count = 0;
|
||||
c->ast_alloca_addr_space = target_alloca_addr_space();
|
||||
|
||||
VECEACH(compiler.type, i)
|
||||
VECEACH(global_context.type, i)
|
||||
{
|
||||
compiler.type[i]->backend_type = NULL;
|
||||
global_context.type[i]->backend_type = NULL;
|
||||
global_context.type[i]->backend_debug_type = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -323,11 +323,11 @@ LLVMTypeRef llvm_get_pointee_type(GenContext *c, Type *any_type)
|
||||
|
||||
LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
|
||||
{
|
||||
if (any_type->backend_type && LLVMGetTypeContext(any_type->backend_type) == c->context)
|
||||
if (any_type->backend_type)
|
||||
{
|
||||
assert(LLVMGetTypeContext(any_type->backend_type) == c->context && "Should have been purged");
|
||||
return any_type->backend_type;
|
||||
}
|
||||
DEBUG_LOG("Generating type %s", any_type->name);
|
||||
switch (any_type->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
|
||||
@@ -420,15 +420,16 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi
|
||||
if (!all_ok) return NULL;
|
||||
|
||||
TokenType type = TOKEN_INVALID_TOKEN;
|
||||
signature->mangled_signature = symtab_add(buffer, buffer_write_offset, fnv1a(buffer, buffer_write_offset), &type);
|
||||
Type *func_type = stable_get(&context->local_symbols, signature->mangled_signature);
|
||||
const char *mangled_signature = symtab_add(buffer, buffer_write_offset, fnv1a(buffer, buffer_write_offset), &type);
|
||||
Type *func_type = stable_get(&context->local_symbols, mangled_signature);
|
||||
c_abi_func_create(signature);
|
||||
if (!func_type)
|
||||
{
|
||||
func_type = type_new(TYPE_FUNC, signature->mangled_signature);
|
||||
func_type = type_new(TYPE_FUNC, mangled_signature);
|
||||
func_type->canonical = func_type;
|
||||
func_type->func.signature = signature;
|
||||
stable_set(&context->local_symbols, signature->mangled_signature, func_type);
|
||||
func_type->func.mangled_function_signature = mangled_signature;
|
||||
stable_set(&context->local_symbols, mangled_signature, func_type);
|
||||
}
|
||||
return func_type;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ void sema_analysis_pass_process_imports(Context *context)
|
||||
Decl *import = context->imports[i];
|
||||
import->resolve_status = RESOLVE_RUNNING;
|
||||
Path *path = import->import.path;
|
||||
Module *module = stable_get(&compiler.modules, path->module);
|
||||
Module *module = stable_get(&global_context.modules, path->module);
|
||||
DEBUG_LOG("- Import of %s.", path->module);
|
||||
if (!module)
|
||||
{
|
||||
|
||||
@@ -122,17 +122,7 @@ const char *type_to_error_string(Type *type)
|
||||
case TYPE_VIRTUAL:
|
||||
return type->name;
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
asprintf(&buffer, type->func.signature->failable ? "func %s!(" : "func %s(",
|
||||
type_to_error_string(type->func.signature->rtype->type));
|
||||
VECEACH(type->func.signature->params, i)
|
||||
{
|
||||
if (i != 0) buffer = strcat_arena(buffer, ", ");
|
||||
strcat_arena(buffer, type_to_error_string(type->func.signature->params[i]->type));
|
||||
}
|
||||
|
||||
return strcat_arena(buffer, ")");
|
||||
}
|
||||
return strcat_arena("func ", type->func.mangled_function_signature);
|
||||
case TYPE_COMPLEX:
|
||||
switch (type->complex->type_kind)
|
||||
{
|
||||
@@ -1037,6 +1027,7 @@ static void type_create(const char *name, Type *location, TypeKind kind, unsigne
|
||||
};
|
||||
location->name = name;
|
||||
location->canonical = location;
|
||||
global_context_add_type(location);
|
||||
}
|
||||
|
||||
static void type_create_alias(const char *name, Type *location, Type *canonical)
|
||||
@@ -1046,6 +1037,7 @@ static void type_create_alias(const char *name, Type *location, Type *canonical)
|
||||
.name = name,
|
||||
.canonical = canonical
|
||||
};
|
||||
global_context_add_type(location);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,17 +23,17 @@ func void test1(Func arg)
|
||||
|
||||
func void test2(Func arg)
|
||||
{
|
||||
ichar b = cast(arg as ichar); // #error: Cannot cast 'Func' (func void()) to 'ichar'.
|
||||
ichar b = cast(arg as ichar); // #error: Cannot cast 'Func' (func void(int)) to 'ichar'.
|
||||
}
|
||||
|
||||
func void test3(Func arg)
|
||||
{
|
||||
uint c = cast(arg as uint); // #error: Cannot cast 'Func' (func void()) to 'uint'.
|
||||
uint c = cast(arg as uint); // #error: Cannot cast 'Func' (func void(int)) to 'uint'.
|
||||
}
|
||||
|
||||
func void test4(Func arg)
|
||||
{
|
||||
float d = cast(arg as float); // #error: Cannot cast 'Func' (func void()) to 'float'.
|
||||
float d = cast(arg as float); // #error: Cannot cast 'Func' (func void(int)) to 'float'.
|
||||
}
|
||||
|
||||
func void test7(Func arg)
|
||||
@@ -41,7 +41,7 @@ func void test7(Func arg)
|
||||
usize g = cast(arg as usize);
|
||||
FuncOther k = cast(arg as FuncOther);
|
||||
FuncSame l = cast(arg as FuncSame);
|
||||
FuncOther ke = arg; // #error: Cannot implicitly cast 'Func' (func void()) to 'FuncOther' (func bool())
|
||||
FuncOther ke = arg; // #error: Cannot implicitly cast 'Func' (func void(int)) to 'FuncOther' (func bool(char*))
|
||||
FuncSame fe = arg;
|
||||
Enum j = cast(arg as Enum); // #error: Cannot cast 'Func' (func void()) to 'Enum'.
|
||||
Enum j = cast(arg as Enum); // #error: Cannot cast 'Func' (func void(int)) to 'Enum'.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user