aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp62
1 files changed, 52 insertions, 10 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 1e83a51b5b..aeeefb3eed 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -208,6 +208,7 @@ bool type_is_complete(TypeTableEntry *type_entry) {
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
return true;
}
zig_unreachable();
@@ -245,6 +246,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
return true;
}
zig_unreachable();
@@ -921,6 +923,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
assert(param_node->type == NodeTypeParamDecl);
bool param_is_inline = param_node->data.param_decl.is_inline;
+ bool param_is_var_args = param_node->data.param_decl.is_var_args;
if (param_is_inline) {
if (fn_type_id.is_extern) {
@@ -929,6 +932,13 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
return g->builtin_types.entry_invalid;
}
return get_generic_fn_type(g, &fn_type_id);
+ } else if (param_is_var_args) {
+ if (fn_type_id.is_extern) {
+ fn_type_id.param_count = fn_type_id.next_param_index;
+ continue;
+ } else {
+ return get_generic_fn_type(g, &fn_type_id);
+ }
}
TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type);
@@ -939,6 +949,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdArgTuple:
add_node_error(g, param_node->data.param_decl.type,
buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
@@ -989,6 +1000,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
+ case TypeTableEntryIdArgTuple:
add_node_error(g, fn_proto->return_type,
buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name)));
return g->builtin_types.entry_invalid;
@@ -1558,13 +1570,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
AstNode *fn_def_node = fn_proto->fn_def_node;
- if (fn_def_node && fn_proto->is_var_args) {
- add_node_error(g, proto_node,
- buf_sprintf("variadic arguments only allowed in extern function declarations"));
- tld_fn->base.resolution = TldResolutionInvalid;
- return;
- }
-
FnTableEntry *fn_table_entry = create_fn(tld_fn->base.source_node);
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
@@ -1799,6 +1804,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdBlock:
+ case TypeTableEntryIdArgTuple:
add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
buf_ptr(&underlying_type->name)));
return g->builtin_types.entry_invalid;
@@ -2210,6 +2216,7 @@ static bool is_container(TypeTableEntry *type_entry) {
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
return false;
}
zig_unreachable();
@@ -2260,6 +2267,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdVar:
case TypeTableEntryIdEnumTag:
+ case TypeTableEntryIdArgTuple:
zig_unreachable();
}
}
@@ -2290,7 +2298,13 @@ void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, Vari
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i);
- Buf *param_name = param_decl_node ? param_decl_node->data.param_decl.name : buf_sprintf("arg%zu", i);
+ Buf *param_name;
+ bool is_var_args = param_decl_node && param_decl_node->data.param_decl.is_var_args;
+ if (param_decl_node && !is_var_args) {
+ param_name = param_decl_node->data.param_decl.name;
+ } else {
+ param_name = buf_sprintf("arg%zu", i);
+ }
TypeTableEntry *param_type = param_info->type;
bool is_noalias = param_info->is_noalias;
@@ -2308,6 +2322,7 @@ void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, Vari
param_name, true, create_const_runtime(param_type));
var->src_arg_index = i;
fn_table_entry->child_scope = var->child_scope;
+ var->shadowable = var->shadowable || is_var_args;
if (type_has_bits(param_type)) {
fn_table_entry->variable_list.append(var);
@@ -2627,6 +2642,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdVar:
+ case TypeTableEntryIdArgTuple:
zig_unreachable();
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdVoid:
@@ -2742,6 +2758,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
case TypeTableEntryIdFloat:
case TypeTableEntryIdNumLitFloat:
return const_val->data.x_bignum.data.x_float * UINT32_MAX;
+ case TypeTableEntryIdArgTuple:
+ return const_val->data.x_arg_tuple.start_index * 281907309 +
+ const_val->data.x_arg_tuple.end_index * 2290442768;
case TypeTableEntryIdPointer:
return hash_ptr(const_val->data.x_ptr.base_ptr) + hash_size(const_val->data.x_ptr.index);
case TypeTableEntryIdUndefLit:
@@ -2805,7 +2824,7 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
assert(a->fn_entry);
if (a->fn_entry != b->fn_entry) return false;
- assert(a->param_count == b->param_count);
+ if (a->param_count != b->param_count) return false;
for (size_t i = 0; i < a->param_count; i += 1) {
ConstExprValue *a_val = &a->params[i];
ConstExprValue *b_val = &b->params[i];
@@ -2904,6 +2923,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdVar:
+ case TypeTableEntryIdArgTuple:
zig_unreachable();
case TypeTableEntryIdArray:
return type_of_first_thing_in_memory(type_entry->data.array.child_type);
@@ -2946,6 +2966,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdBoundFn:
+ case TypeTableEntryIdArgTuple:
return true;
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
@@ -3155,6 +3176,20 @@ ConstExprValue *create_const_ptr(CodeGen *g, ConstExprValue *base_ptr, size_t in
return const_val;
}
+void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->type = g->builtin_types.entry_arg_tuple;
+ const_val->data.x_arg_tuple.start_index = arg_index_start;
+ const_val->data.x_arg_tuple.end_index = arg_index_end;
+}
+
+ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end) {
+ ConstExprValue *const_val = allocate<ConstExprValue>(1);
+ init_const_arg_tuple(g, const_val, arg_index_start, arg_index_end);
+ return const_val;
+}
+
+
void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) {
if (type_entry->id == TypeTableEntryIdStruct) {
if (!type_entry->data.structure.complete)
@@ -3245,6 +3280,9 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
return a->data.x_import == b->data.x_import;
case TypeTableEntryIdBlock:
return a->data.x_block == b->data.x_block;
+ case TypeTableEntryIdArgTuple:
+ return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index &&
+ a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index;
case TypeTableEntryIdBoundFn:
case TypeTableEntryIdInvalid:
case TypeTableEntryIdUnreachable:
@@ -3506,7 +3544,11 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));
return;
}
+ case TypeTableEntryIdArgTuple:
+ {
+ buf_appendf(buf, "(args value)");
+ return;
+ }
}
zig_unreachable();
}
-