diff --git a/src/compiler/c_codegen.c b/src/compiler/c_codegen.c index 8af3f5e66..1d21e0e81 100644 --- a/src/compiler/c_codegen.c +++ b/src/compiler/c_codegen.c @@ -407,6 +407,7 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr) case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_RVALUE: + case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_RECAST: case EXPR_ADDR_CONVERSION: case EXPR_EXT_TRUNC: @@ -437,8 +438,9 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr) case EXPR_CALL: break; case EXPR_CAST: + case EXPR_CATCH_UNRESOLVED: UNREACHABLE - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: break; case EXPR_COMPILER_CONST: break; diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 258bf95f9..fad2bf77b 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -863,21 +863,10 @@ typedef struct typedef struct { - union - { - struct - { - Path *path; - const char *ident; - bool is_const; - }; - struct - { - Decl *decl; - bool was_ref; - }; - }; -} ExprIdentifier; + Path *path; + const char *ident; + bool is_const; +} ExprUnresolvedIdentifier; typedef struct { @@ -1025,21 +1014,16 @@ typedef struct typedef struct { - union - { - struct - { - Expr *variable; - TypeInfo *type; - }; - struct - { - Decl *decl; - Expr *lhs; - }; - }; + Decl *decl; Expr **exprs; -} ExprCatchUnwrap; +} ExprCatch; + +typedef struct +{ + Expr *variable; + TypeInfo *type; + Expr **exprs; +} ExprUnresolvedCatch; typedef struct { @@ -1153,7 +1137,8 @@ struct Expr_ ExprBuiltin builtin_expr; // 16 ExprCall call_expr; // 40 ExprCast cast_expr; // 12 - ExprCatchUnwrap catch_unwrap_expr; // 24 + ExprUnresolvedCatch unresolved_catch_expr; // 24 + ExprCatch catch_expr; // 24 Expr** cond_expr; // 8 ExprConst const_expr; // 32 ExprCtArg ct_arg_expr; @@ -1178,7 +1163,8 @@ struct Expr_ ExprGenericIdent generic_ident_expr; ExprDefaultArg default_arg_expr; ExprIdentifierRaw hash_ident_expr; // 24 - ExprIdentifier identifier_expr; // 24 + ExprUnresolvedIdentifier unresolved_ident_expr;// 24 + Decl *ident_expr; // 8 Expr** initializer_list; // 8 Expr *inner_expr; // 8 ExprMakeAny make_any_expr; @@ -3412,7 +3398,8 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc) case EXPR_BITASSIGN: case EXPR_BUILTIN_ACCESS: case EXPR_CALL: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH_UNRESOLVED: + case EXPR_CATCH: case EXPR_COMPILER_CONST: case EXPR_COMPOUND_LITERAL: case EXPR_COND: @@ -3463,6 +3450,7 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc) case EXPR_TYPEID_INFO: case EXPR_TYPEINFO: case EXPR_UNARY: + case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_ANYSWITCH: case EXPR_VASPLAT: case EXPR_MACRO_BODY: @@ -3494,8 +3482,9 @@ INLINE bool exprid_is_simple(ExprId expr_id, bool to_float) { return expr_is_sim INLINE void expr_resolve_ident(Expr *expr, Decl *decl) { - expr->identifier_expr = (ExprIdentifier) { .decl = decl }; - expr->type = decl->type; + expr->expr_kind = EXPR_IDENTIFIER; + expr->ident_expr = decl; + expr->type = decl->type ? decl->type : type_void; expr->resolve_status = RESOLVE_DONE; } diff --git a/src/compiler/copying.c b/src/compiler/copying.c index e5f729dac..4c219f701 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -392,25 +392,19 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) case EXPR_TRY_UNWRAP_CHAIN: MACRO_COPY_EXPR_LIST(expr->try_unwrap_chain_expr); return expr; - case EXPR_CATCH_UNWRAP: - if (expr->resolve_status == RESOLVE_DONE) - { - MACRO_COPY_DECL(expr->catch_unwrap_expr.decl); - MACRO_COPY_EXPR(expr->catch_unwrap_expr.lhs); - } - else - { - MACRO_COPY_TYPE(expr->catch_unwrap_expr.type); - MACRO_COPY_EXPR(expr->catch_unwrap_expr.variable); - } - MACRO_COPY_EXPR_LIST(expr->catch_unwrap_expr.exprs); + case EXPR_CATCH_UNRESOLVED: + MACRO_COPY_TYPE(expr->unresolved_catch_expr.type); + MACRO_COPY_EXPR(expr->unresolved_catch_expr.variable); + MACRO_COPY_EXPR_LIST(expr->unresolved_catch_expr.exprs); + return expr; + case EXPR_CATCH: + MACRO_COPY_DECL(expr->catch_expr.decl); + MACRO_COPY_EXPR_LIST(expr->catch_expr.exprs); return expr; case EXPR_IDENTIFIER: - if (expr->resolve_status == RESOLVE_DONE) - { - fixup_decl(c, &expr->identifier_expr.decl); - } + fixup_decl(c, &expr->ident_expr); return expr; + case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_CT_IDENT: case EXPR_HASH_IDENT: ASSERT0(expr->resolve_status != RESOLVE_DONE); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index b40df380b..57a17c965 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -725,7 +725,8 @@ typedef enum EXPR_BUILTIN_ACCESS, EXPR_CALL, EXPR_CAST, - EXPR_CATCH_UNWRAP, + EXPR_CATCH_UNRESOLVED, + EXPR_CATCH, EXPR_COMPILER_CONST, EXPR_COMPOUND_LITERAL, EXPR_COND, @@ -802,6 +803,7 @@ typedef enum EXPR_TYPEID, EXPR_TYPEID_INFO, EXPR_TYPEINFO, + EXPR_UNRESOLVED_IDENTIFIER, EXPR_UNARY, EXPR_VASPLAT, EXPR_VECTOR_FROM_ARRAY, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index c31eb7438..f8b942dd9 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -23,7 +23,8 @@ const char *expr_kind_to_string(ExprKind kind) case EXPR_BUILTIN_ACCESS: return "builtin_access"; case EXPR_CALL: return "call"; case EXPR_CAST: return "cast"; - case EXPR_CATCH_UNWRAP: return "catch_unwrap"; + case EXPR_CATCH: return "catch_unwrap"; + case EXPR_CATCH_UNRESOLVED: return "catch_unresolved"; case EXPR_COMPILER_CONST: return "compiler_const"; case EXPR_COMPOUND_LITERAL: return "compound_litera"; case EXPR_COND: return "cond"; @@ -55,6 +56,7 @@ const char *expr_kind_to_string(ExprKind kind) case EXPR_GENERIC_IDENT: return "generic_ident"; case EXPR_HASH_IDENT: return "hash_ident"; case EXPR_IDENTIFIER: return "identifier"; + case EXPR_UNRESOLVED_IDENTIFIER: return "unresolved_identifier"; case EXPR_INITIALIZER_LIST: return "initializer_list"; case EXPR_INT_TO_FLOAT: return "int_to_float"; case EXPR_INT_TO_PTR: return "int_to_ptr"; @@ -178,7 +180,7 @@ bool expr_is_zero(Expr *expr) bool expr_is_unwrapped_ident(Expr *expr) { if (expr->expr_kind != EXPR_IDENTIFIER) return false; - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) return false; return decl->var.kind == VARDECL_UNWRAPPED && IS_OPTIONAL(decl->var.alias); } @@ -188,11 +190,13 @@ bool expr_may_addr(Expr *expr) if (IS_OPTIONAL(expr)) return false; switch (expr->expr_kind) { + case EXPR_UNRESOLVED_IDENTIFIER: + UNREACHABLE case EXPR_OTHER_CONTEXT: return expr_may_addr(expr->expr_other_context.inner); case EXPR_IDENTIFIER: { - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) return false; decl = decl_raw(decl); switch (decl->var.kind) @@ -254,7 +258,8 @@ bool expr_may_addr(Expr *expr) case EXPR_CALL: case EXPR_CAST: case EXPR_MAKE_ANY: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: + case EXPR_CATCH_UNRESOLVED: case EXPR_COMPOUND_LITERAL: case EXPR_COND: case EXPR_CONST: @@ -337,7 +342,8 @@ bool expr_is_runtime_const(Expr *expr) case EXPR_EXPR_BLOCK: case EXPR_DECL: case EXPR_CALL: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: + case EXPR_CATCH_UNRESOLVED: case EXPR_MACRO_BODY_EXPANSION: case EXPR_TRY_UNWRAP: case EXPR_TRY_UNWRAP_CHAIN: @@ -354,6 +360,7 @@ bool expr_is_runtime_const(Expr *expr) case EXPR_INT_TO_FLOAT: case EXPR_FLOAT_TO_INT: case EXPR_SLICE_LEN: + case EXPR_UNRESOLVED_IDENTIFIER: return false; case EXPR_VECTOR_FROM_ARRAY: case EXPR_ANYFAULT_TO_FAULT: @@ -405,7 +412,7 @@ bool expr_is_runtime_const(Expr *expr) goto RETRY; case EXPR_IDENTIFIER: { - Decl *ident = expr->identifier_expr.decl; + Decl *ident = expr->ident_expr; if (ident->decl_kind != DECL_VAR) return true; switch (ident->var.kind) { @@ -449,7 +456,7 @@ bool expr_is_runtime_const(Expr *expr) expr = exprptr(expr->subscript_expr.expr); if (expr->expr_kind == EXPR_IDENTIFIER) { - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind == DECL_VAR) { switch (decl->var.kind) @@ -542,10 +549,12 @@ static inline bool expr_unary_addr_is_constant_eval(Expr *expr) case EXPR_DESIGNATED_INITIALIZER_LIST: // We can't create temporaries as const locally or making them into compile time constants. return expr_is_runtime_const(inner); + case EXPR_UNRESOLVED_IDENTIFIER: + UNREACHABLE case EXPR_IDENTIFIER: { // The address of an identifier is side effect free. - Decl *decl = inner->identifier_expr.decl; + Decl *decl = inner->ident_expr; if (decl->decl_kind == DECL_FUNC) return true; if (decl->decl_kind != DECL_VAR) return false; switch (decl->var.kind) @@ -794,6 +803,7 @@ bool expr_is_pure(Expr *expr) case EXPR_CT_IDENT: case EXPR_EMBED: case EXPR_IDENTIFIER: + case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_LAMBDA: case EXPR_MACRO_BODY: case EXPR_NOP: @@ -841,7 +851,8 @@ bool expr_is_pure(Expr *expr) UNREACHABLE case EXPR_MACRO_BODY_EXPANSION: case EXPR_CALL: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: + case EXPR_CATCH_UNRESOLVED: case EXPR_COMPOUND_LITERAL: case EXPR_COND: case EXPR_DESIGNATOR: @@ -1070,8 +1081,8 @@ Expr *expr_variable(Decl *decl) expr_resolve_ident(expr, decl); return expr; } - Expr *expr = expr_new(EXPR_IDENTIFIER, decl->span); - expr->identifier_expr.ident = decl->name; + Expr *expr = expr_new(EXPR_UNRESOLVED_IDENTIFIER, decl->span); + expr->unresolved_ident_expr = (ExprUnresolvedIdentifier) { .ident = decl->name }; expr->resolve_status = RESOLVE_NOT_DONE; return expr; } diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index e822ae464..2a925455d 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -548,7 +548,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) // Fold "source" of the init. while (init_expr && init_expr->expr_kind == EXPR_IDENTIFIER) { - Decl *inner_decl = decl_flatten(init_expr->identifier_expr.decl); + Decl *inner_decl = decl_flatten(init_expr->ident_expr); if (inner_decl->decl_kind != DECL_VAR) break; if (inner_decl->var.kind != VARDECL_CONST) break; init_expr = inner_decl->var.init_expr; diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index cdc88f528..9d2024f2e 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -4475,7 +4475,7 @@ static void llvm_emit_binary_expr(GenContext *c, BEValue *be_value, Expr *expr) // If the LHS is an identifier, then we're assigning the optional value to that. if (left->expr_kind == EXPR_IDENTIFIER) { - optional_ref = decl_optional_ref(left->identifier_expr.decl); + optional_ref = decl_optional_ref(left->ident_expr); be_value->kind = BE_ADDRESS; } @@ -6348,14 +6348,10 @@ static inline void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *exp void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr) { BEValue addr; - if (expr->catch_unwrap_expr.lhs) + if (expr->catch_expr.decl) { - llvm_emit_expr(c, &addr, expr->catch_unwrap_expr.lhs); - } - else if (expr->catch_unwrap_expr.decl) - { - llvm_emit_local_decl(c, expr->catch_unwrap_expr.decl, &addr); - llvm_value_set_decl_address(c, &addr, expr->catch_unwrap_expr.decl); + llvm_emit_local_decl(c, expr->catch_expr.decl, &addr); + llvm_value_set_decl_address(c, &addr, expr->catch_expr.decl); } else { @@ -6367,7 +6363,7 @@ void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr) PUSH_CATCH_VAR_BLOCK(addr.value, catch_block); - FOREACH(Expr *, e, expr->catch_unwrap_expr.exprs) + FOREACH(Expr *, e, expr->catch_expr.exprs) { BEValue val; LLVMBasicBlockRef block = llvm_basic_block_new(c, "testblock"); @@ -7028,6 +7024,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_COMPOUND_LITERAL: case EXPR_OPERATOR_CHARS: case EXPR_CAST: + case EXPR_CATCH_UNRESOLVED: UNREACHABLE case EXPR_VECTOR_TO_ARRAY: llvm_emit_vector_to_array(c, value, expr); @@ -7149,7 +7146,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_TRY_UNWRAP: llvm_emit_try_unwrap(c, value, expr); return; - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: llvm_emit_catch_unwrap(c, value, expr); return; case EXPR_TYPEID_INFO: @@ -7211,11 +7208,12 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) llvm_emit_rethrow_expr(c, value, expr); return; case EXPR_TYPEID: + case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_SUBSCRIPT_ASSIGN: // These are folded in the semantic analysis step. UNREACHABLE case EXPR_IDENTIFIER: - llvm_value_set_decl(c, value, expr->identifier_expr.decl); + llvm_value_set_decl(c, value, expr->ident_expr); return; case EXPR_SUBSCRIPT: llvm_emit_subscript(c, value, expr); diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 0c19d6356..a53e9d006 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -183,7 +183,7 @@ static inline Expr *parse_try_chain_expr(ParseContext *c) */ static inline Expr *parse_catch_unwrap(ParseContext *c) { - Expr *expr = expr_new(EXPR_CATCH_UNWRAP, c->span); + Expr *expr = expr_new(EXPR_CATCH_UNRESOLVED, c->span); advance_and_verify(c, TOKEN_CATCH); Expr **exprs = NULL; @@ -201,7 +201,7 @@ static inline Expr *parse_catch_unwrap(ParseContext *c) vec_add(exprs, sub_expr); } while (try_consume(c, TOKEN_COMMA)); // We're done. - expr->catch_unwrap_expr.exprs = exprs; + expr->unresolved_catch_expr.exprs = exprs; return expr; } @@ -209,28 +209,28 @@ static inline Expr *parse_catch_unwrap(ParseContext *c) if (sub_expr->expr_kind == EXPR_TYPEINFO) { // Assign the type - expr->catch_unwrap_expr.type = sub_expr->type_expr; + expr->unresolved_catch_expr.type = sub_expr->type_expr; // Assign the variable - ASSIGN_EXPR_OR_RET(expr->catch_unwrap_expr.variable, parse_try_chain_expr(c), poisoned_expr); + ASSIGN_EXPR_OR_RET(expr->unresolved_catch_expr.variable, parse_try_chain_expr(c), poisoned_expr); } else { // Here we assume it's either "f" or an expression. - expr->catch_unwrap_expr.type = NULL; - expr->catch_unwrap_expr.variable = sub_expr; + expr->unresolved_catch_expr.type = NULL; + expr->unresolved_catch_expr.variable = sub_expr; } // If we don't have an '=', we check whether if (!try_consume(c, TOKEN_EQ)) { // If we had "anyfault f", then we MUST have '=' - if (expr->catch_unwrap_expr.type) + if (expr->unresolved_catch_expr.type) { PRINT_ERROR_HERE("Expected a '=' here."); return poisoned_expr; } // We just have `catch foo`, so we add the "variable" as an expression - vec_add(expr->catch_unwrap_expr.exprs, expr->catch_unwrap_expr.variable); - expr->catch_unwrap_expr.variable = NULL; + vec_add(expr->unresolved_catch_expr.exprs, expr->unresolved_catch_expr.variable); + expr->unresolved_catch_expr.variable = NULL; RANGE_EXTEND_PREV(expr); return expr; } @@ -240,7 +240,7 @@ static inline Expr *parse_catch_unwrap(ParseContext *c) ASSIGN_EXPR_OR_RET(sub_expr, parse_try_chain_expr(c), poisoned_expr); vec_add(exprs, sub_expr); } while (try_consume(c, TOKEN_COMMA)); - expr->catch_unwrap_expr.exprs = exprs; + expr->unresolved_catch_expr.exprs = exprs; RANGE_EXTEND_PREV(expr); return expr; } @@ -262,7 +262,7 @@ static inline Expr *parse_try_unwrap(ParseContext *c) { expr->try_unwrap_expr.variable = lhs; } - if (lhs->expr_kind == EXPR_TYPEINFO && expr->try_unwrap_expr.variable->expr_kind != EXPR_IDENTIFIER) + if (lhs->expr_kind == EXPR_TYPEINFO && expr->try_unwrap_expr.variable->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) { RETURN_PRINT_ERROR_AT(poisoned_expr, expr->try_unwrap_expr.variable, "A new variable was expected."); } @@ -1182,8 +1182,8 @@ static Expr *parse_ct_sizeof(ParseContext *c, Expr *left) type_info->unresolved_type_expr = inner; typeof_expr->type_expr = type_info; access->access_expr.parent = typeof_expr; - Expr *ident = expr_new(EXPR_IDENTIFIER, c->span); - ident->identifier_expr.ident = type_property_list[TYPE_PROPERTY_SIZEOF]; + Expr *ident = expr_new(EXPR_UNRESOLVED_IDENTIFIER, c->span); + ident->unresolved_ident_expr.ident = type_property_list[TYPE_PROPERTY_SIZEOF]; access->access_expr.child = ident; RANGE_EXTEND_PREV(access); return access; @@ -1330,9 +1330,9 @@ static Expr *parse_identifier(ParseContext *c, Expr *left) advance(c); return expr; } - Expr *expr = EXPR_NEW_TOKEN(EXPR_IDENTIFIER); - expr->identifier_expr.ident = symstr(c); - expr->identifier_expr.is_const = tok_is(c, TOKEN_CONST_IDENT); + Expr *expr = EXPR_NEW_TOKEN(EXPR_UNRESOLVED_IDENTIFIER); + expr->unresolved_ident_expr.ident = symstr(c); + expr->unresolved_ident_expr.is_const = tok_is(c, TOKEN_CONST_IDENT); advance(c); return expr; } @@ -1351,7 +1351,7 @@ static Expr *parse_identifier_starting_expression(ParseContext *c, Expr *left) case TOKEN_AT_IDENT: { Expr *expr = parse_identifier(c, NULL); - expr->identifier_expr.path = path; + expr->unresolved_ident_expr.path = path; if (path) { expr->span = extend_span_with_token(path->span, expr->span); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 9ad9ed0f3..03f732c34 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1952,8 +1952,8 @@ static inline Decl *parse_def_type(ParseContext *c) case EXPR_TYPEINFO: type_info = expr->type_expr; break; - case EXPR_IDENTIFIER: - if (expr->identifier_expr.is_const) + case EXPR_UNRESOLVED_IDENTIFIER: + if (expr->unresolved_ident_expr.is_const) { print_error_at(decl->span, "A constant may not have a type name alias, it must have an all caps name."); } @@ -2350,7 +2350,7 @@ static inline Decl *parse_enum_declaration(ParseContext *c) if (try_consume(c, TOKEN_RBRACE)) break; ASSIGN_EXPR_OR_RET(Expr *arg, parse_expr(c), poisoned_decl); vec_add(args, arg); - if (tok_is(c, TOKEN_COLON) && arg->expr_kind == EXPR_IDENTIFIER) + if (tok_is(c, TOKEN_COLON) && arg->expr_kind == EXPR_UNRESOLVED_IDENTIFIER) { print_error_at(extend_span_with_token(arg->span, c->span), "This looks like a designated initializer, but that style of declaration " diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index ea5c27f32..5a26e4620 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -19,7 +19,7 @@ static Ast *parse_decl_stmt_after_type(ParseContext *c, TypeInfo *type) switch (c->tok) { case TOKEN_LBRACE: - if (decl->var.init_expr && decl->var.init_expr->expr_kind == EXPR_IDENTIFIER) + if (decl->var.init_expr && decl->var.init_expr->expr_kind == EXPR_UNRESOLVED_IDENTIFIER) { print_error_at(decl->var.init_expr->span, "An identifier would not usually be followed by a '{'. Did you intend write the name of a type here?"); @@ -982,7 +982,7 @@ static inline Ast *parse_decl_or_expr_stmt(ParseContext *c) ast->span = expr->span; ast->ast_kind = AST_EXPR_STMT; ast->expr_stmt = expr; - if (tok_is(c, TOKEN_IDENT) && expr->expr_kind == EXPR_IDENTIFIER) + if (tok_is(c, TOKEN_IDENT) && expr->expr_kind == EXPR_UNRESOLVED_IDENTIFIER) { RETURN_PRINT_ERROR_AT(poisoned_ast, expr, "Expected a type here."); } diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 350bedc44..b2cb8b598 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -287,16 +287,6 @@ static bool cast_if_valid(SemaContext *context, Expr *expr, Type *to_type, bool if (from_type == to_type) return true; - if (to_type->canonical->type_kind == TYPE_POINTER && from_type->canonical->type_kind != TYPE_POINTER - && to_type->canonical->pointer == from_type->canonical && expr->expr_kind == EXPR_IDENTIFIER - && expr->identifier_expr.was_ref) - { - if (is_silent) return false; - RETURN_SEMA_ERROR(expr, "A macro ref parameter is a dereferenced pointer ('*&foo'). You can prefix it" - " with '&' to pass it as a pointer."); - } - - bool is_void_silence = type_is_void(to_type) && is_explicit; bool add_optional = type_is_optional(to_type) || type_is_optional(from_type); from_type = type_no_optional(from_type); @@ -1231,7 +1221,7 @@ static bool rule_to_distinct(CastContext *cc, bool is_explicit, bool is_silent) if (!is_const && from_type->type_kind == TYPE_FUNC_PTR && expr->expr_kind == EXPR_UNARY && expr->unary_expr.operator == UNARYOP_ADDR && expr->unary_expr.expr->expr_kind == EXPR_IDENTIFIER - && expr->unary_expr.expr->identifier_expr.decl->decl_kind == DECL_FUNC) + && expr->unary_expr.expr->ident_expr->decl_kind == DECL_FUNC) { is_const = true; } diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 08e0f6212..e9e50fc3e 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -2663,14 +2663,14 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ } switch (expr->expr_kind) { - case EXPR_IDENTIFIER: - if (expr->identifier_expr.path) goto FAILED_OP_TYPE; - if (expr->identifier_expr.ident == kw_construct) + case EXPR_UNRESOLVED_IDENTIFIER: + if (expr->unresolved_ident_expr.path) goto FAILED_OP_TYPE; + if (expr->unresolved_ident_expr.ident == kw_construct) { decl->operator = OVERLOAD_CONSTRUCT; break; } - if (expr->identifier_expr.ident != kw_len) goto FAILED_OP_TYPE; + if (expr->unresolved_ident_expr.ident != kw_len) goto FAILED_OP_TYPE; decl->operator = OVERLOAD_LEN; break; case EXPR_OPERATOR_CHARS: @@ -4613,7 +4613,7 @@ static inline bool sema_analyse_define(SemaContext *context, Decl *decl, bool *e { RETURN_SEMA_ERROR(expr, "A global variable or function name was expected here."); } - Decl *symbol = expr->identifier_expr.decl; + Decl *symbol = expr->ident_expr; if (!sema_analyse_decl(context, symbol)) return false; bool should_be_const = char_is_upper(decl->name[0]); if (should_be_const) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index abf9b7d3f..a8cc0bf1c 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -306,7 +306,7 @@ Expr *sema_ct_eval_expr(SemaContext *context, bool is_type_eval, Expr *inner, bo switch (token) { case TOKEN_CONST_IDENT: - inner->identifier_expr.is_const = true; + inner->unresolved_ident_expr.is_const = true; break; case TOKEN_IDENT: if (!interned_version) @@ -317,7 +317,7 @@ Expr *sema_ct_eval_expr(SemaContext *context, bool is_type_eval, Expr *inner, bo } return NULL; } - inner->identifier_expr.is_const = false; + inner->unresolved_ident_expr.is_const = false; break; case TYPE_TOKENS: { @@ -349,10 +349,10 @@ Expr *sema_ct_eval_expr(SemaContext *context, bool is_type_eval, Expr *inner, bo } return NULL; } - inner->expr_kind = EXPR_IDENTIFIER; + inner->expr_kind = EXPR_UNRESOLVED_IDENTIFIER; inner->resolve_status = RESOLVE_NOT_DONE; - inner->identifier_expr.ident = interned_version; - inner->identifier_expr.path = path; + inner->unresolved_ident_expr.ident = interned_version; + inner->unresolved_ident_expr.path = path; return inner; } @@ -457,7 +457,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp return sema_binary_is_expr_lvalue(context, top_expr, expr->expr_other_context.inner, failed_ref); case EXPR_IDENTIFIER: { - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) { if (failed_ref) goto FAILED_REF; @@ -520,6 +520,8 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp case EXPR_CONST: if (failed_ref) goto FAILED_REF; RETURN_SEMA_ERROR(top_expr, "You cannot assign to a constant expression."); + case EXPR_UNRESOLVED_IDENTIFIER: + UNREACHABLE case EXPR_POISONED: case EXPR_ADDR_CONVERSION: case EXPR_ANYSWITCH: @@ -531,7 +533,8 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp case EXPR_BUILTIN_ACCESS: case EXPR_CALL: case EXPR_CAST: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: + case EXPR_CATCH_UNRESOLVED: case EXPR_COMPILER_CONST: case EXPR_COMPOUND_LITERAL: case EXPR_COND: @@ -648,9 +651,11 @@ static bool expr_may_ref(Expr *expr) return expr_may_ref(expr->expr_other_context.inner); case EXPR_SUBSCRIPT_ASSIGN: return true; + case EXPR_UNRESOLVED_IDENTIFIER: + UNREACHABLE case EXPR_IDENTIFIER: { - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) return false; if (decl->var.kind == VARDECL_CONST) return false; decl = decl_raw(decl); @@ -700,7 +705,8 @@ static bool expr_may_ref(Expr *expr) case EXPR_BUILTIN_ACCESS: case EXPR_CALL: case EXPR_CAST: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: + case EXPR_CATCH_UNRESOLVED: case EXPR_COMPILER_CONST: case EXPR_COMPOUND_LITERAL: case EXPR_COND: @@ -759,19 +765,19 @@ bool sema_expr_check_assign(SemaContext *context, Expr *expr, bool *failed_ref) if (expr->expr_kind == EXPR_SUBSCRIPT) { inner = exprptr(expr->subscript_expr.expr); - if (inner->expr_kind == EXPR_IDENTIFIER) inner->identifier_expr.decl->var.is_written = true; + if (inner->expr_kind == EXPR_IDENTIFIER) inner->ident_expr->var.is_written = true; goto CHECK_INNER; } if (expr->expr_kind == EXPR_BITACCESS || expr->expr_kind == EXPR_ACCESS) expr = expr->access_expr.parent; if (expr->expr_kind == EXPR_IDENTIFIER) { - expr->identifier_expr.decl->var.is_written = true; + expr->ident_expr->var.is_written = true; } if (expr->expr_kind != EXPR_UNARY) return true; inner = expr->inner_expr; CHECK_INNER: if (inner->expr_kind != EXPR_IDENTIFIER) return true; - Decl *decl = inner->identifier_expr.decl; + Decl *decl = inner->ident_expr; if (decl->decl_kind != DECL_VAR) return true; if (!decl->var.in_param) return true; RETURN_SEMA_ERROR(inner, "'in' parameters may not be assigned to."); @@ -779,7 +785,7 @@ CHECK_INNER: static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) { - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; decl = decl_flatten(decl); switch (decl->decl_kind) { @@ -1009,7 +1015,7 @@ static inline bool sema_identifier_find_possible_inferred(SemaContext *context, { case DECL_ENUM: case DECL_FAULT: - return sema_expr_analyse_enum_constant(context, expr, expr->identifier_expr.ident, parent_decl); + return sema_expr_analyse_enum_constant(context, expr, expr->unresolved_ident_expr.ident, parent_decl); case DECL_UNION: case DECL_STRUCT: case DECL_BITSTRUCT: @@ -1025,14 +1031,14 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Decl *ambiguous_decl = NULL; Decl *private_symbol = NULL; - ASSERT_SPAN(expr, expr && expr->identifier_expr.ident); - DEBUG_LOG("Resolving identifier '%s'", expr->identifier_expr.ident); + ASSERT_SPAN(expr, expr && expr->unresolved_ident_expr.ident); + DEBUG_LOG("Resolving identifier '%s'", expr->unresolved_ident_expr.ident); ASSERT_SPAN(expr, expr->resolve_status != RESOLVE_DONE); DeclId body_param; - if (!expr->identifier_expr.path && context->current_macro && (body_param = context->current_macro->func_decl.body_param)) + if (!expr->unresolved_ident_expr.path && context->current_macro && (body_param = context->current_macro->func_decl.body_param)) { - if (expr->identifier_expr.ident == declptr(body_param)->name) + if (expr->unresolved_ident_expr.ident == declptr(body_param)->name) { expr->expr_kind = EXPR_MACRO_BODY_EXPANSION; expr->body_expansion_expr.first_stmt = 0; @@ -1043,12 +1049,12 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, } } // Just start with inference - if (!expr->identifier_expr.path && to) + if (!expr->unresolved_ident_expr.path && to) { if (sema_identifier_find_possible_inferred(context, to, expr)) return expr_ok(expr); } - Decl *decl = sema_find_path_symbol(context, expr->identifier_expr.ident, expr->identifier_expr.path); + Decl *decl = sema_find_path_symbol(context, expr->unresolved_ident_expr.ident, expr->unresolved_ident_expr.path); // Is this a broken decl? if (!decl_ok(decl)) return false; @@ -1056,7 +1062,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, // Rerun if we can't do inference. if (!decl) { - decl = sema_resolve_symbol(context, expr->identifier_expr.ident, expr->identifier_expr.path, expr->span); + decl = sema_resolve_symbol(context, expr->unresolved_ident_expr.ident, expr->unresolved_ident_expr.path, expr->span); (void)decl; ASSERT_SPAN(expr, !decl); return false; @@ -1065,7 +1071,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, if (decl_needs_prefix(decl)) { if (!sema_analyse_decl(context, decl)) return false; - if (decl->unit->module != context->unit->module && !expr->identifier_expr.path) + if (decl->unit->module != context->unit->module && !expr->unresolved_ident_expr.path) { const char *message; switch (decl->decl_kind) @@ -1122,9 +1128,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, break; } } - if (!decl->type) decl->type = type_void; - expr->identifier_expr = (ExprIdentifier) { .decl = decl }; - expr->type = decl->type; + expr_resolve_ident(expr, decl); return true; } @@ -1158,7 +1162,7 @@ static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *e static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *binary, Expr *left, Expr *right) { // Special handling of f = FOO_BAR - if (right->resolve_status != RESOLVE_DONE && right->expr_kind == EXPR_IDENTIFIER && right->identifier_expr.is_const) + if (right->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && right->unresolved_ident_expr.is_const) { if (!sema_analyse_expr(context, left)) return false; if (type_flatten(left->type)->type_kind == TYPE_ENUM) @@ -1167,7 +1171,7 @@ static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *binar } } // Special handling of f = FOO_BAR - if (left->resolve_status != RESOLVE_DONE && left->expr_kind == EXPR_IDENTIFIER && left->identifier_expr.is_const) + if (left->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && left->unresolved_ident_expr.is_const) { if (!sema_analyse_expr(context, right)) return false; if (type_flatten(right->type)->type_kind == TYPE_ENUM) @@ -1284,7 +1288,7 @@ static inline bool sema_call_check_invalid_body_arguments(SemaContext *context, INLINE bool sema_arg_is_pass_through_ref(Expr *expr) { if (expr->expr_kind != EXPR_IDENTIFIER) return false; - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) return false; return decl->var.kind == VARDECL_PARAM_REF; } @@ -1347,7 +1351,7 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, { if (arg->expr_kind == EXPR_IDENTIFIER) { - param->alignment = arg->identifier_expr.decl->alignment; + param->alignment = arg->ident_expr->alignment; } else { @@ -1887,14 +1891,14 @@ static inline bool sema_call_check_contract_param_match(SemaContext *context, De } if (expr->expr_kind == EXPR_UNARY && expr->unary_expr.expr->expr_kind == EXPR_IDENTIFIER) { - if (expr->unary_expr.expr->identifier_expr.decl->var.kind == VARDECL_CONST && param->var.out_param) + if (expr->unary_expr.expr->ident_expr->var.kind == VARDECL_CONST && param->var.out_param) { SEMA_ERROR(expr, "A const parameter may not be passed into a function or macro as an 'out' argument."); return false; } } if (expr->expr_kind != EXPR_IDENTIFIER) return true; - Decl *ident = expr->identifier_expr.decl; + Decl *ident = expr->ident_expr; if (ident->decl_kind != DECL_VAR) return true; if (ident->var.out_param && param->var.in_param) { @@ -2789,7 +2793,7 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool case EXPR_BUILTIN: return sema_expr_analyse_builtin_call(context, expr); case EXPR_IDENTIFIER: - decl = func_expr->identifier_expr.decl; + decl = func_expr->ident_expr; if (!sema_analyse_decl(context, decl)) return false; break; case EXPR_ACCESS: @@ -3687,9 +3691,10 @@ RETRY: goto RETRY; } case EXPR_IDENTIFIER: - if (child->resolve_status == RESOLVE_DONE) goto ALREADY_RESOLVED; + goto ALREADY_RESOLVED; + case EXPR_UNRESOLVED_IDENTIFIER: // A path is not allowed. - if (child->identifier_expr.path) break; + if (child->unresolved_ident_expr.path) break; return child; case EXPR_CT_IDENT: if (child->resolve_status == RESOLVE_DONE) goto ALREADY_RESOLVED; @@ -3839,10 +3844,10 @@ static inline Decl *sema_check_for_type_method(SemaContext *context, Expr *expr, static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, Expr *identifier, bool *missing_ref) { - ASSERT_SPAN(expr, identifier->expr_kind == EXPR_IDENTIFIER); + ASSERT_SPAN(expr, identifier->expr_kind == EXPR_UNRESOLVED_IDENTIFIER); Type *canonical = parent_type->canonical; - const char *name = identifier->identifier_expr.ident; - bool is_const = identifier->identifier_expr.is_const; + const char *name = identifier->unresolved_ident_expr.ident; + bool is_const = identifier->unresolved_ident_expr.is_const; if (!is_const) { @@ -3862,7 +3867,6 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp if (missing_ref) goto MISSING_REF; RETURN_SEMA_ERROR(expr, "'%s' does not have a property or method '%s'.", type_to_error_string(parent_type), name); } - expr->expr_kind = EXPR_IDENTIFIER; expr_resolve_ident(expr, member); return true; } @@ -3935,8 +3939,6 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp expr->type = type_member; return true; } - - expr->expr_kind = EXPR_IDENTIFIER; expr_resolve_ident(expr, member); return true; MISSING_REF: @@ -3946,11 +3948,11 @@ MISSING_REF: static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, Expr *identifier, bool *missing_ref) { - ASSERT_SPAN(expr, identifier->expr_kind == EXPR_IDENTIFIER); + ASSERT_SPAN(expr, identifier->expr_kind == EXPR_UNRESOLVED_IDENTIFIER); Decl *decl = parent->const_expr.member.decl; - const char *name = identifier->identifier_expr.ident; - bool is_const = identifier->identifier_expr.is_const; + const char *name = identifier->unresolved_ident_expr.ident; + bool is_const = identifier->unresolved_ident_expr.is_const; if (is_const) { @@ -4905,7 +4907,7 @@ static inline bool sema_analyse_maybe_dead_expr(SemaContext *context, Expr *expr static inline void sema_expr_flatten_const_ident(Expr *expr) { if (expr->expr_kind != EXPR_IDENTIFIER) return; - Decl *ident = expr->identifier_expr.decl; + Decl *ident = expr->ident_expr; if (ident->decl_kind != DECL_VAR) return; switch (ident->var.kind) { @@ -4992,7 +4994,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo SourceSpan span; Expr *identifier = sema_expr_resolve_access_child(context, child, missing_ref); if (!identifier) return false; - const char *kw = identifier->identifier_expr.ident; + const char *kw = identifier->unresolved_ident_expr.ident; // 2. If our left-hand side is a type, e.g. MyInt.abc, handle this here. if (parent->expr_kind == EXPR_TYPEINFO) @@ -5001,7 +5003,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo } if (parent->expr_kind == EXPR_IDENTIFIER) { - Decl *decl = parent->identifier_expr.decl; + Decl *decl = parent->ident_expr; switch (decl->decl_kind) { case DECL_FUNC: @@ -5777,7 +5779,7 @@ RETRY:; if (is_unwrapped_var && IS_OPTIONAL(right)) { - sema_rewrap_var(context, left->identifier_expr.decl); + sema_rewrap_var(context, left->ident_expr); return true; } if (left->expr_kind == EXPR_SUBSCRIPT_ASSIGN) @@ -7020,7 +7022,7 @@ static inline const char *sema_addr_may_take_of_var(Expr *expr, Decl *decl) static inline const char *sema_addr_may_take_of_ident(Expr *inner) { - Decl *decl = decl_raw(inner->identifier_expr.decl); + Decl *decl = decl_raw(inner->ident_expr); switch (decl->decl_kind) { case DECL_POISONED: @@ -7158,7 +7160,7 @@ RESOLVED: expr->type = type_get_ptr_recurse(inner->type); if (inner->expr_kind == EXPR_IDENTIFIER) { - Decl *ident = inner->identifier_expr.decl; + Decl *ident = inner->ident_expr; if (decl_is_global(ident)) { expr_rewrite_const_ref(expr, ident); @@ -8125,10 +8127,10 @@ RETRY: switch (current->expr_kind) { case EXPR_CT_IDENT: - current = current->identifier_expr.decl->var.init_expr; + current = current->ident_expr->var.init_expr; goto RETRY; case EXPR_IDENTIFIER: - decl = current->identifier_expr.decl; + decl = current->ident_expr; break; default: SEMA_ERROR(expr, "A variable was expected here."); @@ -8192,8 +8194,8 @@ static inline bool sema_expr_analyse_decl_element(SemaContext *context, Designat } Expr *field = sema_expr_resolve_access_child(context, element->field_expr, is_missing); if (!field) return false; - if (field->expr_kind != EXPR_IDENTIFIER) RETURN_SEMA_ERROR(field, "Expected an identifier here."); - const char *kw = field->identifier_expr.ident; + if (field->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) RETURN_SEMA_ERROR(field, "Expected an identifier here."); + const char *kw = field->unresolved_ident_expr.ident; if (kw == kw_ptr) { switch (actual_type->type_kind) @@ -8739,16 +8741,15 @@ static inline bool sema_expr_analyse_embed(SemaContext *context, Expr *expr, boo static inline bool sema_expr_analyse_generic_ident(SemaContext *context, Expr *expr) { Expr *parent = exprptr(expr->generic_ident_expr.parent); - if (parent->expr_kind != EXPR_IDENTIFIER) + if (parent->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) { SEMA_ERROR(parent, "Expected an identifier to parameterize."); return false; } - Decl *symbol = sema_analyse_parameterized_identifier(context, parent->identifier_expr.path, - parent->identifier_expr.ident, parent->span, + Decl *symbol = sema_analyse_parameterized_identifier(context, parent->unresolved_ident_expr.path, + parent->unresolved_ident_expr.ident, parent->span, expr->generic_ident_expr.parmeters, NULL); if (!decl_ok(symbol)) return false; - expr->expr_kind = EXPR_IDENTIFIER; expr_resolve_ident(expr, symbol); return true; } @@ -8896,11 +8897,10 @@ static inline bool sema_expr_analyse_ct_feature(SemaContext *context, Expr *expr Expr *inner = expr->ct_call_expr.main_var; if (expr->ct_call_expr.flat_path) goto ERROR; - if (inner->expr_kind != EXPR_IDENTIFIER) goto ERROR; - if (inner->resolve_status != RESOLVE_NOT_DONE) goto ERROR; - if (!inner->identifier_expr.is_const) goto ERROR; + if (inner->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) goto ERROR; + if (!inner->unresolved_ident_expr.is_const) goto ERROR; - const char *name = inner->identifier_expr.ident; + const char *name = inner->unresolved_ident_expr.ident; void *value = htable_get(&compiler.context.features, (void *)name); ASSERT_SPAN(expr, !value || value == name); expr_rewrite_const_bool(expr, type_bool, value != NULL); @@ -8951,9 +8951,9 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr success = false; } break; - case EXPR_IDENTIFIER: + case EXPR_UNRESOLVED_IDENTIFIER: { - Decl *decl = sema_find_path_symbol(active_context, main_expr->identifier_expr.ident, main_expr->identifier_expr.path); + 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; break; @@ -9042,9 +9042,10 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_POISONED: success = false; break; + case EXPR_CATCH_UNRESOLVED: + case EXPR_CATCH: case EXPR_COND: case EXPR_TEST_HOOK: - case EXPR_CATCH_UNWRAP: case EXPR_DESIGNATOR: case EXPR_BENCHMARK_HOOK: case EXPR_TRY_UNWRAP: @@ -9056,6 +9057,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_DECL: case EXPR_LAST_FAULT: case EXPR_DEFAULT_ARG: + case EXPR_IDENTIFIER: case EXPR_NAMED_ARGUMENT: UNREACHABLE case EXPR_BINARY: @@ -9511,7 +9513,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr, case EXPR_ANYSWITCH: case EXPR_ASM: case EXPR_BENCHMARK_HOOK: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH_UNRESOLVED: + case EXPR_CATCH: case EXPR_COND: case EXPR_DEFAULT_ARG: case EXPR_DESIGNATOR: @@ -9659,6 +9662,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr, case EXPR_TYPEID: return sema_expr_analyse_typeid(context, expr); case EXPR_IDENTIFIER: + UNREACHABLE + case EXPR_UNRESOLVED_IDENTIFIER: return sema_expr_analyse_identifier(context, NULL, expr); case EXPR_CALL: return sema_expr_analyse_call(context, expr, NULL); @@ -9836,7 +9841,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat { Expr *inner = exprptr(expr->expr_kind == EXPR_SUBSCRIPT ? expr->subscript_expr.expr : expr->slice_expr.expr); if (inner->expr_kind != EXPR_IDENTIFIER) break; - Decl *decl = inner->identifier_expr.decl; + Decl *decl = inner->ident_expr; if (decl->decl_kind != DECL_VAR) break; if (!decl->var.out_param) break; RETURN_SEMA_ERROR(expr, "'out' parameters may not be read."); @@ -9846,7 +9851,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat if (expr->unary_expr.operator != UNARYOP_DEREF) break; Expr *inner = expr->inner_expr; if (inner->expr_kind != EXPR_IDENTIFIER) break; - Decl *decl = inner->identifier_expr.decl; + Decl *decl = inner->ident_expr; if (decl->decl_kind != DECL_VAR) break; if (!decl->var.out_param) break; RETURN_SEMA_ERROR(expr, "'out' parameters may not be read."); @@ -10104,7 +10109,7 @@ RETRY: case EXPR_EXPR_BLOCK: if (!sema_expr_analyse_expr_block(context, infer_type, expr)) return expr_poison(expr); break; - case EXPR_IDENTIFIER: + case EXPR_UNRESOLVED_IDENTIFIER: if (!sema_expr_analyse_identifier(context, infer_type, expr)) return expr_poison(expr); break; case EXPR_LAMBDA: diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index 294e40444..150a66e0a 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -876,7 +876,7 @@ void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value) } if (value->expr_kind == EXPR_IDENTIFIER) { - Decl *ident = decl_flatten(value->identifier_expr.decl); + Decl *ident = decl_flatten(value->ident_expr); ASSERT0(ident->decl_kind == DECL_VAR); ASSERT0(ident->var.kind == VARDECL_CONST); const_init_rewrite_to_value(const_init, expr_copy(ident->var.init_expr)); @@ -1305,12 +1305,12 @@ static Decl *sema_resolve_element_for_name(SemaContext *context, Decl **decls, D Expr *field = sema_expr_resolve_access_child(context, element->field_expr, NULL); if (!field) return poisoned_decl; - if (field->expr_kind != EXPR_IDENTIFIER) + if (field->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) { SEMA_ERROR(field, "An identifier was expected."); return poisoned_decl; } - const char *name = field->identifier_expr.ident; + const char *name = field->unresolved_ident_expr.ident; unsigned old_index = *index; FOREACH_IDX(i, Decl *, decl, decls) { diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index ba0914b31..1efa089bc 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -264,6 +264,7 @@ RETRY: case EXPR_MACRO_BODY: case EXPR_MEMBER_GET: case EXPR_NAMED_ARGUMENT: + case EXPR_UNRESOLVED_IDENTIFIER: UNREACHABLE case EXPR_OTHER_CONTEXT: UNREACHABLE @@ -328,8 +329,8 @@ RETRY: return; } case EXPR_CAST: - expr = exprptr(expr->cast_expr.expr); - goto RETRY; + ASSERT(expr, "Casts should be gone when tracing liveness"); + UNREACHABLE case EXPR_FORCE_UNWRAP: case EXPR_RETHROW: case EXPR_OPTIONAL: @@ -357,17 +358,13 @@ RETRY: case EXPR_BUILTIN_ACCESS: expr = exprptr(expr->builtin_access_expr.inner); goto RETRY; - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: { - if (expr->catch_unwrap_expr.lhs) + if (expr->catch_expr.decl) { - sema_trace_expr_liveness(expr->catch_unwrap_expr.lhs); + sema_trace_decl_liveness(expr->catch_expr.decl); } - else if (expr->catch_unwrap_expr.decl) - { - sema_trace_decl_liveness(expr->catch_unwrap_expr.decl); - } - FOREACH(Expr *, e, expr->catch_unwrap_expr.exprs) sema_trace_expr_liveness(e); + FOREACH(Expr *, e, expr->catch_expr.exprs) sema_trace_expr_liveness(e); return; } case EXPR_CONST: @@ -417,7 +414,7 @@ RETRY: sema_trace_expr_list_liveness(expr->designated_init_list); return; case EXPR_IDENTIFIER: - sema_trace_decl_liveness(expr->identifier_expr.decl); + sema_trace_decl_liveness(expr->ident_expr); return; case EXPR_INITIALIZER_LIST: { @@ -425,6 +422,7 @@ RETRY: return; } case EXPR_LAMBDA: + case EXPR_CATCH_UNRESOLVED: UNREACHABLE case EXPR_MACRO_BLOCK: { diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 53107f60c..6d33622fe 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -317,15 +317,15 @@ static void sema_unwrappable_from_catch_in_else(SemaContext *c, Expr *cond) last = sema_dive_into_expression(last); // Skip any non-unwraps - if (last->expr_kind != EXPR_CATCH_UNWRAP) return; + if (last->expr_kind != EXPR_CATCH) return; // If we have "if (catch x)" then this will unwrap x in the // else branch. - FOREACH(Expr *, expr, last->catch_unwrap_expr.exprs) + FOREACH(Expr *, expr, last->unresolved_catch_expr.exprs) { if (expr->expr_kind != EXPR_IDENTIFIER) continue; - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) continue; ASSERT0(decl->type->type_kind == TYPE_OPTIONAL && "The variable should always be optional at this point."); @@ -566,7 +566,7 @@ INLINE bool sema_check_not_stack_variable_escape(SemaContext *context, Expr *exp CHECK_ACCESS: while (expr->expr_kind == EXPR_ACCESS) expr = expr->access_expr.parent; if (expr->expr_kind != EXPR_IDENTIFIER) return true; - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; if (decl->decl_kind != DECL_VAR) return true; switch (decl->var.kind) { @@ -687,7 +687,8 @@ static inline bool sema_expr_valid_try_expression(Expr *expr) switch (expr->expr_kind) { case EXPR_BITASSIGN: - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH: + case EXPR_CATCH_UNRESOLVED: case EXPR_COND: case EXPR_POISONED: case EXPR_CT_AND_OR: @@ -701,6 +702,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr) case EXPR_CT_EVAL: case EXPR_CT_IDENT: case EXPR_NAMED_ARGUMENT: + case EXPR_UNRESOLVED_IDENTIFIER: UNREACHABLE case EXPR_BINARY: case EXPR_POINTER_OFFSET: @@ -809,7 +811,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) expr->type = type_bool; return true; } - Decl *decl = ident->identifier_expr.decl; + Decl *decl = ident->ident_expr; if (decl->decl_kind != DECL_VAR) { RETURN_SEMA_ERROR(ident, "Expected this to be the name of an optional variable, but it isn't. Did you mistype?"); @@ -847,15 +849,15 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) // 3. We are creating a new variable // 3a. If we had a variable type, then our expression must be an identifier. - if (ident->expr_kind != EXPR_IDENTIFIER) RETURN_SEMA_ERROR(ident, "A variable name was expected here."); + if (ident->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) RETURN_SEMA_ERROR(ident, "A variable name was expected here."); ASSERT0(ident->resolve_status != RESOLVE_DONE); - if (ident->identifier_expr.path) RETURN_SEMA_ERROR(ident->identifier_expr.path, "The variable may not have a path."); - if (ident->identifier_expr.is_const) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter."); - const char *ident_name = ident->identifier_expr.ident; + if (ident->unresolved_ident_expr.path) RETURN_SEMA_ERROR(ident->unresolved_ident_expr.path, "The variable may not have a path."); + if (ident->unresolved_ident_expr.is_const) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter."); + const char *ident_name = ident->unresolved_ident_expr.ident; // Special check for `if (try a = a)` - if (optional->expr_kind == EXPR_IDENTIFIER && optional->resolve_status == RESOLVE_NOT_DONE - && !optional->identifier_expr.path && optional->identifier_expr.ident == ident_name) + if (optional->expr_kind == EXPR_UNRESOLVED_IDENTIFIER + && !optional->unresolved_ident_expr.path && optional->unresolved_ident_expr.ident == ident_name) { RETURN_SEMA_ERROR(ident, "If you want to unwrap the same variable, use 'if (try %s)' { ... } instead.", ident_name); } @@ -881,7 +883,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) } // 4d. A new declaration is created. - Decl *decl = decl_new_var(ident->identifier_expr.ident, ident->span, var_type, VARDECL_LOCAL); + Decl *decl = decl_new_var(ident->unresolved_ident_expr.ident, ident->span, var_type, VARDECL_LOCAL); // 4e. Analyse it if (!sema_analyse_var_decl(context, decl, true)) return false; @@ -918,16 +920,11 @@ static inline bool sema_analyse_try_unwrap_chain(SemaContext *context, Expr *exp } static inline bool sema_analyse_catch_unwrap(SemaContext *context, Expr *expr) { - Expr *ident = expr->catch_unwrap_expr.variable; + Expr *ident = expr->unresolved_catch_expr.variable; + TypeInfo *type = expr->unresolved_catch_expr.type; - TypeInfo *type = expr->catch_unwrap_expr.type; - - if (!type && !ident) - { - expr->catch_unwrap_expr.lhs = NULL; - expr->catch_unwrap_expr.decl = NULL; - goto RESOLVE_EXPRS; - } + Decl *decl = NULL; + if (!type && !ident) goto RESOLVE_EXPRS; type = type ? type : type_info_new_base(type_anyfault, expr->span); if (!sema_resolve_type_info(context, type, RESOLVE_TYPE_DEFAULT)) return false; @@ -937,27 +934,24 @@ static inline bool sema_analyse_catch_unwrap(SemaContext *context, Expr *expr) RETURN_SEMA_ERROR(type, "Expected the type to be %s, not %s.", type_quoted_error_string(type_anyfault), type_quoted_error_string(type->type)); } - if (ident->expr_kind != EXPR_IDENTIFIER) + if (ident->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) { RETURN_SEMA_ERROR(ident, "A variable name was expected here."); } - ASSERT0(ident->resolve_status != RESOLVE_DONE); - if (ident->identifier_expr.path) RETURN_SEMA_ERROR(ident->identifier_expr.path, "The variable may not have a path."); - if (ident->identifier_expr.is_const) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter."); + if (ident->unresolved_ident_expr.path) RETURN_SEMA_ERROR(ident->unresolved_ident_expr.path, "The variable may not have a path."); + if (ident->unresolved_ident_expr.is_const) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter."); // 4d. A new declaration is created. - Decl *decl = decl_new_var(ident->identifier_expr.ident, ident->span, type, VARDECL_LOCAL); + decl = decl_new_var(ident->unresolved_ident_expr.ident, ident->span, type, VARDECL_LOCAL); decl->var.no_init = true; // 4e. Analyse it if (!sema_analyse_var_decl(context, decl, true)) return false; - expr->catch_unwrap_expr.decl = decl; - expr->catch_unwrap_expr.lhs = NULL; - RESOLVE_EXPRS:; - FOREACH(Expr *, fail, expr->catch_unwrap_expr.exprs) + Expr **exprs = expr->unresolved_catch_expr.exprs; + FOREACH(Expr *, fail, exprs) { if (!sema_analyse_expr(context, fail)) return false; if (!type_is_optional(fail->type)) @@ -965,6 +959,8 @@ RESOLVE_EXPRS:; RETURN_SEMA_ERROR(fail, "This expression is not optional, did you add it by mistake?"); } } + expr->catch_expr = (ExprCatch) { .exprs = exprs, .decl = decl }; + expr->expr_kind = EXPR_CATCH; expr->type = type_anyfault; expr->resolve_status = RESOLVE_DONE; return true; @@ -1001,7 +997,7 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond return false; } return sema_analyse_try_unwrap_chain(context, expr, cond_type, result); - case EXPR_CATCH_UNWRAP: + case EXPR_CATCH_UNRESOLVED: if (cond_type != COND_TYPE_UNWRAP_BOOL && cond_type != COND_TYPE_UNWRAP) { RETURN_SEMA_ERROR(expr, "Catch unwrapping is only allowed inside of a 'while' or 'if' conditional, maybe '@catch()' will do what you need?"); @@ -1019,11 +1015,11 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond { // No variable on the lhs? Then it can't be an any unwrap. Expr *left = exprptr(expr->binary_expr.left); - if (left->resolve_status == RESOLVE_DONE || left->expr_kind != EXPR_IDENTIFIER || left->identifier_expr.path) goto NORMAL_EXPR; + if (left->resolve_status == RESOLVE_DONE || left->expr_kind != EXPR_UNRESOLVED_IDENTIFIER || left->unresolved_ident_expr.path) goto NORMAL_EXPR; // Does the identifier exist in the parent scope? // then again it can't be an any unwrap. - BoolErr defined_in_scope = sema_symbol_is_defined_in_scope(context, left->identifier_expr.ident); + BoolErr defined_in_scope = sema_symbol_is_defined_in_scope(context, left->unresolved_ident_expr.ident); if (defined_in_scope == BOOL_ERR) return false; if (defined_in_scope == BOOL_TRUE) goto NORMAL_EXPR; @@ -1041,7 +1037,7 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond if (type != type_any) goto NORMAL_EXPR; // Found an expansion here expr->expr_kind = EXPR_ANYSWITCH; - expr->any_switch.new_ident = left->identifier_expr.ident; + expr->any_switch.new_ident = left->unresolved_ident_expr.ident; expr->any_switch.span = left->span; expr->any_switch.any_expr = right; expr->any_switch.is_deref = is_deref; @@ -1055,7 +1051,7 @@ static inline bool sema_analyse_last_cond(SemaContext *context, Expr *expr, Cond if (type != type_any) return true; if (expr->expr_kind == EXPR_IDENTIFIER) { - Decl *decl = expr->identifier_expr.decl; + Decl *decl = expr->ident_expr; expr->expr_kind = EXPR_ANYSWITCH; expr->any_switch.is_deref = false; expr->any_switch.is_assign = false; @@ -1604,7 +1600,7 @@ SKIP_OVERLOAD:; bool is_variable = false; if (enumerator->expr_kind == EXPR_IDENTIFIER) { - enumerator->identifier_expr.decl->var.is_written = true; + enumerator->ident_expr->var.is_written = true; is_variable = true; } else if (expr_may_addr(enumerator)) @@ -1616,7 +1612,7 @@ SKIP_OVERLOAD:; Decl *temp = NULL; if (is_variable) { - temp = enumerator->identifier_expr.decl; + temp = enumerator->ident_expr; } else {