From 2bbc6cbbca89825fb5484a8f6873ccbdffeee36c Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 21 Jun 2025 23:18:17 +0200 Subject: [PATCH] Further #2226 fixes. --- releasenotes.md | 1 + src/compiler/compiler_internal.h | 2 ++ src/compiler/diagnostics.c | 2 +- src/compiler/enums.h | 1 + src/compiler/sema_decls.c | 6 +++++- src/compiler/sema_expr.c | 9 ++++----- src/compiler/sema_internal.h | 5 +++-- src/compiler/sema_stmts.c | 1 + src/compiler/symtab.c | 1 + test/test_suite/functions/deprecation.c3 | 23 +++++++++++++++++++++++ 10 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 test/test_suite/functions/deprecation.c3 diff --git a/releasenotes.md b/releasenotes.md index 70ee6de0b..f589c18c1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -25,6 +25,7 @@ - Support distrinct types as the base type of bitstructs. #2218 - Add hash::sha512 module to stdlib. #2227 - Compile time type assignment (eg `$Foo = int`) is no longer an expression. +- Add `@allow_deprecated` attribute to functions to selectively allow deprecated declarations #2223 ### Fixes - `-2147483648`, MIN literals work correctly. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index aaf3f1344..2cb59ee24 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -630,6 +630,7 @@ typedef struct Decl_ bool attr_nopadding : 1; bool attr_compact : 1; bool resolved_attributes : 1; + bool allow_deprecated : 1; union { void *backend_ref; @@ -1695,6 +1696,7 @@ typedef struct bool ensures : 1; bool pure : 1; bool in_no_eval : 1; + bool ignore_deprecation : 1; SourceSpan in_if_resolution; Decl **opt_returns; union diff --git a/src/compiler/diagnostics.c b/src/compiler/diagnostics.c index 7c9b87e98..2a08a406f 100644 --- a/src/compiler/diagnostics.c +++ b/src/compiler/diagnostics.c @@ -221,7 +221,7 @@ void sema_warning_at(SourceSpan loc, const char *message, ...) { va_list list; va_start(list, message); - print_error_type_at(loc, str_vprintf(message, list), PRINT_TYPE_NOTE); + print_error_type_at(loc, str_vprintf(message, list), PRINT_TYPE_WARN); va_end(list); } diff --git a/src/compiler/enums.h b/src/compiler/enums.h index cbef99ebd..12ed1b7d0 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -265,6 +265,7 @@ typedef enum FLAG_ATTR typedef enum { ATTRIBUTE_ALIGN, + ATTRIBUTE_ALLOW_DEPRECATED, ATTRIBUTE_BENCHMARK, ATTRIBUTE_BIGENDIAN, ATTRIBUTE_BUILTIN, diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 8485f8de2..a93458953 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -2940,6 +2940,7 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ // NOLINTBEGIN(*.EnumCastOutOfRange) static AttributeDomain attribute_domain[NUMBER_OF_ATTRIBUTES] = { [ATTRIBUTE_ALIGN] = ATTR_FUNC | ATTR_CONST | ATTR_LOCAL | ATTR_GLOBAL | ATTR_BITSTRUCT | ATTR_STRUCT | ATTR_UNION | ATTR_MEMBER, // NOLINT + [ATTRIBUTE_ALLOW_DEPRECATED] = ATTR_FUNC, [ATTRIBUTE_BENCHMARK] = ATTR_FUNC, [ATTRIBUTE_BIGENDIAN] = ATTR_BITSTRUCT, [ATTRIBUTE_BUILTIN] = ATTR_MACRO | ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST, @@ -3031,6 +3032,9 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ attr_data->deprecated = expr->const_expr.bytes.ptr; } return true; + case ATTRIBUTE_ALLOW_DEPRECATED: + decl->allow_deprecated = true; + return true; case ATTRIBUTE_OPTIONAL: decl->func_decl.attr_optional = true; return true; @@ -4639,7 +4643,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) if (type_is_user_defined(type) && type->decl) { if (!sema_analyse_decl(context, type->decl)) return false; - sema_display_deprecated_warning_on_use(type->decl, type_info->span); + sema_display_deprecated_warning_on_use(context, type->decl, type_info->span); } if (is_static && context->call_env.pure) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 214df89a0..119dfa646 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1152,7 +1152,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, { if (!sema_analyse_decl(context, decl)) return decl_poison(decl); } - sema_display_deprecated_warning_on_use(decl, expr->span); + sema_display_deprecated_warning_on_use(context, decl, expr->span); unit_register_external_symbol(context, decl); decl = decl_flatten(decl); @@ -1168,8 +1168,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, if (!sema_analyse_expr(context, copy)) return false; if (!expr_is_runtime_const(copy)) { - SEMA_ERROR(expr, "Constant value did not evaluate to a constant."); - return false; + RETURN_SEMA_ERROR(expr, "Constant value did not evaluate to a constant."); } expr_replace(expr, copy); return true; @@ -2387,7 +2386,7 @@ static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, return false; } - sema_display_deprecated_warning_on_use(decl, expr->span); + sema_display_deprecated_warning_on_use(context, decl, expr->span); // Tag dynamic dispatch. if (struct_var && decl->func_decl.attr_interface_method) expr->call_expr.is_dynamic_dispatch = true; @@ -2461,7 +2460,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s "possibly due non-terminating macro recursion."); } - sema_display_deprecated_warning_on_use(decl, call_expr->span); + sema_display_deprecated_warning_on_use(context, decl, call_expr->span); copy_begin(); Decl **params = copy_decl_list_macro(decl->func_decl.signature.params); diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 094211ced..d369ca737 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -127,7 +127,7 @@ bool sema_parameterized_type_is_found(SemaContext *context, Path *decl_path, con Type *sema_resolve_type_get_func(Signature *signature, CallABI abi); INLINE bool sema_set_abi_alignment(SemaContext *context, Type *type, AlignSize *result); INLINE bool sema_set_alloca_alignment(SemaContext *context, Type *type, AlignSize *result); -INLINE void sema_display_deprecated_warning_on_use(Decl *decl, SourceSpan span); +INLINE void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *decl, SourceSpan span); bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr *left, Expr *right, bool *failed_ref); INLINE bool sema_check_left_right_const(SemaContext *context, Expr *left, Expr *right) @@ -165,10 +165,11 @@ INLINE Attr* attr_find_kind(Attr **attrs, AttributeType attr_type) return NULL; } -INLINE void sema_display_deprecated_warning_on_use(Decl *decl, SourceSpan span) +INLINE void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *decl, SourceSpan span) { ASSERT(decl->resolve_status == RESOLVE_DONE); if (!decl->resolved_attributes || !decl->attrs_resolved || !decl->attrs_resolved->deprecated) return; + if (context->call_env.ignore_deprecation) return; const char *msg = decl->attrs_resolved->deprecated; // Prevent multiple reports diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 101a2f2dd..e9f4f6941 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -3255,6 +3255,7 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func) .current_function = func, .kind = CALL_ENV_FUNCTION, .pure = func->func_decl.signature.attrs.is_pure, + .ignore_deprecation = func->allow_deprecated || (func->resolved_attributes && func->attrs_resolved && func->attrs_resolved->deprecated && func->resolved_attributes && func->attrs_resolved->deprecated) }; context->rtype = prototype->rtype; context->macro_call_depth = 0; diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 71c0c91e9..9603a0e06 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -328,6 +328,7 @@ void symtab_init(uint32_t capacity) kw_at_require = KW_DEF("@require"); kw_at_return = KW_DEF("@return"); attribute_list[ATTRIBUTE_ALIGN] = KW_DEF("@align"); + attribute_list[ATTRIBUTE_ALLOW_DEPRECATED] = KW_DEF("@allow_deprecated"); attribute_list[ATTRIBUTE_BENCHMARK] = KW_DEF("@benchmark"); attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("@bigendian"); attribute_list[ATTRIBUTE_BUILTIN] = KW_DEF("@builtin"); diff --git a/test/test_suite/functions/deprecation.c3 b/test/test_suite/functions/deprecation.c3 new file mode 100644 index 000000000..f94f2df8e --- /dev/null +++ b/test/test_suite/functions/deprecation.c3 @@ -0,0 +1,23 @@ + +fn int foo() @deprecated +{ + if (false) foo(); + return 1; +} + +fn int main() @allow_deprecated +{ + foo(); + return 0; +} + +fn int foo2() @deprecated +{ + return 1; +} + +fn int main2() +{ + foo2(); // #warning: 'foo2' is deprecated + return 0; +} \ No newline at end of file