diff --git a/lib/std/time/time.c3 b/lib/std/time/time.c3 index 1aa5c12f9..20a22baa3 100644 --- a/lib/std/time/time.c3 +++ b/lib/std/time/time.c3 @@ -78,7 +78,7 @@ enum Month : char (String name, String abbrev, int days, bool leap) fn Time now() { - $if $defined(native_timestamp): + $if $defined(os::native_timestamp): return os::native_timestamp(); $else return (Time)0; diff --git a/releasenotes.md b/releasenotes.md index af958b537..0693545a4 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -17,6 +17,8 @@ - Compiler crash when concatenating structs and arrays to an untyped list. - Strings assigned to longer arrays would crash codegen, e.g. `char[10] x = "abcd`. - Typedefs and structs with inline types supporting lengthof would not work with lengthof #2641. +- `$defined(foo())` now correctly errors if `foo()` would require a path. +- `@if($defined((char*){}.foo()))` does not error if `foo` is missing. ### 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 6315fd38f..985c81059 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -50,7 +50,7 @@ static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, bool throw_error); static inline bool sema_expr_analyse_binary(SemaContext *context, Type *infer_type, Expr *expr, bool *failed_ref); static inline bool sema_expr_resolve_ct_eval(SemaContext *context, Expr *expr); -static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr); +static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr, bool *failed_ref); static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_ternary(SemaContext *context, Type *infer_type, Expr *expr); @@ -1197,7 +1197,7 @@ static inline bool sema_identifier_find_possible_inferred(SemaContext *context, } } -static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr) +static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr, bool *failed_ref) { ASSERT(expr); ASSERT_SPAN(expr, expr->unresolved_ident_expr.ident); @@ -1231,6 +1231,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, // Rerun if we can't do inference. if (!decl) { + if (failed_ref) return *failed_ref = true, false; if (!expr->unresolved_ident_expr.path && expr->unresolved_ident_expr.is_const && (!to || to->canonical->type_kind != TYPE_ENUM)) { CompilationUnit **units = context->unit->module->units; @@ -1256,6 +1257,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, ASSERT_SPAN(expr, !decl); return false; } + if (failed_ref && decl_is_defaulted_var(decl)) return *failed_ref = true, false; if (decl_needs_prefix(decl)) { @@ -3727,10 +3729,28 @@ static inline bool sema_call_analyse_member_get(SemaContext *context, Expr *expr expr->type = decl->type; return true; } + +static inline bool sema_expr_analyse_call_expr_dispatch(SemaContext *context, Expr *expr, bool *no_match_ref) +{ + switch (expr->expr_kind) + { + case EXPR_UNRESOLVED_IDENTIFIER: + return sema_expr_analyse_identifier(context, NULL, expr, no_match_ref); + case EXPR_ACCESS_UNRESOLVED: + return sema_expr_analyse_access(context, expr, no_match_ref); + default: + return sema_analyse_expr_dispatch(context, expr); + } +} +static inline bool sema_expr_analyse_call_expr(SemaContext *context, Expr *expr, bool *no_match_ref) +{ + RESOLVE(expr, sema_expr_analyse_call_expr_dispatch(context, expr, no_match_ref)); +} + static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool *no_match_ref) { Expr *func_expr = exprptr(expr->call_expr.function); - if (!sema_analyse_expr(context, func_expr)) return false; + if (!sema_expr_analyse_call_expr(context, func_expr, no_match_ref)) return false; bool optional = func_expr->type && IS_OPTIONAL(func_expr); Decl *decl; Expr *struct_var = NULL; @@ -10966,12 +10986,12 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr } break; case EXPR_UNRESOLVED_IDENTIFIER: - { - Decl *decl = sema_find_path_symbol(active_context, main_expr->unresolved_ident_expr.ident, main_expr->unresolved_ident_expr.path); - if (!decl_ok(decl)) goto FAIL; - success = decl != NULL && !decl_is_defaulted_var(decl); + if (!sema_expr_analyse_identifier(active_context, NULL, main_expr, &failed)) + { + if (!failed) goto FAIL; + success = false; + } break; - } case EXPR_HASH_IDENT: { if (unroll_hash) @@ -11750,7 +11770,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) case EXPR_IDENTIFIER: UNREACHABLE case EXPR_UNRESOLVED_IDENTIFIER: - return sema_expr_analyse_identifier(context, NULL, expr); + return sema_expr_analyse_identifier(context, NULL, expr, NULL); case EXPR_CALL: return sema_expr_analyse_call(context, expr, NULL); case EXPR_SUBSCRIPT: @@ -12397,7 +12417,7 @@ RETRY: if (!sema_expr_analyse_initializer_list(context, to, expr, no_match_ref)) return expr_poison(expr); break; case EXPR_UNRESOLVED_IDENTIFIER: - if (!sema_expr_analyse_identifier(context, to, expr)) return expr_poison(expr); + if (!sema_expr_analyse_identifier(context, to, expr, NULL)) return expr_poison(expr); break; case EXPR_LAMBDA: if (!sema_expr_analyse_lambda(context, to, expr)) return expr_poison(expr);