mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
no "use of undeclared identifer" in dead comptime branches
This commit is contained in:
parent
528c151a55
commit
b66438eb80
@ -2306,6 +2306,7 @@ enum IrInstructionId {
|
||||
IrInstructionIdAssertZero,
|
||||
IrInstructionIdAssertNonNull,
|
||||
IrInstructionIdHasDecl,
|
||||
IrInstructionIdUndeclaredIdent,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
@ -3519,6 +3520,12 @@ struct IrInstructionHasDecl {
|
||||
IrInstruction *name;
|
||||
};
|
||||
|
||||
struct IrInstructionUndeclaredIdent {
|
||||
IrInstruction base;
|
||||
|
||||
Buf *name;
|
||||
};
|
||||
|
||||
static const size_t slice_ptr_index = 0;
|
||||
static const size_t slice_len_index = 1;
|
||||
|
||||
|
||||
@ -5606,6 +5606,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdBitCast:
|
||||
case IrInstructionIdGlobalAsm:
|
||||
case IrInstructionIdHasDecl:
|
||||
case IrInstructionIdUndeclaredIdent:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdDeclVarGen:
|
||||
|
||||
51
src/ir.cpp
51
src/ir.cpp
@ -1015,6 +1015,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) {
|
||||
return IrInstructionIdHasDecl;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent *) {
|
||||
return IrInstructionIdUndeclaredIdent;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
@ -3031,6 +3035,15 @@ static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *s
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_undeclared_identifier(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
Buf *name)
|
||||
{
|
||||
IrInstructionUndeclaredIdent *instruction = ir_build_instruction<IrInstructionUndeclaredIdent>(irb, scope, source_node);
|
||||
instruction->name = name;
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
|
||||
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
|
||||
instruction->scope_is_comptime = scope_is_comptime;
|
||||
@ -3896,13 +3909,18 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
|
||||
|
||||
Buf *variable_name = node->data.symbol_expr.symbol;
|
||||
|
||||
if (buf_eql_str(variable_name, "_") && lval == LValPtr) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, node);
|
||||
const_instruction->base.value.type = get_pointer_to_type(irb->codegen,
|
||||
irb->codegen->builtin_types.entry_void, false);
|
||||
const_instruction->base.value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialDiscard;
|
||||
return &const_instruction->base;
|
||||
if (buf_eql_str(variable_name, "_")) {
|
||||
if (lval == LValPtr) {
|
||||
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, node);
|
||||
const_instruction->base.value.type = get_pointer_to_type(irb->codegen,
|
||||
irb->codegen->builtin_types.entry_void, false);
|
||||
const_instruction->base.value.special = ConstValSpecialStatic;
|
||||
const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialDiscard;
|
||||
return &const_instruction->base;
|
||||
} else {
|
||||
add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to"));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
}
|
||||
|
||||
ZigType *primitive_type;
|
||||
@ -3943,11 +3961,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
// put a variable of same name with invalid type in global scope
|
||||
// so that future references to this same name will find a variable with an invalid type
|
||||
populate_invalid_variable_in_scope(irb->codegen, scope, node, variable_name);
|
||||
add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
|
||||
return irb->codegen->invalid_instruction;
|
||||
return ir_build_undeclared_identifier(irb, scope, node, variable_name);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
|
||||
@ -23237,6 +23251,16 @@ static IrInstruction *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstruct
|
||||
return ir_const_bool(ira, &instruction->base, true);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstructionUndeclaredIdent *instruction) {
|
||||
// put a variable of same name with invalid type in global scope
|
||||
// so that future references to this same name will find a variable with an invalid type
|
||||
populate_invalid_variable_in_scope(ira->codegen, instruction->base.scope, instruction->base.source_node,
|
||||
instruction->name);
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("use of undeclared identifier '%s'", buf_ptr(instruction->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
|
||||
switch (instruction->id) {
|
||||
case IrInstructionIdInvalid:
|
||||
@ -23533,6 +23557,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
|
||||
return ir_analyze_instruction_check_runtime_scope(ira, (IrInstructionCheckRuntimeScope *)instruction);
|
||||
case IrInstructionIdHasDecl:
|
||||
return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction);
|
||||
case IrInstructionIdUndeclaredIdent:
|
||||
return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -23667,6 +23693,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdAssertNonNull:
|
||||
case IrInstructionIdResizeSlice:
|
||||
case IrInstructionIdGlobalAsm:
|
||||
case IrInstructionIdUndeclaredIdent:
|
||||
return true;
|
||||
|
||||
case IrInstructionIdPhi:
|
||||
|
||||
@ -1461,6 +1461,10 @@ static void ir_print_has_decl(IrPrint *irp, IrInstructionHasDecl *instruction) {
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_undeclared_ident(IrPrint *irp, IrInstructionUndeclaredIdent *instruction) {
|
||||
fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name));
|
||||
}
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
@ -1931,6 +1935,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdHasDecl:
|
||||
ir_print_has_decl(irp, (IrInstructionHasDecl *)instruction);
|
||||
break;
|
||||
case IrInstructionIdUndeclaredIdent:
|
||||
ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
||||
@ -158,10 +158,3 @@ pub const EWOULDBLOCK = 140;
|
||||
pub const EDQUOT = 10069;
|
||||
|
||||
pub const F_OK = 0;
|
||||
|
||||
// These are workarounds for "use of undeclared identifier" compile errors
|
||||
// TODO make the compiler even more lazy. don't emit "use of undeclared identifier" errors
|
||||
// for if branches that aren't taken.
|
||||
pub const SIGKILL = @compileError("Windows libc does not have this");
|
||||
|
||||
|
||||
|
||||
@ -1219,7 +1219,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:2:5: error: `_` is not a declarable symbol",
|
||||
"tmp.zig:3:12: error: use of undeclared identifier '_'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -1232,7 +1231,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:4:20: error: use of undeclared identifier '_'",
|
||||
"tmp.zig:4:20: error: `_` may only be used to assign things to",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -1248,7 +1247,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ return 1;
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:4:20: error: use of undeclared identifier '_'",
|
||||
"tmp.zig:4:20: error: `_` may only be used to assign things to",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -1266,7 +1265,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ return error.optionalReturnError;
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:6:17: error: use of undeclared identifier '_'",
|
||||
"tmp.zig:6:17: error: `_` may only be used to assign things to",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
||||
@ -93,11 +93,13 @@ pub const Vec3 = struct {
|
||||
data: [3]f32,
|
||||
};
|
||||
pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
|
||||
return Vec3{ .data = []f32{
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
} };
|
||||
return Vec3{
|
||||
.data = []f32{
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test "constant expressions" {
|
||||
@ -776,3 +778,9 @@ fn oneItem(x: i32) [1]i32 {
|
||||
fn scalar(x: u32) u32 {
|
||||
return x;
|
||||
}
|
||||
|
||||
test "no undeclared identifier error in unanalyzed branches" {
|
||||
if (false) {
|
||||
lol_this_doesnt_exist = nonsense;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user