Commit bf3d1c1aab

Jimmi HC <jhc@liab.dk>
2018-06-08 09:21:31
Allow access of array.len through a pointer
1 parent ffb089a
Changed files (4)
src/analyze.cpp
@@ -3761,14 +3761,24 @@ static bool is_container(TypeTableEntry *type_entry) {
     zig_unreachable();
 }
 
+bool is_ref(TypeTableEntry *type_entry) {
+    return type_entry->id == TypeTableEntryIdPointer && type_entry->data.pointer.ptr_len == PtrLenSingle;
+}
+
+bool is_array_ref(TypeTableEntry *type_entry) {
+    TypeTableEntry *array = is_ref(type_entry) ?
+        type_entry->data.pointer.child_type : type_entry;
+    return array->id == TypeTableEntryIdArray;
+}
+
 bool is_container_ref(TypeTableEntry *type_entry) {
-    return (type_entry->id == TypeTableEntryIdPointer && type_entry->data.pointer.ptr_len == PtrLenSingle) ?
+    return is_ref(type_entry) ?
         is_container(type_entry->data.pointer.child_type) : is_container(type_entry);
 }
 
 TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) {
     assert(is_container_ref(type_entry));
-    return (type_entry->id == TypeTableEntryIdPointer && type_entry->data.pointer.ptr_len == PtrLenSingle) ?
+    return is_ref(type_entry) ?
         type_entry->data.pointer.child_type : type_entry;
 }
 
src/analyze.hpp
@@ -70,6 +70,8 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
 TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
 TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
 
+bool is_ref(TypeTableEntry *type_entry);
+bool is_array_ref(TypeTableEntry *type_entry);
 bool is_container_ref(TypeTableEntry *type_entry);
 void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
 void scan_import(CodeGen *g, ImportTableEntry *import);
src/ir.cpp
@@ -13846,10 +13846,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
             ir_link_new_instruction(result, &field_ptr_instruction->base);
             return result->value.type;
         }
-    } else if (container_type->id == TypeTableEntryIdArray) {
+    } else if (is_array_ref(container_type)) {
         if (buf_eql_str(field_name, "len")) {
             ConstExprValue *len_val = create_const_vals(1);
-            init_const_usize(ira->codegen, len_val, container_type->data.array.len);
+            if (container_type->id == TypeTableEntryIdPointer) {
+                init_const_usize(ira->codegen, len_val, container_type->data.pointer.child_type->data.array.len);
+            } else {
+                init_const_usize(ira->codegen, len_val, container_type->data.array.len);
+            }
 
             TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
             bool ptr_is_const = true;
test/cases/array.zig
@@ -116,6 +116,15 @@ test "array len property" {
     assert(@typeOf(x).len == 5);
 }
 
+test "array len field" {
+    var arr = [4]u8{ 0, 0, 0, 0 };
+    var ptr = &arr;
+    assert(arr.len == 4);
+    comptime assert(arr.len == 4);
+    assert(ptr.len == 4);
+    comptime assert(ptr.len == 4);
+}
+
 test "single-item pointer to array indexing and slicing" {
     testSingleItemPtrArrayIndexSlice();
     comptime testSingleItemPtrArrayIndexSlice();
@@ -143,4 +152,3 @@ fn testImplicitCastSingleItemPtr() void {
     slice[0] += 1;
     assert(byte == 101);
 }
-