From e54679c01ea237766928ad8caf7ee05e5ca4ccb8 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 9 Dec 2021 02:15:05 +0100 Subject: [PATCH] Remove string literals. --- src/compiler/codegen_general.c | 1 - src/compiler/compiler_internal.h | 4 +- src/compiler/enums.h | 1 - src/compiler/headers.c | 2 - src/compiler/llvm_codegen.c | 2 - src/compiler/llvm_codegen_c_abi_x64.c | 2 - src/compiler/llvm_codegen_c_abi_x86.c | 2 - src/compiler/llvm_codegen_debug_info.c | 1 - src/compiler/llvm_codegen_expr.c | 16 +---- src/compiler/llvm_codegen_type.c | 2 - src/compiler/parse_expr.c | 3 +- src/compiler/sema_casts.c | 48 +++++++-------- src/compiler/sema_decls.c | 3 +- src/compiler/sema_expr.c | 11 +--- src/compiler/sema_stmts.c | 4 +- src/compiler/sema_types.c | 1 - src/compiler/types.c | 60 ++++++++++++------- test/test_suite/compile_time/ct_switch.c3t | 14 ++--- .../compile_time/ct_switch_type_check.c3t | 6 +- .../compile_time_introspection/qnameof.c3t | 18 +++--- test/test_suite/strings/string_to_array.c3t | 24 ++++++++ test/test_suite/symbols/various.c3 | 2 +- test/test_suite/types/enum_errors.c3 | 2 +- 23 files changed, 113 insertions(+), 116 deletions(-) create mode 100644 test/test_suite/strings/string_to_array.c3t diff --git a/src/compiler/codegen_general.c b/src/compiler/codegen_general.c index 43d393586..f1ee04af1 100644 --- a/src/compiler/codegen_general.c +++ b/src/compiler/codegen_general.c @@ -210,7 +210,6 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements) case TYPE_VOID: case TYPE_TYPEID: case TYPE_FUNC: - case TYPE_STRLIT: case TYPE_SUBARRAY: case CT_TYPES: case TYPE_FAILABLE_ANY: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 1a1d72a30..060973549 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -148,7 +148,7 @@ typedef struct struct { const char *chars; - uint32_t len; + ArraySize len; } string; Decl *enum_val; Decl *err_val; @@ -1526,7 +1526,7 @@ extern Type *poisoned_type; extern TypeInfo *poisoned_type_info; -extern Type *type_bool, *type_void, *type_compstr, *type_voidptr; +extern Type *type_bool, *type_void, *type_voidptr; extern Type *type_half, *type_float, *type_double, *type_quad; extern Type *type_ichar, *type_short, *type_int, *type_long, *type_isize; extern Type *type_char, *type_ushort, *type_uint, *type_ulong, *type_usize; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 1a289e757..0fb8b9311 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -549,7 +549,6 @@ typedef enum TYPE_BITSTRUCT, TYPE_ERRTYPE, TYPE_TYPEDEF, - TYPE_STRLIT, TYPE_DISTINCT, TYPE_ARRAY, TYPE_SUBARRAY, diff --git a/src/compiler/headers.c b/src/compiler/headers.c index 0291fbf09..fe192ec16 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -112,8 +112,6 @@ static void header_print_type(FILE *file, Type *type) break; case TYPE_TYPEDEF: break; - case TYPE_STRLIT: - UNREACHABLE case TYPE_ARRAY: break; case TYPE_ANY: diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index ab6faaa29..30c284a1e 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -339,8 +339,6 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value) llvm_value_set_address_align(value, member.value, type_get_ptr(value->type->array.base), type_abi_alignment(value->type->array.base)); return; } - case TYPE_STRLIT: - return; default: UNREACHABLE } diff --git a/src/compiler/llvm_codegen_c_abi_x64.c b/src/compiler/llvm_codegen_c_abi_x64.c index 8caa6002d..c5066133e 100644 --- a/src/compiler/llvm_codegen_c_abi_x64.c +++ b/src/compiler/llvm_codegen_c_abi_x64.c @@ -398,7 +398,6 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X case TYPE_TYPEID: case TYPE_FUNC: case TYPE_DISTINCT: - case TYPE_STRLIT: case TYPE_ANYERR: case TYPE_ERRTYPE: case TYPE_BITSTRUCT: @@ -588,7 +587,6 @@ AbiType *x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_ty case TYPE_FUNC: case TYPE_TYPEDEF: case TYPE_DISTINCT: - case TYPE_STRLIT: case TYPE_ANYERR: case TYPE_ERRTYPE: case TYPE_BITSTRUCT: diff --git a/src/compiler/llvm_codegen_c_abi_x86.c b/src/compiler/llvm_codegen_c_abi_x86.c index dd0a08c36..b1f14a0ea 100644 --- a/src/compiler/llvm_codegen_c_abi_x86.c +++ b/src/compiler/llvm_codegen_c_abi_x86.c @@ -113,7 +113,6 @@ static bool x86_should_return_type_in_reg(Type *type) case TYPE_TYPEDEF: case TYPE_DISTINCT: case TYPE_ENUM: - case TYPE_STRLIT: case TYPE_ERRTYPE: case TYPE_TYPEID: case TYPE_ANYERR: @@ -595,7 +594,6 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type) case TYPE_FUNC: case TYPE_TYPEID: case TYPE_BITSTRUCT: - case TYPE_STRLIT: case TYPE_FAILABLE: case TYPE_FAILABLE_ANY: case CT_TYPES: diff --git a/src/compiler/llvm_codegen_debug_info.c b/src/compiler/llvm_codegen_debug_info.c index 859beea21..62649c1a5 100644 --- a/src/compiler/llvm_codegen_debug_info.c +++ b/src/compiler/llvm_codegen_debug_info.c @@ -495,7 +495,6 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type * switch (type->type_kind) { case TYPE_TYPEID: - case TYPE_STRLIT: case CT_TYPES: UNREACHABLE case TYPE_FAILABLE: diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index ee7e0ca2f..005c5a4ae 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -514,11 +514,6 @@ static inline void llvm_emit_subscript_addr_with_base(GenContext *c, BEValue *re llvm_value_set_address_align(result, ptr, type->array.base, type_abi_alignment(type->array.base)); } return; - case TYPE_STRLIT: - // TODO insert trap on overflow. - llvm_value_set_address_align(result, llvm_emit_pointer_inbounds_gep_raw(c, llvm_get_type(c, type_char), parent->value, index->value), - type_char, type_abi_alignment(type_char)); - return; default: UNREACHABLE @@ -2131,9 +2126,6 @@ void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_l case TYPE_ARRAY: llvm_value_set(be_value, llvm_const_int(c, type_usize, expr_to_len->type->array.len), type_usize); break; - case TYPE_STRLIT: - TODO - break; default: UNREACHABLE } @@ -2206,8 +2198,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r case TYPE_ARRAY: parent_base = parent_addr; break; - case TYPE_STRLIT: - TODO default: UNREACHABLE } @@ -2236,8 +2226,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r case TYPE_ARRAY: llvm_value_set_int(c, &len, type_usize, parent_type->array.len); break; - case TYPE_STRLIT: - TODO default: UNREACHABLE } @@ -3129,7 +3117,6 @@ void llvm_emit_derived_backend_type(GenContext *c, Type *type) case TYPE_TYPEDEF: original_type = original_type->canonical; continue; - case TYPE_STRLIT: case TYPE_INFERRED_ARRAY: case TYPE_UNTYPED_LIST: case TYPE_FAILABLE_ANY: @@ -3787,7 +3774,7 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr) expr->const_expr.string.len, 0)); llvm_set_alignment(global_name, 1); - global_name = LLVMConstBitCast(global_name, LLVMPointerType(llvm_get_type(c, type_char), 0)); + global_name = LLVMConstBitCast(global_name, llvm_get_ptr_type(c, type_get_array(type_char, expr->const_expr.string.len))); llvm_value_set(be_value, global_name, type); return; } @@ -3867,7 +3854,6 @@ static void llvm_expand_type_to_args(GenContext *context, Type *param_type, LLVM case TYPE_TYPEID: case TYPE_FUNC: case TYPE_DISTINCT: - case TYPE_STRLIT: case TYPE_ENUM: case TYPE_ERRTYPE: case TYPE_ANYERR: diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index d5ce7962a..327935c38 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -351,8 +351,6 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type) return any_type->backend_type = LLVMIntTypeInContext(c->context, 8U); case TYPE_POINTER: return any_type->backend_type = llvm_type_from_ptr(c, any_type); - case TYPE_STRLIT: - return any_type->backend_type = LLVMPointerType(llvm_get_type(c, type_char), 0); case TYPE_ARRAY: return any_type->backend_type = llvm_type_from_array(c, any_type); case TYPE_SUBARRAY: diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 8413c80a5..07a40c4d9 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -1425,7 +1425,6 @@ static Expr *parse_string_literal(Context *context, Expr *left) { assert(!left && "Had left hand side"); Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, context->tok); - expr_string->type = type_compstr; TokenData *data = TOKDATA(context->tok); const char *str = data->string; @@ -1454,7 +1453,7 @@ static Expr *parse_string_literal(Context *context, Expr *left) assert(str); expr_string->const_expr.string.chars = str; expr_string->const_expr.string.len = (uint32_t)len; - expr_string->type = type_compstr; + expr_string->type = type_get_ptr(type_get_array(type_char, len)); expr_string->const_expr.const_kind = CONST_STRING; return expr_string; } diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 6d6d99fd3..0e2ce49fa 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -67,6 +67,10 @@ bool pointer_to_pointer(Expr* expr, Type *type) { if (insert_runtime_cast_unless_const(expr, CAST_PTRPTR, type)) return true; + if (expr->const_expr.const_kind == CONST_STRING) + { + return insert_cast(expr, CAST_PTRPTR, type); + } // Must have been a null expr->type = type; expr->const_expr.narrowable = false; @@ -374,7 +378,6 @@ CastKind cast_to_bool_kind(Type *type) case TYPE_VOID: case TYPE_STRUCT: case TYPE_UNION: - case TYPE_STRLIT: case TYPE_ENUM: case TYPE_FUNC: case TYPE_ARRAY: @@ -492,10 +495,6 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, FALLTHROUGH; case TYPE_UNION: return type_is_structurally_equivalent(from_type, to_type); - case TYPE_STRLIT: - if (to_kind == TYPE_POINTER) return true; - if (to_kind == TYPE_SUBARRAY && (to_type->array.base == type_char || to_type->array.base == type_ichar)) return true; - return false; case TYPE_SUBARRAY: return to_kind == TYPE_POINTER; case TYPE_VECTOR: @@ -604,9 +603,6 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool return type_is_subtype(to->pointer, from->pointer); } - // 4c. Assigning a compile time string to char* is fine. TODO fix correct later - if (from->type_kind == TYPE_STRLIT && to->pointer == type_char) return true; - return false; } @@ -621,10 +617,6 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool { // 5a. char[] foo = "test" Type *base = to->array.base; - if (from->type_kind == TYPE_STRLIT && (base->type_kind == TYPE_I8 || base->type_kind == TYPE_U8)) - { - return true; - } // 5b. Assign sized array pointer int[] = int[4]* if (type_is_pointer(from)) @@ -635,15 +627,6 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool } - // 7. In the case of distinct types, we allow implicit conversion from literal types. - if (to->type_kind == TYPE_DISTINCT) - { - if (from->type_kind == TYPE_STRLIT) - { - return cast_may_implicit(from, type_flatten(to), is_simple_expr, failable_allowed); - } - } - // 8. Check if we may cast this to bool. It is safe for many types. if (to->type_kind == TYPE_BOOL) @@ -1016,12 +999,30 @@ static void sema_error_const_int_out_of_range(Expr *expr, Expr *problem, Type *t SEMA_ERROR(problem, "The value '%s' is out of range for %s, so you need an explicit cast to truncate the value.", error_value, type_quoted_error_string(to_type)); } + +static inline bool cast_maybe_string_lit_to_char_array(Expr *expr, Type *expr_canonical, Type *to_canonical) +{ + if (expr->expr_kind != EXPR_CONST || expr->const_expr.const_kind != CONST_STRING) return false; + if (expr_canonical->type_kind != TYPE_POINTER) return false; + if (to_canonical->type_kind != TYPE_ARRAY && to_canonical->type_kind != TYPE_INFERRED_ARRAY) return false; + if (to_canonical->array.base != type_char) return false; + Type *pointer = expr_canonical->pointer; + if (pointer->type_kind != TYPE_ARRAY) return false; + if (pointer->array.base != type_char) return false; + expr_insert_deref(expr); + return true; +} bool cast_implicit(Expr *expr, Type *to_type) { assert(!type_is_failable(to_type)); Type *expr_type = expr->type; Type *expr_canonical = expr_type->canonical; Type *to_canonical = to_type->canonical; + if (cast_maybe_string_lit_to_char_array(expr, expr_canonical, to_canonical)) + { + expr_type = expr->type; + expr_canonical = expr_type->canonical; + } if (expr_canonical == to_canonical) return true; bool is_simple = expr_is_simple(expr); if (!cast_may_implicit(expr_canonical, to_canonical, is_simple, true)) @@ -1268,11 +1269,6 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type) return insert_cast(expr, CAST_STST, to_type); } // Starting in a little while... break; - case TYPE_STRLIT: - to = type_flatten(to); - if (to->type_kind == TYPE_POINTER) return insert_cast(expr, CAST_STRPTR, to_type); - if (to->type_kind == TYPE_SUBARRAY) return string_literal_to_subarray(expr, to_type); - break; case TYPE_SUBARRAY: if (to->type_kind == TYPE_POINTER) return insert_cast(expr, CAST_SAPTR, to); if (to->type_kind == TYPE_BOOL) return subarray_to_bool(expr); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 5e0952d1d..205937398 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -683,7 +683,6 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl) decl->distinct_decl.base_type = base; switch (base->type_kind) { - case TYPE_STRLIT: case TYPE_FUNC: case TYPE_TYPEDEF: case TYPE_DISTINCT: @@ -1166,7 +1165,7 @@ AttributeType sema_analyse_attribute(Context *context, Attr *attr, AttributeDoma return ATTRIBUTE_NONE; } if (!sema_analyse_expr(context, attr->expr)) return false; - if (attr->expr->expr_kind != EXPR_CONST || attr->expr->type->canonical != type_compstr) + if (attr->expr->expr_kind != EXPR_CONST || attr->expr->const_expr.const_kind != CONST_STRING) { SEMA_ERROR(attr->expr, "Expected a constant string value as argument."); return ATTRIBUTE_NONE; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 9605903b1..7155fc450 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2326,7 +2326,6 @@ static bool expr_check_index_in_range(Context *context, Type *type, Expr *index_ } break; } - case TYPE_STRLIT: case TYPE_SUBARRAY: // If not from end, just check the negative values. if (!from_end) break; @@ -2610,9 +2609,10 @@ static inline void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *str expr_to_rewrite->expr_kind = EXPR_CONST; expr_to_rewrite->const_expr.const_kind = CONST_STRING; expr_to_rewrite->const_expr.string.chars = (char *)string; - expr_to_rewrite->const_expr.string.len = (uint32_t)strlen(string); + ArraySize len = (ArraySize)strlen(string); + expr_to_rewrite->const_expr.string.len = len; expr_to_rewrite->resolve_status = RESOLVE_DONE; - expr_to_rewrite->type = type_compstr; + expr_to_rewrite->type = type_get_ptr(type_get_array(type_char, len)); } @@ -2972,11 +2972,6 @@ CHECK_DEEPER: // 9. Fix hard coded function `len` on subarrays and arrays if (!is_macro && kw == kw_len) { - if (flat_type->type_kind == TYPE_STRLIT) - { - expr_rewrite_to_int_const(expr, type_isize, parent->const_expr.string.len, true); - return true; - } if (flat_type->type_kind == TYPE_SUBARRAY) { expr->expr_kind = EXPR_LEN; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index d6a86c26d..016e89aa7 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -2099,7 +2099,7 @@ bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement) if (message) { if (!sema_analyse_expr(context, message)) return false; - if (message->type->type_kind != TYPE_STRLIT) + if (message->expr_kind != EXPR_CONST || message->const_expr.const_kind != CONST_STRING) { SEMA_ERROR(message, "Expected a string as the error message."); } @@ -2175,7 +2175,7 @@ bool sema_analyse_assert_stmt(Context *context, Ast *statement) if (message) { if (!sema_analyse_expr(context, message)) return false; - if (message->type->type_kind != TYPE_STRLIT) + if (message->expr_kind != EXPR_CONST || message->const_expr.const_kind != CONST_STRING) { SEMA_ERROR(message, "Expected a string as the error message."); } diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 128f016fe..674bbe1eb 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -193,7 +193,6 @@ bool sema_resolve_type(Context *context, Type *type) case TYPE_TYPEID: case TYPE_ANY: case TYPE_ANYERR: - case TYPE_STRLIT: case TYPE_VECTOR: case TYPE_TYPEINFO: case TYPE_UNTYPED_LIST: diff --git a/src/compiler/types.c b/src/compiler/types.c index 0984ab721..2f0c545cd 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -12,7 +12,7 @@ static struct Type f16, f32, f64, f128, fxx; Type usz, isz, uptr, iptr, uptrdiff, iptrdiff; Type voidstar, typeid, anyerr, typeinfo, ctlist; - Type str, any, anyfail; + Type any, anyfail; } t; Type *type_bool = &t.u1; @@ -41,7 +41,6 @@ Type *type_u128 = &t.u128; Type *type_uptr = &t.uptr; Type *type_uptrdiff = &t.uptrdiff; Type *type_usize = &t.usz; -Type *type_compstr = &t.str; Type *type_anyerr = &t.anyerr; Type *type_complist = &t.ctlist; Type *type_anyfail = &t.anyfail; @@ -146,8 +145,6 @@ const char *type_to_error_string(Type *type) if (!type->failable) return "void!"; asprintf(&buffer, "%s!", type_to_error_string(type->failable)); return buffer; - case TYPE_STRLIT: - return "string literal"; case TYPE_ARRAY: asprintf(&buffer, "%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len); return buffer; @@ -235,7 +232,6 @@ RETRY: case TYPE_ANYERR: case TYPE_ANY: return type->builtin.bytesize; - case TYPE_STRLIT: case TYPE_FUNC: case TYPE_POINTER: return t.iptr.canonical->builtin.bytesize; @@ -306,7 +302,6 @@ bool type_is_abi_aggregate(Type *type) case TYPE_POINTER: case TYPE_ENUM: case TYPE_FUNC: - case TYPE_STRLIT: case TYPE_VECTOR: case TYPE_ANYERR: case TYPE_ERRTYPE: @@ -447,7 +442,6 @@ AlignSize type_abi_alignment(Type *type) return type->builtin.abi_alignment; case TYPE_FUNC: case TYPE_POINTER: - case TYPE_STRLIT: case TYPE_TYPEID: return t.iptr.canonical->builtin.abi_alignment; case TYPE_ARRAY: @@ -724,8 +718,6 @@ Type *type_get_indexed_type(Type *type) case TYPE_INFERRED_ARRAY: case TYPE_VECTOR: return type->array.base; - case TYPE_STRLIT: - return type_char; case TYPE_DISTINCT: type = type->decl->distinct_decl.base_type; goto RETRY; @@ -925,7 +917,6 @@ static void type_append_name_to_scratch(Type *type) case TYPE_VECTOR: scratch_buffer_append(type->name); break; - case TYPE_STRLIT: case TYPE_UNTYPED_LIST: case TYPE_INFERRED_ARRAY: case TYPE_TYPEINFO: @@ -1017,7 +1008,6 @@ void type_setup(PlatformTarget *target) type_init_int("void", &t.u0, TYPE_VOID, BITS8); - type_init("string", &t.str, TYPE_STRLIT, target->width_pointer, target->align_pointer); type_create("typeinfo", &t.typeinfo, TYPE_TYPEINFO, 1, 1, 1); @@ -1092,7 +1082,6 @@ bool type_is_scalar(Type *type) case TYPE_BOOL: case ALL_INTS: case ALL_FLOATS: - case TYPE_STRLIT: case TYPE_TYPEID: case TYPE_POINTER: case TYPE_ENUM: @@ -1314,6 +1303,20 @@ static inline Type *type_find_max_ptr_type(Type *type, Type *other) } +Type *type_decay_array_pointer(Type *type) +{ + assert(type->type_kind == TYPE_POINTER); + Type *ptr = type->pointer; + switch (ptr->type_kind) + { + case TYPE_ARRAY: + return type_get_ptr(ptr->array.base->canonical); + case TYPE_VECTOR: + return type_get_ptr(ptr->vector.base->canonical); + default: + return type; + } +} Type *type_find_max_type(Type *type, Type *other) { if (type == type_anyfail) @@ -1361,6 +1364,28 @@ Type *type_find_max_type(Type *type, Type *other) if (other->type_kind == TYPE_DISTINCT && type_is_float(other->decl->distinct_decl.base_type)) return other; return type_find_max_num_type(type, other); case TYPE_POINTER: + if (type->pointer->type_kind == TYPE_ARRAY) + { + Type *array_base = type->pointer->array.base->canonical; + if (other->type_kind == TYPE_SUBARRAY && + array_base == other->array.base->canonical) + { + return other; + } + } + if (type->pointer->type_kind == TYPE_VECTOR) + { + Type *vector_base = type->pointer->vector.base->canonical; + if (other->type_kind == TYPE_SUBARRAY && vector_base == other->array.base->canonical) + { + return other; + } + } + // We need to decay the pointer + type = type_decay_array_pointer(type); + // And possibly the other pointer as well + if (other->type_kind == TYPE_POINTER) other = type_decay_array_pointer(other); + return type_find_max_ptr_type(type, other); case TYPE_ENUM: // IMPROVE: should there be implicit conversion between one enum and the other in @@ -1378,17 +1403,6 @@ Type *type_find_max_type(Type *type, Type *other) TODO case TYPE_TYPEDEF: UNREACHABLE - case TYPE_STRLIT: - if (other->type_kind == TYPE_DISTINCT) - { - // In this case we only react to the flattened type. - Type *flatten_other = type_flatten(other); - if (flatten_other->type_kind == TYPE_SUBARRAY && flatten_other->array.base->type_kind == TYPE_U8) return other; - if (flatten_other->type_kind == TYPE_POINTER && flatten_other->pointer->type_kind == TYPE_U8) return other; - } - if (other->type_kind == TYPE_SUBARRAY && other->array.base->type_kind == TYPE_U8) return other; - if (other->type_kind == TYPE_POINTER && other->pointer->type_kind == TYPE_U8) return other; - return NULL; case TYPE_DISTINCT: return NULL; case TYPE_ARRAY: diff --git a/test/test_suite/compile_time/ct_switch.c3t b/test/test_suite/compile_time/ct_switch.c3t index 62f9f5e3a..449a3d30b 100644 --- a/test/test_suite/compile_time/ct_switch.c3t +++ b/test/test_suite/compile_time/ct_switch.c3t @@ -49,17 +49,15 @@ fn void main() @.str.7 = private constant [14 x i8] c"donnowifprime\00", align 1 @.str.8 = private constant [4 x i8] c"%s\0A\00", align 1 @.str.9 = private constant [14 x i8] c"donnowifprime\00", align 1 - ; Function Attrs: nounwind declare void @printf(i8*, ...) #0 - ; Function Attrs: nounwind define void @main() #0 { entry: - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.3, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.7, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.8, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.9, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), [5 x i8]* bitcast ([6 x i8]* @.str.1 to [5 x i8]*)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.3 to [9 x i8]*)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.5 to [9 x i8]*)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.6, i32 0, i32 0), [13 x i8]* bitcast ([14 x i8]* @.str.7 to [13 x i8]*)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.8, i32 0, i32 0), [13 x i8]* bitcast ([14 x i8]* @.str.9 to [13 x i8]*)) ret void -} \ No newline at end of file +} diff --git a/test/test_suite/compile_time/ct_switch_type_check.c3t b/test/test_suite/compile_time/ct_switch_type_check.c3t index a12c2352b..e20f06348 100644 --- a/test/test_suite/compile_time/ct_switch_type_check.c3t +++ b/test/test_suite/compile_time/ct_switch_type_check.c3t @@ -37,8 +37,8 @@ declare void @printf(i8*, ...) #0 ; Function Attrs: nounwind define void @main() #0 { entry: - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.3, i32 0, i32 0)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), [3 x i8]* bitcast ([4 x i8]* @.str.1 to [3 x i8]*)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), [6 x i8]* bitcast ([7 x i8]* @.str.3 to [6 x i8]*)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.4, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.5 to [9 x i8]*)) ret void } \ No newline at end of file diff --git a/test/test_suite/compile_time_introspection/qnameof.c3t b/test/test_suite/compile_time_introspection/qnameof.c3t index 9126bcac9..58058569f 100644 --- a/test/test_suite/compile_time_introspection/qnameof.c3t +++ b/test/test_suite/compile_time_introspection/qnameof.c3t @@ -43,13 +43,13 @@ fn void main() define void @main() %help = alloca i32, align 4 store i32 0, i32* %help, align 4 - %0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0)) - %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.3, i32 0, i32 0)) - %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.5, i32 0, i32 0)) - %3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.7, i32 0, i32 0)) - %4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.8, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.9, i32 0, i32 0)) - %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.11, i32 0, i32 0)) - %6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.12, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.13, i32 0, i32 0)) - %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.14, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.15, i32 0, i32 0)) - %8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.16, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.17, i32 0, i32 0)) + %0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), [6 x i8]* bitcast ([7 x i8]* @.str.1 to [6 x i8]*)) + %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0), [17 x i8]* bitcast ([18 x i8]* @.str.3 to [17 x i8]*)) + %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), [15 x i8]* bitcast ([16 x i8]* @.str.5 to [15 x i8]*)) + %3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), [4 x i8]* bitcast ([5 x i8]* @.str.7 to [4 x i8]*)) + %4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.8, i32 0, i32 0), [12 x i8]* bitcast ([13 x i8]* @.str.9 to [12 x i8]*)) + %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i32 0, i32 0), [1 x i8]* bitcast ([2 x i8]* @.str.11 to [1 x i8]*)) + %6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.12, i32 0, i32 0), [4 x i8]* bitcast ([5 x i8]* @.str.13 to [4 x i8]*)) + %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.14, i32 0, i32 0), [15 x i8]* bitcast ([16 x i8]* @.str.15 to [15 x i8]*)) + %8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.16, i32 0, i32 0), [9 x i8]* bitcast ([10 x i8]* @.str.17 to [9 x i8]*)) ret void diff --git a/test/test_suite/strings/string_to_array.c3t b/test/test_suite/strings/string_to_array.c3t new file mode 100644 index 000000000..56f4ca522 --- /dev/null +++ b/test/test_suite/strings/string_to_array.c3t @@ -0,0 +1,24 @@ +// #target: x64-darwin +module foo; + +fn void main() +{ + char[2] x = "ab"; + char[*] y = "abc"; +} + +/* #expect: foo.ll + +@.str = private constant [3 x i8] c"ab\00", align 1 +@.str.1 = private constant [4 x i8] c"abc\00", align 1 + +define void @main() #0 { +entry: + %x = alloca [2 x i8], align 1 + %y = alloca [3 x i8], align 1 + %0 = bitcast [2 x i8]* %x to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 8 getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i32 2, i1 false) + %1 = bitcast [3 x i8]* %y to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %1, i8* align 8 getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i32 3, i1 false) + ret void +} diff --git a/test/test_suite/symbols/various.c3 b/test/test_suite/symbols/various.c3 index 6e4ba7ac6..d3a7679c5 100644 --- a/test/test_suite/symbols/various.c3 +++ b/test/test_suite/symbols/various.c3 @@ -125,7 +125,7 @@ fn void test16() fn void test17() { - int a = "test"; // #error: 'string literal' into 'int' + int a = "test"; // #error: 'char[4]*' into 'int' } fn void test18() diff --git a/test/test_suite/types/enum_errors.c3 b/test/test_suite/types/enum_errors.c3 index c701a3816..5c7b7bc5b 100644 --- a/test/test_suite/types/enum_errors.c3 +++ b/test/test_suite/types/enum_errors.c3 @@ -12,6 +12,6 @@ fn int foo() enum State { A = foo(), // #error: Expected a constant expression for enum - B = "hello", // #error: 'string literal' into 'int' + B = "hello", // #error: 'char[5]*' into 'int' C = true, // #error: 'bool' to 'int' }