aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-04-07 17:56:01 -0400
committerAndrew Kelley <superjoe30@gmail.com>2017-04-07 17:56:01 -0400
commit7611ed3484ad810fe10d3c303a04d66bfa0bd6fd (patch)
treedc0b432b5abc0b0cb46e917f2fa30ae99e4ba515 /src/ir.cpp
parent5eb78ba1772b54af1ecfb1cd28cb0f1c46dab9b3 (diff)
downloadzig-7611ed3484ad810fe10d3c303a04d66bfa0bd6fd.tar.gz
zig-7611ed3484ad810fe10d3c303a04d66bfa0bd6fd.zip
allow implicit cast from `[N]T` to `&const []const T`
closes #296
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 625bff3b38..b3f647db70 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -5751,6 +5751,10 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
return false;
}
+static bool is_slice(TypeTableEntry *type) {
+ return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
+}
+
enum ImplicitCastMatchResult {
ImplicitCastMatchResultNo,
ImplicitCastMatchResultYes,
@@ -5837,6 +5841,22 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
}
}
+ // implicit [N]T to &const []const N
+ if (expected_type->id == TypeTableEntryIdPointer &&
+ expected_type->data.pointer.is_const &&
+ is_slice(expected_type->data.pointer.child_type) &&
+ actual_type->id == TypeTableEntryIdArray)
+ {
+ TypeTableEntry *ptr_type =
+ expected_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
+ assert(ptr_type->id == TypeTableEntryIdPointer);
+ if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
+ types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ {
+ return ImplicitCastMatchResultYes;
+ }
+ }
+
// implicit number literal to typed number
// implicit number literal to &const integer
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
@@ -5883,10 +5903,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
return ImplicitCastMatchResultNo;
}
-static bool is_slice(TypeTableEntry *type) {
- return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
-}
-
static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {
assert(instruction_count >= 1);
IrInstruction *prev_inst = instructions[0];
@@ -6860,6 +6876,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
+ // explicit cast from [N]T to &const []const N
+ if (wanted_type->id == TypeTableEntryIdPointer &&
+ wanted_type->data.pointer.is_const &&
+ is_slice(wanted_type->data.pointer.child_type) &&
+ actual_type->id == TypeTableEntryIdArray)
+ {
+ TypeTableEntry *ptr_type =
+ wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
+ assert(ptr_type->id == TypeTableEntryIdPointer);
+ if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
+ types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+ {
+ IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
+ if (type_is_invalid(cast1->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+ if (type_is_invalid(cast2->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return cast2;
+ }
+ }
+
// explicit cast from []T to []u8 or []u8 to []T
if (is_slice(wanted_type) && is_slice(actual_type) &&
(is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||