diff --git a/releasenotes.md b/releasenotes.md index a764adb0c..67fc1f7ba 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -113,6 +113,9 @@ - Comparing a flexible array member to another type would hit an assert. #2830 - Underlying slice type not checked correctly in $defined #2829 - Checking for exhaustive cases is done even in if-chain switch if all is enum #2828 +- Constant shifting incorrectly doesn't flatten the underlying vector base #2825 +- String not set as attributes resolved breaking has_tagof #2824 +- Self referencing forward resolved const enum fails to be properly detected #2823 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index b042d6bf6..34480aa65 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1187,14 +1187,19 @@ static inline bool sema_expr_analyse_enum_constant(SemaContext *context, Expr *e Decl *enum_constant = decl_find_enum_constant(decl, name); if (!enum_constant) return false; - if (!sema_analyse_decl(context, decl)) return false; + if (!sema_analyse_decl(context, decl)) return expr_poison(expr), true; - ASSERT_SPAN(expr, enum_constant->resolve_status != RESOLVE_NOT_DONE); + if (enum_constant->resolve_status == RESOLVE_NOT_DONE) + { + SEMA_ERROR(expr, "Unable to properly resolve enum constant value, this can sometimes happen in recursive definitions."); + return expr_poison(expr), true; + } expr->type = decl->type; if (enum_constant->enum_constant.is_raw) { expr_replace(expr, copy_expr_single(enum_constant->enum_constant.value)); - return sema_analyse_expr_rvalue(context, expr); + if (!sema_analyse_expr_rvalue(context, expr)) expr_poison(expr); + return true; } expr->expr_kind = EXPR_CONST; expr->const_expr.const_kind = CONST_ENUM; @@ -5077,7 +5082,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp RETURN_SEMA_ERROR(expr, "'%s' has no enumeration value '%s'.", decl->name, name); return false; } - return true; + return expr_ok(expr); } break; case DECL_UNION: @@ -8304,7 +8309,7 @@ static bool sema_expr_check_shift_rhs(SemaContext *context, Expr *expr, Expr *le { // Make sure the value does not exceed the bitsize of // the left hand side. We ignore this check for lhs being a constant. - Type *base = type_vector_base(left_type_flat); + Type *base = type_flatten(type_vector_base(left_type_flat)); ASSERT_SPAN(expr, type_kind_is_any_integer(base->type_kind)); if (int_ucomp(right->const_expr.ixx, base->builtin.bitsize, BINARYOP_GE)) { diff --git a/src/compiler/types.c b/src/compiler/types.c index b1e9c3978..ffefc0959 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -1548,6 +1548,7 @@ void type_setup(PlatformTarget *target) type_wildcard_optional = type_get_optional(type_wildcard); Decl *string_decl = decl_new_with_type(symtab_preset("String", TOKEN_TYPE_IDENT), INVALID_SPAN, DECL_TYPEDEF); string_decl->unit = compiler.context.core_unit; + string_decl->resolved_attributes = true; string_decl->extname = string_decl->name; string_decl->is_substruct = true; string_decl->distinct = type_info_new_base(type_chars, INVALID_SPAN); diff --git a/test/test_suite/enumerations/const_enum_self_ref.c3 b/test/test_suite/enumerations/const_enum_self_ref.c3 new file mode 100644 index 000000000..140b263ad --- /dev/null +++ b/test/test_suite/enumerations/const_enum_self_ref.c3 @@ -0,0 +1,11 @@ +enum MyEnum : const +{ + VAL1 = VAL3, // #error: Unable to properly resolve enum constant value, this can sometimes happen in recursive definitions + VAL2 , + VAL3 +} + +fn int main() +{ + return 0; +} \ No newline at end of file diff --git a/test/test_suite/expressions/const_array_shift_typedef.c3 b/test/test_suite/expressions/const_array_shift_typedef.c3 new file mode 100644 index 000000000..6042a61c6 --- /dev/null +++ b/test/test_suite/expressions/const_array_shift_typedef.c3 @@ -0,0 +1,5 @@ +typedef Foo = int; + +Foo[<2>] f3 = (Foo[<2>]) 1 << 2; // #error: The expression must be a constant value + +fn int main() => 0; \ No newline at end of file diff --git a/test/test_suite/macros/string_tagof.c3t b/test/test_suite/macros/string_tagof.c3t new file mode 100644 index 000000000..86f51a0c8 --- /dev/null +++ b/test/test_suite/macros/string_tagof.c3t @@ -0,0 +1,6 @@ +fn int main() +{ + $if String.has_tagof(""): + $endif + return 0; +} \ No newline at end of file