aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyze.cpp1
-rw-r--r--src/ir.cpp123
2 files changed, 72 insertions, 52 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index fe705dfce8..eaeb3fa553 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -2510,6 +2510,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
IrInstruction *init_value = nullptr;
+ // TODO more validation for types that can't be used for export/extern variables
TypeTableEntry *implicit_type = nullptr;
if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {
implicit_type = explicit_type;
diff --git a/src/ir.cpp b/src/ir.cpp
index a30851d010..5771fd480d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -9794,6 +9794,58 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi
zig_unreachable();
}
+enum VarClassRequired {
+ VarClassRequiredAny,
+ VarClassRequiredConst,
+ VarClassRequiredIllegal,
+};
+
+static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
+ switch (type_entry->id) {
+ case TypeTableEntryIdInvalid:
+ zig_unreachable();
+ case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdVar:
+ return VarClassRequiredIllegal;
+ case TypeTableEntryIdBool:
+ case TypeTableEntryIdInt:
+ case TypeTableEntryIdFloat:
+ case TypeTableEntryIdVoid:
+ case TypeTableEntryIdPureError:
+ case TypeTableEntryIdFn:
+ case TypeTableEntryIdEnumTag:
+ return VarClassRequiredAny;
+ case TypeTableEntryIdNumLitFloat:
+ case TypeTableEntryIdNumLitInt:
+ case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdBlock:
+ case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdOpaque:
+ case TypeTableEntryIdMetaType:
+ case TypeTableEntryIdNamespace:
+ case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
+ return VarClassRequiredConst;
+
+ case TypeTableEntryIdPointer:
+ return get_var_class_required(type_entry->data.pointer.child_type);
+ case TypeTableEntryIdArray:
+ return get_var_class_required(type_entry->data.array.child_type);
+ case TypeTableEntryIdMaybe:
+ return get_var_class_required(type_entry->data.maybe.child_type);
+ case TypeTableEntryIdErrorUnion:
+ return get_var_class_required(type_entry->data.error.child_type);
+
+ case TypeTableEntryIdStruct:
+ case TypeTableEntryIdEnum:
+ case TypeTableEntryIdUnion:
+ // TODO check the fields of these things and make sure that they don't recursively
+ // contain any of the other variable classes
+ return VarClassRequiredAny;
+ }
+ zig_unreachable();
+}
+
static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {
VariableTableEntry *var = decl_var_instruction->var;
@@ -9803,10 +9855,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
return var->value->type;
}
- AstNodeVariableDeclaration *variable_declaration = &var->decl_node->data.variable_declaration;
- bool is_export = (variable_declaration->visib_mod == VisibModExport);
- bool is_extern = variable_declaration->is_extern;
-
var->ref_count = 0;
TypeTableEntry *explicit_type = nullptr;
@@ -9824,59 +9872,30 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
AstNode *source_node = decl_var_instruction->base.source_node;
IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
+ bool is_comptime_var = ir_get_var_is_comptime(var);
+
TypeTableEntry *result_type = casted_init_value->value.type;
if (type_is_invalid(result_type)) {
result_type = ira->codegen->builtin_types.entry_invalid;
- }
-
- bool is_comptime_var = ir_get_var_is_comptime(var);
-
- switch (result_type->id) {
- case TypeTableEntryIdInvalid:
- break; // handled above
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdUndefLit:
- if (is_export || is_extern || (!var->src_is_const && !is_comptime_var)) {
- ir_add_error_node(ira, source_node, buf_sprintf("unable to infer variable type"));
- result_type = ira->codegen->builtin_types.entry_invalid;
- }
- break;
- case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdVar:
- case TypeTableEntryIdBlock:
- case TypeTableEntryIdNullLit:
- case TypeTableEntryIdOpaque:
- ir_add_error_node(ira, source_node,
- buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
- result_type = ira->codegen->builtin_types.entry_invalid;
- break;
- case TypeTableEntryIdMetaType:
- case TypeTableEntryIdNamespace:
- if (casted_init_value->value.special == ConstValSpecialRuntime) {
+ } else {
+ switch (get_var_class_required(result_type)) {
+ case VarClassRequiredIllegal:
ir_add_error_node(ira, source_node,
- buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
+ buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
result_type = ira->codegen->builtin_types.entry_invalid;
- }
- break;
- case TypeTableEntryIdVoid:
- case TypeTableEntryIdBool:
- case TypeTableEntryIdInt:
- case TypeTableEntryIdFloat:
- case TypeTableEntryIdPointer:
- case TypeTableEntryIdArray:
- case TypeTableEntryIdStruct:
- case TypeTableEntryIdMaybe:
- case TypeTableEntryIdErrorUnion:
- case TypeTableEntryIdPureError:
- case TypeTableEntryIdEnum:
- case TypeTableEntryIdUnion:
- case TypeTableEntryIdFn:
- case TypeTableEntryIdBoundFn:
- case TypeTableEntryIdEnumTag:
- case TypeTableEntryIdArgTuple:
- // OK
- break;
+ break;
+ case VarClassRequiredConst:
+ if (!var->src_is_const && !is_comptime_var) {
+ ir_add_error_node(ira, source_node,
+ buf_sprintf("variable of type '%s' must be const or comptime",
+ buf_ptr(&result_type->name)));
+ result_type = ira->codegen->builtin_types.entry_invalid;
+ }
+ break;
+ case VarClassRequiredAny:
+ // OK
+ break;
+ }
}
var->value->type = result_type;