Commit 7f90dbbb11
Changed files (4)
src/analyze.cpp
@@ -30,13 +30,15 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node);
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
-static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
-static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);
+static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,
+ bool depends_on_compile_var);
+static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,
+ bool depends_on_compile_var);
static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
TypeTableEntry *expected_type, uint64_t x);
static AstNode *find_decl(BlockContext *context, Buf *name);
static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
- bool pointer_only, BlockContext *block_context);
+ bool pointer_only, BlockContext *block_context, bool depends_on_compile_var);
static TopLevelDecl *get_as_top_level_decl(AstNode *node);
static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
BlockContext *context, AstNode *source_node,
@@ -2587,7 +2589,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
node->data.field_access_expr.is_member_fn = true;
FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
- return resolve_expr_const_val_as_fn(g, node, fn_entry);
+ return resolve_expr_const_val_as_fn(g, node, fn_entry, false);
} else {
add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'",
buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
@@ -2642,7 +2644,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
AstNode *decl_node = entry ? entry->value : nullptr;
if (decl_node) {
bool pointer_only = false;
- return analyze_decl_ref(g, node, decl_node, pointer_only, context);
+ return analyze_decl_ref(g, node, decl_node, pointer_only, context, false);
} else {
add_node_error(g, node,
buf_sprintf("container '%s' has no member called '%s'",
@@ -2652,7 +2654,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
} else if (child_type->id == TypeTableEntryIdPureError) {
return analyze_error_literal_expr(g, import, context, node, field_name);
} else if (wrapped_in_fn_call) { // this branch should go last, before the error in the else case
- return resolve_expr_const_val_as_type(g, node, child_type);
+ return resolve_expr_const_val_as_type(g, node, child_type, false);
} else {
add_node_error(g, node,
buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
@@ -2671,7 +2673,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
}
bool pointer_only = false;
- return analyze_decl_ref(g, node, decl_node, pointer_only, context);
+ return analyze_decl_ref(g, node, decl_node, pointer_only, context,
+ const_val->depends_on_compile_var);
} else {
const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";
add_node_error(g, node,
@@ -2770,33 +2773,44 @@ static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node)
return g->builtin_types.entry_void;
}
-static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type) {
+static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,
+ bool depends_on_compile_var)
+{
Expr *expr = get_resolved_expr(node);
expr->const_val.ok = true;
expr->const_val.data.x_type = type;
+ expr->const_val.depends_on_compile_var = depends_on_compile_var;
return g->builtin_types.entry_type;
}
-static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode *node, AstNode *other) {
+static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode *node, AstNode *other,
+ bool depends_on_compile_var)
+{
Expr *expr = get_resolved_expr(node);
Expr *other_expr = get_resolved_expr(other);
expr->const_val = other_expr->const_val;
+ expr->const_val.depends_on_compile_var = expr->const_val.depends_on_compile_var ||
+ depends_on_compile_var;
return other_expr->type_entry;
}
-static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
+static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,
+ bool depends_on_compile_var)
+{
Expr *expr = get_resolved_expr(node);
expr->const_val.ok = true;
expr->const_val.data.x_fn = fn;
+ expr->const_val.depends_on_compile_var = depends_on_compile_var;
return fn->type_entry;
}
static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,
- TypeTableEntry *type_entry)
+ TypeTableEntry *type_entry, bool depends_on_compile_var)
{
Expr *expr = get_resolved_expr(node);
expr->const_val.ok = true;
expr->const_val.data.x_type = type_entry;
+ expr->const_val.depends_on_compile_var = depends_on_compile_var;
return type_entry;
}
@@ -2922,7 +2936,7 @@ static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {
}
static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,
- BlockContext *context)
+ BlockContext *context, bool depends_on_compile_var)
{
get_resolved_expr(source_node)->variable = var;
if (!var_is_pure(var, context)) {
@@ -2931,14 +2945,15 @@ static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, Variabl
if (var->is_const && var->val_node) {
ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
if (other_const_val->ok) {
- return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node);
+ return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node,
+ depends_on_compile_var);
}
}
return var->type;
}
static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
- bool pointer_only, BlockContext *block_context)
+ bool pointer_only, BlockContext *block_context, bool depends_on_compile_var)
{
resolve_top_level_decl(g, decl_node, pointer_only);
TopLevelDecl *tld = get_as_top_level_decl(decl_node);
@@ -2948,27 +2963,29 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
if (decl_node->type == NodeTypeVariableDeclaration) {
VariableTableEntry *var = decl_node->data.variable_declaration.variable;
- return analyze_var_ref(g, source_node, var, block_context);
+ return analyze_var_ref(g, source_node, var, block_context, depends_on_compile_var);
} else if (decl_node->type == NodeTypeFnProto) {
if (decl_node->data.fn_proto.generic_params.length > 0) {
TypeTableEntry *type_entry = decl_node->data.fn_proto.generic_fn_type;
assert(type_entry);
- return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry);
+ return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry, depends_on_compile_var);
} else {
FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
assert(fn_entry->type_entry);
- return resolve_expr_const_val_as_fn(g, source_node, fn_entry);
+ return resolve_expr_const_val_as_fn(g, source_node, fn_entry, depends_on_compile_var);
}
} else if (decl_node->type == NodeTypeStructDecl) {
if (decl_node->data.struct_decl.generic_params.length > 0) {
TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type;
assert(type_entry);
- return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry);
+ return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry, depends_on_compile_var);
} else {
- return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry);
+ return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry,
+ depends_on_compile_var);
}
} else if (decl_node->type == NodeTypeTypeDecl) {
- return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry);
+ return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry,
+ depends_on_compile_var);
} else {
zig_unreachable();
}
@@ -2978,25 +2995,25 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
{
if (node->data.symbol_expr.override_type_entry) {
- return resolve_expr_const_val_as_type(g, node, node->data.symbol_expr.override_type_entry);
+ return resolve_expr_const_val_as_type(g, node, node->data.symbol_expr.override_type_entry, false);
}
Buf *variable_name = &node->data.symbol_expr.symbol;
auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
if (primitive_table_entry) {
- return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
+ return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value, false);
}
VariableTableEntry *var = find_variable(g, context, variable_name);
if (var) {
- TypeTableEntry *var_type = analyze_var_ref(g, node, var, context);
+ TypeTableEntry *var_type = analyze_var_ref(g, node, var, context, false);
return var_type;
}
AstNode *decl_node = find_decl(context, variable_name);
if (decl_node) {
- return analyze_decl_ref(g, node, decl_node, pointer_only, context);
+ return analyze_decl_ref(g, node, decl_node, pointer_only, context, false);
}
if (import->any_imports_failed) {
@@ -3819,11 +3836,11 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
return g->builtin_types.entry_invalid;
} else {
return resolve_expr_const_val_as_type(g, node,
- get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint));
+ get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false);
}
} else if (context->fn_entry) {
return resolve_expr_const_val_as_type(g, node,
- get_slice_type(g, child_type, node->data.array_type.is_const));
+ get_slice_type(g, child_type, node->data.array_type.is_const), false);
} else {
add_node_error(g, first_executing_node(size_node),
buf_sprintf("unable to evaluate constant expression"));
@@ -3831,7 +3848,7 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
}
} else {
return resolve_expr_const_val_as_type(g, node,
- get_slice_type(g, child_type, node->data.array_type.is_const));
+ get_slice_type(g, child_type, node->data.array_type.is_const), false);
}
}
@@ -3844,7 +3861,7 @@ static TypeTableEntry *analyze_fn_proto_expr(CodeGen *g, ImportTableEntry *impor
return type_entry;
}
- return resolve_expr_const_val_as_type(g, node, type_entry);
+ return resolve_expr_const_val_as_type(g, node, type_entry, false);
}
static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
@@ -4973,7 +4990,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
case TypeTableEntryIdUnion:
case TypeTableEntryIdFn:
case TypeTableEntryIdTypeDecl:
- return resolve_expr_const_val_as_type(g, node, type_entry);
+ return resolve_expr_const_val_as_type(g, node, type_entry, false);
}
}
case BuiltinFnIdCInclude:
@@ -5307,10 +5324,10 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp
AstNode *impl_decl_node = entry->value;
if (impl_decl_node->type == NodeTypeFnProto) {
FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry;
- return resolve_expr_const_val_as_fn(g, node, fn_table_entry);
+ return resolve_expr_const_val_as_fn(g, node, fn_table_entry, false);
} else if (impl_decl_node->type == NodeTypeStructDecl) {
TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry;
- return resolve_expr_const_val_as_type(g, node, type_entry);
+ return resolve_expr_const_val_as_type(g, node, type_entry, false);
} else {
zig_unreachable();
}
@@ -5324,14 +5341,14 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp
preview_fn_proto_instance(g, import, impl_decl_node, child_context);
g->generic_table.put(generic_fn_type_id, impl_decl_node);
FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry;
- return resolve_expr_const_val_as_fn(g, node, fn_table_entry);
+ return resolve_expr_const_val_as_fn(g, node, fn_table_entry, false);
} else if (decl_node->type == NodeTypeStructDecl) {
AstNode *impl_decl_node = ast_clone_subtree(decl_node, &g->next_node_index);
g->generic_table.put(generic_fn_type_id, impl_decl_node);
scan_struct_decl(g, import, child_context, impl_decl_node);
TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry;
resolve_struct_type(g, import, type_entry);
- return resolve_expr_const_val_as_type(g, node, type_entry);
+ return resolve_expr_const_val_as_type(g, node, type_entry, false);
} else {
zig_unreachable();
}
@@ -5480,7 +5497,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
return g->builtin_types.entry_invalid;
} else {
return resolve_expr_const_val_as_type(g, node,
- get_pointer_to_type(g, meta_type, is_const));
+ get_pointer_to_type(g, meta_type, is_const), false);
}
} else if (child_type->id == TypeTableEntryIdNumLitInt ||
child_type->id == TypeTableEntryIdNumLitFloat)
@@ -5520,7 +5537,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in maybe type"));
return g->builtin_types.entry_invalid;
} else {
- return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type));
+ return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type), false);
}
} else if (type_entry->id == TypeTableEntryIdUnreachable) {
add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
@@ -5548,7 +5565,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in error type"));
return g->builtin_types.entry_invalid;
} else {
- return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type));
+ return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type), false);
}
} else if (type_entry->id == TypeTableEntryIdUnreachable) {
add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type"));
@@ -6159,10 +6176,10 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
return_type = analyze_fn_proto_expr(g, import, context, expected_type, node);
break;
case NodeTypeErrorType:
- return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error);
+ return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error, false);
break;
case NodeTypeTypeLiteral:
- return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_type);
+ return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_type, false);
break;
case NodeTypeSwitchExpr:
return_type = analyze_switch_expr(g, import, context, expected_type, node);
test/a.zig
@@ -0,0 +1,1 @@
+pub const a_bool = true;
test/b.zig
@@ -0,0 +1,1 @@
+pub const a_bool = false;
test/self_hosted.zig
@@ -1656,3 +1656,17 @@ fn use_generic_param_in_generic_param() {
fn a_generic_fn(T: type, a: T)(b: T) -> T {
return a + b;
}
+
+
+#attribute("test")
+fn namespace_depends_on_compile_var() {
+ if (some_namespace.a_bool) {
+ assert(some_namespace.a_bool);
+ } else {
+ assert(!some_namespace.a_bool);
+ }
+}
+const some_namespace = switch(@compile_var("os")) {
+ linux => @import("a.zig"),
+ else => @import("b.zig"),
+};