mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
parent
5fdf3fa195
commit
bc0a60c7a6
@ -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;
|
||||
|
||||
123
src/ir.cpp
123
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;
|
||||
|
||||
@ -1435,20 +1435,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\fn bar() -> %i32 { 0 }
|
||||
, ".tmp_source.zig:2:14: error: expression value is ignored");
|
||||
|
||||
cases.add("integer literal on a non-comptime var",
|
||||
\\export fn foo() {
|
||||
\\ var i = 0;
|
||||
\\ while (i < 10) : (i += 1) { }
|
||||
\\}
|
||||
, ".tmp_source.zig:2:5: error: unable to infer variable type");
|
||||
|
||||
cases.add("undefined literal on a non-comptime var",
|
||||
\\export fn foo() {
|
||||
\\ var i = undefined;
|
||||
\\ i = i32(1);
|
||||
\\}
|
||||
, ".tmp_source.zig:2:5: error: unable to infer variable type");
|
||||
|
||||
cases.add("dereference an array",
|
||||
\\var s_buffer: [10]u8 = undefined;
|
||||
\\pub fn pass(in: []u8) -> []u8 {
|
||||
@ -2090,4 +2076,40 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
,
|
||||
".tmp_source.zig:5:9: error: expected type '&Derp', found '&c_void'");
|
||||
|
||||
cases.add("non-const variables of things that require const variables",
|
||||
\\const Opaque = @OpaqueType();
|
||||
\\
|
||||
\\export fn entry(opaque: &Opaque) {
|
||||
\\ var m2 = &2;
|
||||
\\ const y: u32 = *m2;
|
||||
\\
|
||||
\\ var a = undefined;
|
||||
\\ var b = 1;
|
||||
\\ var c = 1.0;
|
||||
\\ var d = this;
|
||||
\\ var e = null;
|
||||
\\ var f = *opaque;
|
||||
\\ var g = i32;
|
||||
\\ var h = @import("std");
|
||||
\\ var i = (Foo {}).bar;
|
||||
\\
|
||||
\\ var z: noreturn = return;
|
||||
\\}
|
||||
\\
|
||||
\\const Foo = struct {
|
||||
\\ fn bar(self: &const Foo) {}
|
||||
\\};
|
||||
,
|
||||
".tmp_source.zig:4:4: error: variable of type '&const (integer literal)' must be const or comptime",
|
||||
".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
|
||||
".tmp_source.zig:8:4: error: variable of type '(integer literal)' must be const or comptime",
|
||||
".tmp_source.zig:9:4: error: variable of type '(float literal)' must be const or comptime",
|
||||
".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime",
|
||||
".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime",
|
||||
".tmp_source.zig:12:4: error: variable of type 'Opaque' must be const or comptime",
|
||||
".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime",
|
||||
".tmp_source.zig:14:4: error: variable of type '(namespace)' must be const or comptime",
|
||||
".tmp_source.zig:15:4: error: variable of type '(bound fn(&const Foo))' must be const or comptime",
|
||||
".tmp_source.zig:17:4: error: unreachable code");
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user