Skip to content

Commit 5354d1f

Browse files
committedJul 13, 2018
allow == for comparing optional pointers
closes #658
1 parent ac096c2 commit 5354d1f

File tree

3 files changed

+35
-20
lines changed

3 files changed

+35
-20
lines changed
 

‎src/codegen.cpp‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,10 +2249,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
22492249
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
22502250
} else if (type_entry->id == TypeTableEntryIdEnum ||
22512251
type_entry->id == TypeTableEntryIdErrorSet ||
2252-
type_entry->id == TypeTableEntryIdPointer ||
22532252
type_entry->id == TypeTableEntryIdBool ||
2254-
type_entry->id == TypeTableEntryIdPromise ||
2255-
type_entry->id == TypeTableEntryIdFn)
2253+
get_codegen_ptr_type(type_entry) != nullptr)
22562254
{
22572255
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
22582256
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");

‎src/ir.cpp‎

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11147,7 +11147,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1114711147
if (type_is_invalid(resolved_type))
1114811148
return resolved_type;
1114911149

11150-
11150+
bool operator_allowed;
1115111151
switch (resolved_type->id) {
1115211152
case TypeTableEntryIdInvalid:
1115311153
zig_unreachable(); // handled above
@@ -11156,6 +11156,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1115611156
case TypeTableEntryIdComptimeInt:
1115711157
case TypeTableEntryIdInt:
1115811158
case TypeTableEntryIdFloat:
11159+
operator_allowed = true;
1115911160
break;
1116011161

1116111162
case TypeTableEntryIdBool:
@@ -11170,32 +11171,27 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1117011171
case TypeTableEntryIdBoundFn:
1117111172
case TypeTableEntryIdArgTuple:
1117211173
case TypeTableEntryIdPromise:
11173-
if (!is_equality_cmp) {
11174-
ir_add_error_node(ira, source_node,
11175-
buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
11176-
return ira->codegen->builtin_types.entry_invalid;
11177-
}
11178-
break;
11179-
1118011174
case TypeTableEntryIdEnum:
11181-
if (!is_equality_cmp) {
11182-
ir_add_error_node(ira, source_node,
11183-
buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
11184-
return ira->codegen->builtin_types.entry_invalid;
11185-
}
11175+
operator_allowed = is_equality_cmp;
1118611176
break;
1118711177

1118811178
case TypeTableEntryIdUnreachable:
1118911179
case TypeTableEntryIdArray:
1119011180
case TypeTableEntryIdStruct:
1119111181
case TypeTableEntryIdUndefined:
1119211182
case TypeTableEntryIdNull:
11193-
case TypeTableEntryIdOptional:
1119411183
case TypeTableEntryIdErrorUnion:
1119511184
case TypeTableEntryIdUnion:
11196-
ir_add_error_node(ira, source_node,
11197-
buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
11198-
return ira->codegen->builtin_types.entry_invalid;
11185+
operator_allowed = false;
11186+
break;
11187+
case TypeTableEntryIdOptional:
11188+
operator_allowed = is_equality_cmp && get_codegen_ptr_type(resolved_type) != nullptr;
11189+
break;
11190+
}
11191+
if (!operator_allowed) {
11192+
ir_add_error_node(ira, source_node,
11193+
buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
11194+
return ira->codegen->builtin_types.entry_invalid;
1119911195
}
1120011196

1120111197
IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);

‎test/cases/optional.zig‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,24 @@ test "optional pointer to size zero struct" {
77
var o: ?*EmptyStruct = &e;
88
assert(o != null);
99
}
10+
11+
test "equality compare nullable pointers" {
12+
testNullPtrsEql();
13+
comptime testNullPtrsEql();
14+
}
15+
16+
fn testNullPtrsEql() void {
17+
var number: i32 = 1234;
18+
19+
var x: ?*i32 = null;
20+
var y: ?*i32 = null;
21+
assert(x == y);
22+
y = &number;
23+
assert(x != y);
24+
assert(x != &number);
25+
assert(&number != x);
26+
x = &number;
27+
assert(x == y);
28+
assert(x == &number);
29+
assert(&number == x);
30+
}

0 commit comments

Comments
 (0)