authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-10 00:14:30-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-10 00:14:30-05:00
logb8cbe3872e702ab8ec388e75cb711330a45825b0
tree3f0162c85bee328083466f1c2d164eb4035450bb
parentcaf672c49586f1af5e3d41ae200aded991b8b0f7
signature Commit is signed but in an unrecognized format.

added C pointer type and implicit int-to-ptr for this type

See #1059

7 files changed, 210 insertions(+), 75 deletions(-)

src/all_types.hpp+1
......@@ -1038,6 +1038,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
10381038enum PtrLen {
10391039 PtrLenUnknown,
10401040 PtrLenSingle,
1041 PtrLenC,
10411042};
10421043
10431044struct ZigTypePointer {
src/analyze.cpp+13-1
......@@ -417,6 +417,18 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
417417 return entry;
418418}
419419
420static const char *ptr_len_to_star_str(PtrLen ptr_len) {
421 switch (ptr_len) {
422 case PtrLenSingle:
423 return "*";
424 case PtrLenUnknown:
425 return "[*]";
426 case PtrLenC:
427 return "[*c]";
428 }
429 zig_unreachable();
430}
431
420432ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
421433 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
422434 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
......@@ -466,7 +478,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
466478
467479 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
468480
469 const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
481 const char *star_str = ptr_len_to_star_str(ptr_len);
470482 const char *const_str = is_const ? "const " : "";
471483 const char *volatile_str = is_volatile ? "volatile " : "";
472484 buf_resize(&entry->name, 0);
src/ir.cpp+163-73
......@@ -169,6 +169,10 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
169169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
172static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
173 ZigType *ptr_type);
174static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
175 ZigType *dest_type);
172176
173177static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
174178 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -5019,10 +5023,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
50195023 return ir_build_ref(irb, scope, value->source_node, value, false, false);
50205024}
50215025
5026static PtrLen star_token_to_ptr_len(TokenId token_id) {
5027 switch (token_id) {
5028 case TokenIdStar:
5029 case TokenIdStarStar:
5030 return PtrLenSingle;
5031 case TokenIdBracketStarBracket:
5032 return PtrLenUnknown;
5033 case TokenIdBracketStarCBracket:
5034 return PtrLenC;
5035 default:
5036 zig_unreachable();
5037 }
5038}
5039
50225040static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
50235041 assert(node->type == NodeTypePointerType);
5024 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||
5025 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5042 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
50265043 bool is_const = node->data.pointer_type.is_const;
50275044 bool is_volatile = node->data.pointer_type.is_volatile;
50285045 AstNode *expr_node = node->data.pointer_type.op_expr;
......@@ -8538,6 +8555,20 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
85388555 }
85398556 }
85408557 }
8558 if (other_type->id == ZigTypeIdPointer && other_type->data.pointer.ptr_len == PtrLenC && const_val_is_int) {
8559 if (!bigint_fits_in_bits(&const_val->data.x_bigint, ira->codegen->pointer_size_bytes * 8, true) &&
8560 !bigint_fits_in_bits(&const_val->data.x_bigint, ira->codegen->pointer_size_bytes * 8, false))
8561 {
8562 Buf *val_buf = buf_alloc();
8563 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
8564
8565 ir_add_error(ira, instruction,
8566 buf_sprintf("integer value %s outside of pointer address range",
8567 buf_ptr(val_buf)));
8568 return false;
8569 }
8570 return true;
8571 }
85418572
85428573 const char *num_lit_str;
85438574 Buf *val_buf = buf_alloc();
......@@ -10811,6 +10842,37 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
1081110842 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
1081210843}
1081310844
10845static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
10846 IrInstruction *integer, ZigType *dest_type)
10847{
10848 IrInstruction *unsigned_integer;
10849 if (instr_is_comptime(integer)) {
10850 unsigned_integer = integer;
10851 } else {
10852 assert(integer->value.type->id == ZigTypeIdInt);
10853
10854 if (integer->value.type->data.integral.bit_count >
10855 ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
10856 {
10857 ir_add_error(ira, source_instr,
10858 buf_sprintf("integer type too big for implicit @intToPtr to type '%s'", buf_ptr(&dest_type->name)));
10859 return ira->codegen->invalid_instruction;
10860 }
10861
10862 if (integer->value.type->data.integral.is_signed) {
10863 ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
10864 integer->value.type->data.integral.bit_count);
10865 unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type);
10866 if (type_is_invalid(unsigned_integer->value.type))
10867 return ira->codegen->invalid_instruction;
10868 } else {
10869 unsigned_integer = integer;
10870 }
10871 }
10872
10873 return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type);
10874}
10875
1081410876static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1081510877 ZigType *wanted_type, IrInstruction *value)
1081610878{
......@@ -11217,6 +11279,14 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1121711279 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
1121811280 }
1121911281
11282 // casting to C pointers
11283 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC) {
11284 // cast from integer to C pointer
11285 if (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt) {
11286 return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
11287 }
11288 }
11289
1122011290 // cast from undefined to anything
1122111291 if (actual_type->id == ZigTypeIdUndefined) {
1122211292 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
......@@ -20674,32 +20744,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2067420744 zig_unreachable();
2067520745}
2067620746
20677static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20678 Error err;
20679 IrInstruction *dest_type_value = instruction->dest_type->child;
20680 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20681 if (type_is_invalid(dest_type))
20682 return ira->codegen->invalid_instruction;
20683
20684 IrInstruction *value = instruction->value->child;
20685 ZigType *src_type = value->value.type;
20686 if (type_is_invalid(src_type))
20687 return ira->codegen->invalid_instruction;
20688
20689 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20690 return ira->codegen->invalid_instruction;
20691
20692 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20693 return ira->codegen->invalid_instruction;
20694
20695 if (get_codegen_ptr_type(src_type) != nullptr) {
20696 ir_add_error(ira, value,
20697 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20698 return ira->codegen->invalid_instruction;
20699 }
20700
20701 switch (src_type->id) {
20747static bool type_can_bit_cast(ZigType *t) {
20748 switch (t->id) {
2070220749 case ZigTypeIdInvalid:
20750 zig_unreachable();
2070320751 case ZigTypeIdMetaType:
2070420752 case ZigTypeIdOpaque:
2070520753 case ZigTypeIdBoundFn:
......@@ -20710,42 +20758,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2071020758 case ZigTypeIdComptimeInt:
2071120759 case ZigTypeIdUndefined:
2071220760 case ZigTypeIdNull:
20713 ir_add_error(ira, dest_type_value,
20714 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
20715 return ira->codegen->invalid_instruction;
20761 case ZigTypeIdPointer:
20762 return false;
2071620763 default:
20717 break;
20764 // TODO list these types out explicitly, there are probably some other invalid ones here
20765 return true;
2071820766 }
20767}
2071920768
20720 if (get_codegen_ptr_type(dest_type) != nullptr) {
20721 ir_add_error(ira, dest_type_value,
20722 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
20769static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20770 ZigType *dest_type)
20771{
20772 Error err;
20773
20774 ZigType *src_type = value->value.type;
20775 assert(get_codegen_ptr_type(src_type) == nullptr);
20776 assert(type_can_bit_cast(src_type));
20777 assert(get_codegen_ptr_type(dest_type) == nullptr);
20778 assert(type_can_bit_cast(dest_type));
20779
20780 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20781 return ira->codegen->invalid_instruction;
20782
20783 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
2072320784 return ira->codegen->invalid_instruction;
20724 }
2072520785
20726 switch (dest_type->id) {
20727 case ZigTypeIdInvalid:
20728 case ZigTypeIdMetaType:
20729 case ZigTypeIdOpaque:
20730 case ZigTypeIdBoundFn:
20731 case ZigTypeIdArgTuple:
20732 case ZigTypeIdNamespace:
20733 case ZigTypeIdUnreachable:
20734 case ZigTypeIdComptimeFloat:
20735 case ZigTypeIdComptimeInt:
20736 case ZigTypeIdUndefined:
20737 case ZigTypeIdNull:
20738 ir_add_error(ira, dest_type_value,
20739 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20740 return ira->codegen->invalid_instruction;
20741 default:
20742 break;
20743 }
2074420786
2074520787 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
2074620788 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
2074720789 if (dest_size_bytes != src_size_bytes) {
20748 ir_add_error(ira, &instruction->base,
20790 ir_add_error(ira, source_instr,
2074920791 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
2075020792 buf_ptr(&dest_type->name), dest_size_bytes,
2075120793 buf_ptr(&src_type->name), src_size_bytes));
......@@ -20755,7 +20797,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2075520797 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
2075620798 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
2075720799 if (dest_size_bits != src_size_bits) {
20758 ir_add_error(ira, &instruction->base,
20800 ir_add_error(ira, source_instr,
2075920801 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
2076020802 buf_ptr(&dest_type->name), dest_size_bits,
2076120803 buf_ptr(&src_type->name), src_size_bits));
......@@ -20767,44 +20809,63 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2076720809 if (!val)
2076820810 return ira->codegen->invalid_instruction;
2076920811
20770 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
20812 IrInstruction *result = ir_const(ira, source_instr, dest_type);
2077120813 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
2077220814 buf_write_value_bytes(ira->codegen, buf, val);
20773 if ((err = buf_read_value_bytes(ira, ira->codegen, instruction->base.source_node, buf, &result->value)))
20815 if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value)))
2077420816 return ira->codegen->invalid_instruction;
2077520817 return result;
2077620818 }
2077720819
20778 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
20779 instruction->base.source_node, nullptr, value);
20820 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
20821 source_instr->source_node, nullptr, value);
2078020822 result->value.type = dest_type;
2078120823 return result;
2078220824}
2078320825
20784static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
20785 Error err;
20826static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
2078620827 IrInstruction *dest_type_value = instruction->dest_type->child;
2078720828 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
2078820829 if (type_is_invalid(dest_type))
2078920830 return ira->codegen->invalid_instruction;
2079020831
20791 // We explicitly check for the size, so we can use get_src_ptr_type
20792 if (get_src_ptr_type(dest_type) == nullptr) {
20793 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
20832 IrInstruction *value = instruction->value->child;
20833 ZigType *src_type = value->value.type;
20834 if (type_is_invalid(src_type))
20835 return ira->codegen->invalid_instruction;
20836
20837 if (get_codegen_ptr_type(src_type) != nullptr) {
20838 ir_add_error(ira, value,
20839 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
2079420840 return ira->codegen->invalid_instruction;
2079520841 }
2079620842
20797 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
20843 if (!type_can_bit_cast(src_type)) {
20844 ir_add_error(ira, dest_type_value,
20845 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
2079820846 return ira->codegen->invalid_instruction;
20799 if (!type_has_bits(dest_type)) {
20847 }
20848
20849 if (get_codegen_ptr_type(dest_type) != nullptr) {
2080020850 ir_add_error(ira, dest_type_value,
20801 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
20851 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
2080220852 return ira->codegen->invalid_instruction;
2080320853 }
2080420854
20805 IrInstruction *target = instruction->target->child;
20806 if (type_is_invalid(target->value.type))
20855 if (!type_can_bit_cast(dest_type)) {
20856 ir_add_error(ira, dest_type_value,
20857 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
2080720858 return ira->codegen->invalid_instruction;
20859 }
20860
20861 return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
20862}
20863
20864static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
20865 ZigType *ptr_type)
20866{
20867 assert(get_src_ptr_type(ptr_type) != nullptr);
20868 assert(type_has_bits(ptr_type));
2080820869
2080920870 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
2081020871 if (type_is_invalid(casted_int->value.type))
......@@ -20815,19 +20876,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
2081520876 if (!val)
2081620877 return ira->codegen->invalid_instruction;
2081720878
20818 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
20879 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
2081920880 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
2082020881 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
2082120882 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
2082220883 return result;
2082320884 }
2082420885
20825 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
20826 instruction->base.source_node, nullptr, casted_int);
20827 result->value.type = dest_type;
20886 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
20887 source_instr->source_node, nullptr, casted_int);
20888 result->value.type = ptr_type;
2082820889 return result;
2082920890}
2083020891
20892static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
20893 Error err;
20894 IrInstruction *dest_type_value = instruction->dest_type->child;
20895 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20896 if (type_is_invalid(dest_type))
20897 return ira->codegen->invalid_instruction;
20898
20899 // We explicitly check for the size, so we can use get_src_ptr_type
20900 if (get_src_ptr_type(dest_type) == nullptr) {
20901 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
20902 return ira->codegen->invalid_instruction;
20903 }
20904
20905 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
20906 return ira->codegen->invalid_instruction;
20907 if (!type_has_bits(dest_type)) {
20908 ir_add_error(ira, dest_type_value,
20909 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
20910 return ira->codegen->invalid_instruction;
20911 }
20912
20913
20914 IrInstruction *target = instruction->target->child;
20915 if (type_is_invalid(target->value.type))
20916 return ira->codegen->invalid_instruction;
20917
20918 return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type);
20919}
20920
2083120921static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2083220922 IrInstructionDeclRef *instruction)
2083320923{
src/parser.cpp+8
......@@ -2779,6 +2779,7 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
27792779// <- ASTERISK
27802780// / ASTERISK2
27812781// / LBRACKET ASTERISK RBRACKET
2782// / LBRACKET ASTERISK C RBRACKET
27822783static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
27832784 Token *asterisk = eat_token_if(pc, TokenIdStar);
27842785 if (asterisk != nullptr) {
......@@ -2804,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
28042805 return res;
28052806 }
28062807
2808 Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
2809 if (cptr != nullptr) {
2810 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
2811 res->data.pointer_type.star_token = cptr;
2812 return res;
2813 }
2814
28072815 return nullptr;
28082816}
28092817
src/tokenizer.cpp+18-1
......@@ -221,6 +221,7 @@ enum TokenizeState {
221221 TokenizeStateError,
222222 TokenizeStateLBracket,
223223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
224225};
225226
226227
......@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
846847 switch (c) {
847848 case '*':
848849 t.state = TokenizeStateLBracketStar;
849 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
850850 break;
851851 default:
852852 // reinterpret as just an lbracket
......@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
857857 }
858858 break;
859859 case TokenizeStateLBracketStar:
860 switch (c) {
861 case 'c':
862 t.state = TokenizeStateLBracketStarC;
863 set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
864 break;
865 case ']':
866 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
867 end_token(&t);
868 t.state = TokenizeStateStart;
869 break;
870 default:
871 invalid_char_error(&t, c);
872 }
873 break;
874 case TokenizeStateLBracketStarC:
860875 switch (c) {
861876 case ']':
862877 end_token(&t);
......@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
14911506 case TokenizeStateLineStringContinue:
14921507 case TokenizeStateLineStringContinueC:
14931508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
14941510 tokenize_error(&t, "unexpected EOF");
14951511 break;
14961512 case TokenizeStateLineComment:
......@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
15281544 case TokenIdBitShiftRightEq: return ">>=";
15291545 case TokenIdBitXorEq: return "^=";
15301546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
15311548 case TokenIdCharLiteral: return "CharLiteral";
15321549 case TokenIdCmpEq: return "==";
15331550 case TokenIdCmpGreaterOrEq: return ">=";
src/tokenizer.hpp+1
......@@ -29,6 +29,7 @@ enum TokenId {
2929 TokenIdBitShiftRightEq,
3030 TokenIdBitXorEq,
3131 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
3233 TokenIdCharLiteral,
3334 TokenIdCmpEq,
3435 TokenIdCmpGreaterOrEq,
test/stage1/behavior/pointers.zig+6
......@@ -42,3 +42,9 @@ test "double pointer parsing" {
4242fn PtrOf(comptime T: type) type {
4343 return *T;
4444}
45
46test "assigning integer to C pointer" {
47 var x: i32 = 0;
48 var ptr: [*c]u8 = 0;
49 var ptr2: [*c]u8 = x;
50}