mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Support enum associated values.
This commit is contained in:
committed by
Christoffer Lerno
parent
60832019bd
commit
b0c55ff777
@@ -301,6 +301,7 @@ typedef struct
|
||||
Path *path;
|
||||
const char *name;
|
||||
SourceSpan span;
|
||||
AttributeType attr_kind : 8;
|
||||
union
|
||||
{
|
||||
Expr *expr;
|
||||
@@ -359,6 +360,7 @@ typedef struct VarDecl_
|
||||
};
|
||||
union
|
||||
{
|
||||
int32_t index;
|
||||
struct
|
||||
{
|
||||
struct SemaContext_ *context;
|
||||
|
||||
@@ -665,6 +665,7 @@ typedef enum
|
||||
ATTRIBUTE_AUTOIMPORT,
|
||||
ATTRIBUTE_OPERATOR,
|
||||
ATTRIBUTE_PURE,
|
||||
ATTRIBUTE_REFLECT,
|
||||
ATTRIBUTE_NONE,
|
||||
NUMBER_OF_ATTRIBUTES = ATTRIBUTE_NONE,
|
||||
} AttributeType;
|
||||
|
||||
@@ -730,7 +730,8 @@ void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl)
|
||||
}
|
||||
if (decl_is_enum_kind(decl))
|
||||
{
|
||||
unsigned elements = vec_size(decl->enums.values);
|
||||
Decl **enum_vals = decl->enums.values;
|
||||
unsigned elements = vec_size(enum_vals);
|
||||
LLVMTypeRef element_type = llvm_get_type(c, type_voidptr);
|
||||
LLVMTypeRef elements_type = LLVMArrayType(element_type, elements);
|
||||
scratch_buffer_clear();
|
||||
@@ -744,8 +745,54 @@ void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl)
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
AlignSize store_align;
|
||||
decl->enums.values[i]->backend_ref = llvm_emit_array_gep_raw(c, enum_elements, elements_type, i, alignment, &store_align);
|
||||
enum_vals[i]->backend_ref = llvm_emit_array_gep_raw(c, enum_elements, elements_type, i, alignment, &store_align);
|
||||
}
|
||||
Decl **associated_values = decl->enums.parameters;
|
||||
unsigned associated_value_count = vec_size(associated_values);
|
||||
if (associated_value_count && elements)
|
||||
{
|
||||
|
||||
LLVMValueRef *values = malloc_arena(elements * sizeof(LLVMValueRef));
|
||||
LLVMTypeRef val_type;
|
||||
VECEACH(associated_values, ai)
|
||||
{
|
||||
val_type = NULL;
|
||||
bool mixed = false;
|
||||
for (unsigned i = 0; i < elements; i++)
|
||||
{
|
||||
BEValue value;
|
||||
llvm_emit_expr(c, &value, enum_vals[i]->enum_constant.args[ai]);
|
||||
assert(!llvm_value_is_addr(&value));
|
||||
LLVMValueRef llvm_value = llvm_value_is_bool(&value) ? LLVMConstZExt(value.value, c->byte_type) : value.value;
|
||||
values[i] = llvm_value;
|
||||
if (!val_type)
|
||||
{
|
||||
val_type = LLVMTypeOf(llvm_value);
|
||||
continue;
|
||||
}
|
||||
if (val_type != LLVMTypeOf(llvm_value)) mixed = true;
|
||||
}
|
||||
Decl *associated_value = associated_values[ai];
|
||||
LLVMValueRef associated_value_arr = mixed ? LLVMConstStruct(values, elements, true) : LLVMConstArray(val_type, values, elements);
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->extname);
|
||||
scratch_buffer_append("$$");
|
||||
scratch_buffer_append(associated_value->name);
|
||||
LLVMValueRef global_ref = LLVMAddGlobal(c->module, LLVMTypeOf(associated_value_arr), scratch_buffer_to_string());
|
||||
LLVMSetInitializer(global_ref, associated_value_arr);
|
||||
LLVMSetGlobalConstant(global_ref, true);
|
||||
if (mixed)
|
||||
{
|
||||
LLVMTypeRef cast_type = llvm_get_ptr_type(c, type_get_array(associated_value->type, elements));
|
||||
associated_value->backend_ref = LLVMConstBitCast(global_ref, cast_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
associated_value->backend_ref = global_ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append("introspect.");
|
||||
@@ -1004,6 +1051,10 @@ void *llvm_gen(Module *module)
|
||||
{
|
||||
llvm_emit_type_decls(gen_context, unit->types[i]);
|
||||
}
|
||||
VECEACH(unit->enums, i)
|
||||
{
|
||||
llvm_emit_type_decls(gen_context, unit->enums[i]);
|
||||
}
|
||||
VECEACH(unit->functions, i)
|
||||
{
|
||||
llvm_emit_function_decl(gen_context, unit->functions[i]);
|
||||
|
||||
@@ -1081,6 +1081,17 @@ static inline void gencontext_emit_access_addr(GenContext *context, BEValue *be_
|
||||
llvm_emit_expr(context, be_value, parent);
|
||||
Decl *member = expr->access_expr.ref;
|
||||
|
||||
Type *flat_type = type_flatten_distinct_failable(parent->type);
|
||||
if (flat_type->type_kind == TYPE_ENUM)
|
||||
{
|
||||
llvm_value_rvalue(context, be_value);
|
||||
LLVMTypeRef value_type = llvm_get_type(context, type_get_array(member->type, vec_size(flat_type->decl->enums.values)));
|
||||
AlignSize align = LLVMGetAlignment(member->backend_ref);
|
||||
AlignSize alignment;
|
||||
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(context, member->backend_ref, value_type, be_value->value, align, &alignment);
|
||||
llvm_value_set_address(be_value, ptr, member->type, alignment);
|
||||
return;
|
||||
}
|
||||
gencontext_emit_member_addr(context, be_value, type_lowering(parent->type)->decl, member);
|
||||
}
|
||||
|
||||
|
||||
@@ -1857,6 +1857,7 @@ static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl***
|
||||
SEMA_ERROR_LAST("Vararg parameters are not allowed as enum parameters.");
|
||||
return false;
|
||||
}
|
||||
last_parameter->var.index = vec_size(*parameters_ref) - 1;
|
||||
if (!try_consume(c, TOKEN_COMMA))
|
||||
{
|
||||
EXPECT_OR_RET(TOKEN_RPAREN, false);
|
||||
|
||||
@@ -370,12 +370,11 @@ static bool sema_analyse_struct_union(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Attr *attr = decl->attributes[i];
|
||||
|
||||
AttributeType attribute = sema_analyse_attribute(context, attr, domain);
|
||||
if (attribute == ATTRIBUTE_NONE) return decl_poison(decl);
|
||||
if (!sema_analyse_attribute(context, attr, domain)) return decl_poison(decl);
|
||||
|
||||
bool had = false;
|
||||
#define SET_ATTR(_X) had = decl->func_decl._X; decl->func_decl._X = true; break
|
||||
switch (attribute)
|
||||
switch (attr->attr_kind)
|
||||
{
|
||||
case ATTRIBUTE_EXTNAME:
|
||||
had = decl->has_extname;
|
||||
@@ -537,12 +536,11 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Attr *attr = decl->attributes[i];
|
||||
|
||||
AttributeType attribute = sema_analyse_attribute(context, attr, ATTR_BITSTRUCT);
|
||||
if (attribute == ATTRIBUTE_NONE) return decl_poison(decl);
|
||||
if (!sema_analyse_attribute(context, attr, ATTR_BITSTRUCT)) return decl_poison(decl);
|
||||
|
||||
bool had = false;
|
||||
#define SET_ATTR(_X) had = decl->bitstruct._X; decl->bitstruct._X = true; break
|
||||
switch (attribute)
|
||||
switch (attr->attr_kind)
|
||||
{
|
||||
case ATTRIBUTE_OVERLAP:
|
||||
SET_ATTR(overlap);
|
||||
@@ -762,6 +760,49 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param, bool *has_default)
|
||||
{
|
||||
*has_default = false;
|
||||
assert(param->decl_kind == DECL_VAR);
|
||||
// We need to check that the parameters are not typeless nor are of any macro parameter kind.
|
||||
if (param->var.kind != VARDECL_PARAM && !param->var.type_info)
|
||||
{
|
||||
SEMA_ERROR(param, "An associated value must be a normal typed parameter.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vec_size(param->attributes))
|
||||
{
|
||||
SEMA_ERROR(param->attributes[0], "There are no valid attributes for associated values.");
|
||||
return false;
|
||||
}
|
||||
if (!sema_resolve_type_info(context, param->var.type_info)) return false;
|
||||
if (param->var.vararg)
|
||||
{
|
||||
param->var.type_info->type = type_get_subarray(param->var.type_info->type);
|
||||
}
|
||||
param->type = param->var.type_info->type;
|
||||
if (param->var.init_expr)
|
||||
{
|
||||
Expr *expr = param->var.init_expr;
|
||||
|
||||
if (!sema_analyse_expr_rhs(context, param->type, expr, true)) return false;
|
||||
if (IS_FAILABLE(expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "Default arguments may not be failable.");
|
||||
return false;
|
||||
}
|
||||
if (!expr_is_constant_eval(expr, CONSTANT_EVAL_ANY))
|
||||
{
|
||||
SEMA_ERROR(expr, "Only constant expressions may be used as default values.");
|
||||
return false;
|
||||
}
|
||||
*has_default = true;
|
||||
}
|
||||
param->alignment = type_abi_alignment(param->type);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_enum(SemaContext *context, Decl *decl)
|
||||
{
|
||||
// Resolve the type of the enum.
|
||||
@@ -778,6 +819,40 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl)
|
||||
}
|
||||
|
||||
DEBUG_LOG("* Enum type resolved to %s.", type->name);
|
||||
|
||||
Decl **associated_values = decl->enums.parameters;
|
||||
unsigned associated_value_count = vec_size(associated_values);
|
||||
unsigned mandatory_count = 0;
|
||||
bool default_values_used = false;
|
||||
for (unsigned i = 0; i < associated_value_count; i++)
|
||||
{
|
||||
Decl *value = associated_values[i];
|
||||
switch (value->resolve_status)
|
||||
{
|
||||
case RESOLVE_DONE:
|
||||
continue;
|
||||
case RESOLVE_RUNNING:
|
||||
SEMA_ERROR(value, "Recursive definition found.");
|
||||
return false;
|
||||
case RESOLVE_NOT_DONE:
|
||||
value->resolve_status = RESOLVE_RUNNING;
|
||||
break;
|
||||
}
|
||||
bool has_default = false;
|
||||
if (!sema_analyse_enum_param(context, value, &has_default)) return false;
|
||||
if (!has_default)
|
||||
{
|
||||
mandatory_count++;
|
||||
if (default_values_used && !value->var.vararg)
|
||||
{
|
||||
SEMA_ERROR(value, "Non-default parameters cannot appear after default parameters.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default_values_used |= has_default;
|
||||
value->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
unsigned enums = vec_size(decl->enums.values);
|
||||
Int128 value = { 0, 0 };
|
||||
@@ -811,6 +886,36 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl)
|
||||
|
||||
// Update the value
|
||||
value.low++;
|
||||
|
||||
Expr **args = enum_value->enum_constant.args;
|
||||
unsigned arg_count = vec_size(args);
|
||||
if (arg_count > associated_value_count)
|
||||
{
|
||||
if (!associated_value_count)
|
||||
{
|
||||
SEMA_ERROR(args[0], "No associated values are defined for this enum.");
|
||||
return false;
|
||||
}
|
||||
SEMA_ERROR(args[associated_value_count], "Only %d associated value(s) may be defined for this enum.");
|
||||
return false;
|
||||
}
|
||||
if (arg_count < mandatory_count)
|
||||
{
|
||||
SEMA_ERROR(enum_value, "Expected associated value(s) defined for this enum.");
|
||||
return false;
|
||||
}
|
||||
for (unsigned j = 0; j < arg_count; j++)
|
||||
{
|
||||
Expr *arg = args[j];
|
||||
|
||||
if (!sema_analyse_expr_rhs(context, associated_values[j]->type, arg, false)) return false;
|
||||
if (!expr_is_constant_eval(arg, CONSTANT_EVAL_ANY))
|
||||
{
|
||||
SEMA_ERROR(arg, "Expected a constant expression as parameter.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
REMINDER("named parameters and defaults do not work");
|
||||
enum_value->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
return success;
|
||||
@@ -1111,13 +1216,13 @@ static const char *attribute_domain_to_string(AttributeDomain domain)
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, AttributeDomain domain)
|
||||
bool sema_analyse_attribute(SemaContext *context, Attr *attr, AttributeDomain domain)
|
||||
{
|
||||
AttributeType type = attribute_by_name(attr);
|
||||
if (type == ATTRIBUTE_NONE)
|
||||
{
|
||||
sema_error_at(attr->span, "There is no attribute with the name '%s', did you mistype?", attr->name);
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
static AttributeDomain attribute_domain[NUMBER_OF_ATTRIBUTES] = {
|
||||
[ATTRIBUTE_WEAK] = ATTR_FUNC | ATTR_CONST | ATTR_GLOBAL,
|
||||
@@ -1141,14 +1246,16 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
|
||||
[ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT,
|
||||
[ATTRIBUTE_AUTOIMPORT] = ATTR_MACRO | ATTR_FUNC,
|
||||
[ATTRIBUTE_OPERATOR] = ATTR_MACRO | ATTR_FUNC,
|
||||
[ATTRIBUTE_REFLECT] = ATTR_ENUM,
|
||||
[ATTRIBUTE_PURE] = ATTR_CALL,
|
||||
};
|
||||
|
||||
if ((attribute_domain[type] & domain) != domain)
|
||||
{
|
||||
sema_error_at(attr->span, "'%s' is not a valid %s attribute.", attr->name, attribute_domain_to_string(domain));
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
attr->attr_kind = type;
|
||||
switch (type)
|
||||
{
|
||||
case ATTRIBUTE_CDECL:
|
||||
@@ -1156,7 +1263,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
|
||||
case ATTRIBUTE_STDCALL:
|
||||
case ATTRIBUTE_VECCALL:
|
||||
case ATTRIBUTE_REGCALL:
|
||||
return type;
|
||||
return true;
|
||||
case ATTRIBUTE_OPERATOR:
|
||||
{
|
||||
Expr *expr = attr->expr;
|
||||
@@ -1183,44 +1290,44 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
|
||||
{
|
||||
goto FAILED_OP_TYPE;
|
||||
}
|
||||
return ATTRIBUTE_OPERATOR;
|
||||
return true;
|
||||
FAILED_OP_TYPE:
|
||||
SEMA_ERROR(attr, "'operator' requires an operator type argument: '%s', '%s' or '%s'.", kw_elementat, kw_elementref, kw_len);
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
case ATTRIBUTE_ALIGN:
|
||||
if (!attr->expr)
|
||||
{
|
||||
sema_error_at(attr->span, "'align' requires an power-of-2 argument, e.g. align(8).");
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr(context, attr->expr)) return false;
|
||||
if (attr->expr->expr_kind != EXPR_CONST || !type_is_integer(attr->expr->type->canonical))
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "Expected a constant integer value as argument.");
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
{
|
||||
if (int_ucomp(attr->expr->const_expr.ixx, MAX_ALIGNMENT, BINARYOP_GT))
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "Alignment must be less or equal to %ull.", MAX_ALIGNMENT);
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
if (int_ucomp(attr->expr->const_expr.ixx, 0, BINARYOP_LE))
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "Alignment must be greater than zero.");
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
uint64_t align = int_to_u64(attr->expr->const_expr.ixx);
|
||||
if (!is_power_of_two(align))
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "Alignment must be a power of two.");
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
attr->alignment = (AlignSize)align;
|
||||
}
|
||||
return type;
|
||||
return true;
|
||||
case ATTRIBUTE_SECTION:
|
||||
case ATTRIBUTE_EXTNAME:
|
||||
if (context->unit->module->is_generic)
|
||||
@@ -1231,22 +1338,22 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
|
||||
if (!attr->expr)
|
||||
{
|
||||
sema_error_at(attr->span, "'%s' requires a string argument, e.g. %s(\"foo\").", attr->name, attr->name);
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr(context, attr->expr)) return false;
|
||||
if (attr->expr->expr_kind != EXPR_CONST || attr->expr->const_expr.const_kind != CONST_STRING)
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "Expected a constant string value as argument.");
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
return type;
|
||||
return true;
|
||||
default:
|
||||
if (attr->expr)
|
||||
{
|
||||
SEMA_ERROR(attr->expr, "'%s' should not have any arguments.", attr->name);
|
||||
return ATTRIBUTE_NONE;
|
||||
return false;
|
||||
}
|
||||
return type;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1465,13 +1572,12 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Attr *attr = decl->attributes[i];
|
||||
|
||||
AttributeType attribute = sema_analyse_attribute(context, attr, ATTR_FUNC);
|
||||
if (attribute == ATTRIBUTE_NONE) return decl_poison(decl);
|
||||
if (!sema_analyse_attribute(context, attr, ATTR_FUNC)) return decl_poison(decl);
|
||||
|
||||
bool had = false;
|
||||
#define SET_ATTR(_X) had = decl->func_decl._X; decl->func_decl._X = true; break
|
||||
|
||||
switch (attribute)
|
||||
switch (attr->attr_kind)
|
||||
{
|
||||
case ATTRIBUTE_OPERATOR:
|
||||
had = decl->operator > 0;
|
||||
@@ -1628,11 +1734,10 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Attr *attr = decl->attributes[i];
|
||||
|
||||
AttributeType attribute = sema_analyse_attribute(context, attr, ATTR_MACRO);
|
||||
if (attribute == ATTRIBUTE_NONE) return decl_poison(decl);
|
||||
if (!sema_analyse_attribute(context, attr, ATTR_MACRO)) return decl_poison(decl);
|
||||
|
||||
bool had = false;
|
||||
switch (attribute)
|
||||
switch (attr->attr_kind)
|
||||
{
|
||||
case ATTRIBUTE_OPERATOR:
|
||||
had = decl->operator > 0;
|
||||
@@ -1784,12 +1889,11 @@ static bool sema_analyse_attributes_for_var(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Attr *attr = decl->attributes[i];
|
||||
|
||||
AttributeType attribute = sema_analyse_attribute(context, attr, domain);
|
||||
if (attribute == ATTRIBUTE_NONE) return decl_poison(decl);
|
||||
if (!sema_analyse_attribute(context, attr, domain)) decl_poison(decl);
|
||||
|
||||
bool had = false;
|
||||
#define SET_ATTR(_X) had = decl->func_decl._X; decl->func_decl._X = true; break
|
||||
switch (attribute)
|
||||
switch (attr->attr_kind)
|
||||
{
|
||||
case ATTRIBUTE_EXTNAME:
|
||||
had = decl->has_extname;
|
||||
|
||||
@@ -2879,6 +2879,14 @@ static void add_members_to_context(SemaContext *context, Decl *decl)
|
||||
if (!type_is_user_defined(type)) break;
|
||||
decl = type->decl;
|
||||
}
|
||||
if (decl_is_enum_kind(decl))
|
||||
{
|
||||
Decl **members = decl->enums.parameters;
|
||||
VECEACH(members, i)
|
||||
{
|
||||
sema_add_member(context, members[i]);
|
||||
}
|
||||
}
|
||||
if (decl_is_struct_type(decl) || decl->decl_kind == DECL_BITSTRUCT)
|
||||
{
|
||||
Decl **members = decl->strukt.members;
|
||||
@@ -3259,6 +3267,13 @@ CHECK_DEEPER:
|
||||
member = sema_resolve_symbol_in_current_dynamic_scope(context, kw);
|
||||
SCOPE_END;
|
||||
|
||||
if (member && decl_is_enum_kind(decl) && parent->expr_kind == EXPR_CONST)
|
||||
{
|
||||
assert(parent->const_expr.const_kind == CONST_ENUM);
|
||||
Expr *copy_init = expr_macro_copy(parent->const_expr.enum_val->enum_constant.args[member->var.index]);
|
||||
expr_replace(expr, copy_init);
|
||||
return true;
|
||||
}
|
||||
if (!member)
|
||||
{
|
||||
Decl *ambiguous = NULL;
|
||||
|
||||
@@ -56,7 +56,7 @@ bool splitpathref(const char *string, ArraySize len, Path **path_ref, const char
|
||||
|
||||
#define IS_CONST(_x) ((_x)->expr_kind == EXPR_CONST)
|
||||
|
||||
AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, AttributeDomain domain);
|
||||
bool sema_analyse_attribute(SemaContext *context, Attr *attr, AttributeDomain domain);
|
||||
bool expr_is_ltype(Expr *expr);
|
||||
bool sema_expr_check_assign(SemaContext *c, Expr *expr);
|
||||
|
||||
|
||||
@@ -216,6 +216,7 @@ void symtab_init(uint32_t capacity)
|
||||
attribute_list[ATTRIBUTE_OVERLAP] = KW_DEF("@overlap");
|
||||
attribute_list[ATTRIBUTE_OPERATOR] = KW_DEF("@operator");
|
||||
attribute_list[ATTRIBUTE_PURE] = kw_at_pure;
|
||||
attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect");
|
||||
attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("@autoimport");
|
||||
|
||||
for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++)
|
||||
|
||||
51
test/test_suite/enumerations/enum_associated_value.c3t
Normal file
51
test/test_suite/enumerations/enum_associated_value.c3t
Normal file
@@ -0,0 +1,51 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
|
||||
enum Foo : uint (int val, char* testme)
|
||||
{
|
||||
A(123, "Number A"),
|
||||
B(333, "Number B"),
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
int x = Foo.A.val;
|
||||
Foo f = Foo.B;
|
||||
Foo g = Foo.A;
|
||||
libc::printf("%d (%s) %d (%s)\n", f.val, f.testme, g.val, g.testme);
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
@"test.Foo$elements" = linkonce constant [2 x i8*] zeroinitializer
|
||||
@"test.Foo$$val" = constant [2 x i32] [i32 123, i32 333]
|
||||
@.str = private unnamed_addr constant [9 x i8] c"Number A\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [9 x i8] c"Number B\00", align 1
|
||||
@"test.Foo$$testme" = constant [2 x i8*] [i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i32 0, i32 0)]
|
||||
@introspect.Foo = linkonce constant i8 1
|
||||
@.str.2 = private unnamed_addr constant [17 x i8] c"%d (%s) %d (%s)\0A\00", align 1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
%f = alloca i32, align 4
|
||||
%g = alloca i32, align 4
|
||||
store i32 123, i32* %x, align 4
|
||||
store i32 1, i32* %f, align 4
|
||||
store i32 0, i32* %g, align 4
|
||||
%0 = load i32, i32* %f, align 4
|
||||
%1 = getelementptr inbounds [2 x i32], [2 x i32]* @"test.Foo$$val", i32 0, i32 %0
|
||||
%2 = load i32, i32* %1, align 4
|
||||
%3 = load i32, i32* %f, align 4
|
||||
%4 = getelementptr inbounds [2 x i8*], [2 x i8*]* @"test.Foo$$testme", i32 0, i32 %3
|
||||
%5 = load i8*, i8** %4, align 8
|
||||
%6 = load i32, i32* %g, align 4
|
||||
%7 = getelementptr inbounds [2 x i32], [2 x i32]* @"test.Foo$$val", i32 0, i32 %6
|
||||
%8 = load i32, i32* %7, align 4
|
||||
%9 = load i32, i32* %g, align 4
|
||||
%10 = getelementptr inbounds [2 x i8*], [2 x i8*]* @"test.Foo$$testme", i32 0, i32 %9
|
||||
%11 = load i8*, i8** %10, align 8
|
||||
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.2, i32 0, i32 0), i32 %2, i8* %5, i32 %8, i8* %11)
|
||||
ret void
|
||||
}
|
||||
@@ -21,7 +21,7 @@ enum EnumTestDefault
|
||||
|
||||
enum EnumWithErrorData2 : int (int bar, )
|
||||
{
|
||||
TEST
|
||||
TEST // #error: Expected associated value
|
||||
}
|
||||
|
||||
enum EnumTestErrorType4
|
||||
|
||||
Reference in New Issue
Block a user