diff --git a/example/structs/structs.zig b/example/structs/structs.zig index 53a7cad1d1..e4e949c62b 100644 --- a/example/structs/structs.zig +++ b/example/structs/structs.zig @@ -11,6 +11,13 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { test_foo(foo); + modify_foo(&foo); + + if foo.c != 100 { + print_str("BAD\n"); + } + + print_str("OK\n"); return 0; } @@ -21,7 +28,11 @@ struct Foo { } fn test_foo(foo : Foo) { - if foo.b { - print_str("OK\n" as string); + if !foo.b { + print_str("BAD\n"); } } + +fn modify_foo(foo : &Foo) { + foo.c = 100; +} diff --git a/src/analyze.cpp b/src/analyze.cpp index ebf1f853c1..b0e12925b4 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -116,6 +116,9 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool entry->align_in_bits = g->pointer_size_bytes * 8; entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type, entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name)); + entry->data.pointer.child_type = child_type; + entry->data.pointer.is_const = is_const; + g->type_table.put(&entry->name, entry); *parent_pointer = entry; return entry; @@ -575,6 +578,10 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, case TypeTableEntryIdFloat: if (is_num_lit_float(num_lit)) { return lit_size_in_bits <= other_type->size_in_bits; + } else if (other_type->size_in_bits == 32) { + return lit_size_in_bits < 24; + } else if (other_type->size_in_bits == 64) { + return lit_size_in_bits < 53; } else { return false; } @@ -810,14 +817,19 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i TypeTableEntry *return_type; - if (struct_type->id == TypeTableEntryIdStruct) { + if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && + struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) + { assert(node->codegen_node); FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node; assert(codegen_field_access); Buf *field_name = &node->data.field_access_expr.field_name; - get_struct_field(struct_type, field_name, + TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? + struct_type : struct_type->data.pointer.child_type; + + get_struct_field(bare_struct_type, field_name, &codegen_field_access->type_struct_field, &codegen_field_access->field_index); if (codegen_field_access->type_struct_field) { diff --git a/src/analyze.hpp b/src/analyze.hpp index 2774ea8530..0d4159ea2b 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -20,8 +20,8 @@ struct VariableTableEntry; struct CastNode; struct TypeTableEntryPointer { - TypeTableEntry *pointer_child; - bool pointer_is_const; + TypeTableEntry *child_type; + bool is_const; }; struct TypeTableEntryInt { diff --git a/src/codegen.cpp b/src/codegen.cpp index 0cc803d63c..c29e3653eb 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -248,6 +248,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) { TypeTableEntry *type_entry; LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry); return LLVMBuildLoad(g->builder, ptr, ""); + } else if (struct_type->id == TypeTableEntryIdPointer) { + zig_panic("TODO struct pointer access"); } else { zig_panic("gen_field_access_expr bad struct type"); } diff --git a/src/parser.cpp b/src/parser.cpp index 572309bed7..3231cc0d2f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1153,12 +1153,13 @@ static PrefixOp tok_to_prefix_op(Token *token) { case TokenIdBang: return PrefixOpBoolNot; case TokenIdDash: return PrefixOpNegation; case TokenIdTilde: return PrefixOpBinNot; + case TokenIdAmpersand: return PrefixOpAddressOf; default: return PrefixOpInvalid; } } /* -PrefixOp : token(Not) | token(Dash) | token(Tilde) +PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const))) */ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -1171,6 +1172,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man } } *token_index += 1; + + if (result == PrefixOpAddressOf) { + Token *token = &pc->tokens->at(*token_index); + if (token->id == TokenIdKeywordConst) { + *token_index += 1; + result = PrefixOpConstAddressOf; + } + } + return result; } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index e7729e5a42..8fd17c4d1a 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -569,6 +569,11 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { foo.a += 1; foo.b = foo.a == 1; test_foo(foo); + test_mutation(&foo); + if foo.c != 100 { + print_str("BAD\n"); + } + print_str("OK\n"); return 0; } struct Foo { @@ -577,9 +582,12 @@ struct Foo { c : f32, } fn test_foo(foo : Foo) { - if foo.b { - print_str("OK\n"); + if !foo.b { + print_str("BAD\n"); } +} +fn test_mutation(foo : &Foo) { + foo.c = 100; } )SOURCE", "OK\n");