mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
$defined returns an error when assigning a struct initializer with an incorrect type #2449
This commit is contained in:
@@ -93,6 +93,7 @@
|
||||
- Compiler hangs on == overload if other is generic #2443
|
||||
- Fix missing end of line when encountering errors in project creation.
|
||||
- Const enum methods are not being recognized. #2445
|
||||
- $defined returns an error when assigning a struct initializer with an incorrect type #2449
|
||||
|
||||
### Stdlib changes
|
||||
- Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`.
|
||||
|
||||
@@ -2416,7 +2416,7 @@ bool sema_analyse_expr(SemaContext *context, Expr *expr);
|
||||
bool sema_cast_const(Expr *expr);
|
||||
|
||||
bool sema_expr_check_discard(SemaContext *context, Expr *expr);
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr);
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr, bool *no_match_ref);
|
||||
bool sema_analyse_decl(SemaContext *context, Decl *decl);
|
||||
|
||||
bool sema_analyse_method_register(SemaContext *context, Decl *method);
|
||||
@@ -2429,7 +2429,7 @@ bool sema_analyse_statement(SemaContext *context, Ast *statement);
|
||||
|
||||
bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type *left_type, Expr *right,
|
||||
bool is_unwrapped_var, bool is_declaration, bool *failed_ref);
|
||||
bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr);
|
||||
bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr, bool *no_match_ref);
|
||||
Expr **sema_expand_vasplat_exprs(SemaContext *context, Expr **exprs);
|
||||
|
||||
bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool optional,
|
||||
|
||||
@@ -1690,7 +1690,7 @@ ERR:
|
||||
bool sema_analyse_const_enum_constant_val(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Expr *value = decl->enum_constant.value;
|
||||
if (!sema_analyse_inferred_expr(context, decl->type, value)) return decl_poison(decl);
|
||||
if (!sema_analyse_inferred_expr(context, decl->type, value,NULL)) return decl_poison(decl);
|
||||
if (!expr_is_runtime_const(value))
|
||||
{
|
||||
SEMA_ERROR(value, "Expected an constant enum value.");
|
||||
@@ -3612,7 +3612,7 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA
|
||||
if (!sema_resolve_type_info(context, type_infoptr(param->var.type_info), RESOLVE_TYPE_DEFAULT)) return false;
|
||||
Type *type = typeget(param->var.type_info);
|
||||
ASSERT_SPAN(decl, type);
|
||||
if (!sema_analyse_inferred_expr(context, type, expr)) goto ERR;
|
||||
if (!sema_analyse_inferred_expr(context, type, expr, NULL)) goto ERR;
|
||||
if (!cast_implicit(context, expr, type, false)) goto ERR;
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ static inline bool sema_expr_analyse_pointer_offset(SemaContext *context, Expr *
|
||||
static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, CheckType check);
|
||||
static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bool *missing_ref, CheckType check,
|
||||
bool lvalue);
|
||||
static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr, bool *no_match_ref);
|
||||
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);
|
||||
@@ -1365,7 +1365,7 @@ static inline bool sema_binary_analyse_with_inference(SemaContext *context, Expr
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
if (type_kind_is_any_vector(type_flatten(left->type)->type_kind))
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, left->type, right);
|
||||
return sema_analyse_inferred_expr(context, left->type, right, NULL);
|
||||
}
|
||||
return sema_analyse_expr(context, right);
|
||||
}
|
||||
@@ -1374,7 +1374,7 @@ static inline bool sema_binary_analyse_with_inference(SemaContext *context, Expr
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (type_kind_is_any_vector(type_flatten(right->type)->type_kind))
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, right->type, left);
|
||||
return sema_analyse_inferred_expr(context, right->type, left, NULL);
|
||||
}
|
||||
return sema_analyse_expr(context, left);
|
||||
}
|
||||
@@ -1386,7 +1386,7 @@ static inline bool sema_binary_analyse_with_inference(SemaContext *context, Expr
|
||||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_CONST_ENUM:
|
||||
return sema_analyse_inferred_expr(context, left->type, right);
|
||||
return sema_analyse_inferred_expr(context, left->type, right, NULL);
|
||||
default:
|
||||
return sema_analyse_expr(context, right);
|
||||
}
|
||||
@@ -1405,7 +1405,7 @@ static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *left,
|
||||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_CONST_ENUM:
|
||||
return sema_analyse_inferred_expr(context, left->type, right);
|
||||
return sema_analyse_inferred_expr(context, left->type, right, NULL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1418,7 +1418,7 @@ static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *left,
|
||||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_CONST_ENUM:
|
||||
return sema_analyse_inferred_expr(context, right->type, left);
|
||||
return sema_analyse_inferred_expr(context, right->type, left, NULL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1428,7 +1428,7 @@ static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *left,
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
if (type_kind_is_any_vector(type_flatten(left->type)->type_kind))
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, left->type, right);
|
||||
return sema_analyse_inferred_expr(context, left->type, right, NULL);
|
||||
}
|
||||
return sema_analyse_expr(context, right);
|
||||
}
|
||||
@@ -1437,7 +1437,7 @@ static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *left,
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (type_kind_is_any_vector(type_flatten(right->type)->type_kind))
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, right->type, left);
|
||||
return sema_analyse_inferred_expr(context, right->type, left, NULL);
|
||||
}
|
||||
return sema_analyse_expr(context, left);
|
||||
}
|
||||
@@ -3820,7 +3820,7 @@ static inline bool sema_expr_resolve_subscript_index(SemaContext *context, Expr
|
||||
if (overload)
|
||||
{
|
||||
index_type = overload->func_decl.signature.params[1]->type;
|
||||
if (!sema_analyse_inferred_expr(context, index_type, index))
|
||||
if (!sema_analyse_inferred_expr(context, index_type, index, NULL))
|
||||
{
|
||||
expr_poison(index);
|
||||
return false;
|
||||
@@ -5984,10 +5984,10 @@ static inline bool sema_analyse_maybe_dead_expr(SemaContext *context, Expr *expr
|
||||
{
|
||||
if (!is_dead || context->active_scope.is_dead)
|
||||
{
|
||||
return infer_type ? sema_analyse_inferred_expr(context, infer_type, expr) : sema_analyse_expr(context, expr);
|
||||
return infer_type ? sema_analyse_inferred_expr(context, infer_type, expr, NULL) : sema_analyse_expr(context, expr);
|
||||
}
|
||||
context->active_scope.is_dead = true;
|
||||
bool success = infer_type ? sema_analyse_inferred_expr(context, infer_type, expr) : sema_analyse_expr(context, expr);
|
||||
bool success = infer_type ? sema_analyse_inferred_expr(context, infer_type, expr, NULL) : sema_analyse_expr(context, expr);
|
||||
context->active_scope.is_dead = false;
|
||||
return success;
|
||||
}
|
||||
@@ -6579,7 +6579,7 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr, bool
|
||||
{
|
||||
expr->expr_kind = EXPR_COMPOUND_LITERAL;
|
||||
expr->expr_compound_literal = (ExprCompoundLiteral) { .initializer = inner, .type_info = type_info };
|
||||
return sema_expr_analyse_compound_literal(context, expr);
|
||||
return sema_expr_analyse_compound_literal(context, expr, invalid_cast_ref);
|
||||
}
|
||||
bool success = sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER);
|
||||
if (!sema_analyse_expr(context, inner) || !success) return false;
|
||||
@@ -6613,7 +6613,7 @@ static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Typ
|
||||
Type *base = left_flat->array.base;
|
||||
if (right->expr_kind == EXPR_SLICE || (compiler.build.old_slice_copy && right->expr_kind == EXPR_INITIALIZER_LIST && right->initializer_list))
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, left_type, right)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, left_type, right, NULL)) return false;
|
||||
if (left_flat == type_flatten(right->type) || right->type == type_untypedlist) goto SLICE_COPY;
|
||||
}
|
||||
else
|
||||
@@ -6637,7 +6637,7 @@ static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Typ
|
||||
type_quoted_error_string(base));
|
||||
}
|
||||
}
|
||||
if (!sema_analyse_inferred_expr(context, base, right)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, base, right, NULL)) return false;
|
||||
}
|
||||
Type *right_type = right->type->canonical;
|
||||
if (base->canonical != right_type && (type_is_arraylike(right_type) || right_type->type_kind == TYPE_SLICE))
|
||||
@@ -6719,7 +6719,7 @@ static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *e
|
||||
ASSERT_SPAN(left, left->resolve_status == RESOLVE_DONE);
|
||||
|
||||
// Evaluate right side to using inference from last type.
|
||||
if (!sema_analyse_inferred_expr(context, left->type, right)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, left->type, right, NULL)) return false;
|
||||
|
||||
if (!expr_is_runtime_const(right))
|
||||
{
|
||||
@@ -6926,7 +6926,7 @@ static bool sema_binary_analyse_ct_subscript_op_assign(SemaContext *context, Exp
|
||||
static BoolErr sema_insert_overload_in_op_assign_or_error(SemaContext *context, Expr *expr, Expr *left, Expr *right, BinaryOp operator, Type *lhs_type)
|
||||
{
|
||||
assert(type_is_user_defined(lhs_type));
|
||||
if (!sema_analyse_inferred_expr(context, lhs_type, right)) return BOOL_ERR;
|
||||
if (!sema_analyse_inferred_expr(context, lhs_type, right, NULL)) return BOOL_ERR;
|
||||
static OperatorOverload MAP[BINARYOP_LAST + 1] = {
|
||||
[BINARYOP_ADD_ASSIGN] = OVERLOAD_PLUS_ASSIGN,
|
||||
[BINARYOP_SUB_ASSIGN] = OVERLOAD_MINUS_ASSIGN,
|
||||
@@ -7208,7 +7208,7 @@ BITSTRUCT_OK:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, left->type, right)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, left->type, right, NULL)) return false;
|
||||
}
|
||||
|
||||
// 3. Copy type & set properties.
|
||||
@@ -9100,7 +9100,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, left)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, left, NULL)) return false;
|
||||
}
|
||||
|
||||
Type *type = left->type;
|
||||
@@ -9118,7 +9118,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr,
|
||||
EndJump active_scope_jump = context->active_scope.end_jump;
|
||||
|
||||
// First we analyse the "else" and try to implictly cast.
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, right)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, right, NULL)) return false;
|
||||
|
||||
if (left->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
@@ -10585,10 +10585,16 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
success = false;
|
||||
}
|
||||
break;
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
if (!sema_expr_analyse_compound_literal(context, main_expr, &failed))
|
||||
{
|
||||
if (!failed) goto FAIL;
|
||||
success = false;
|
||||
}
|
||||
break;
|
||||
case EXPR_CT_ARG:
|
||||
case EXPR_BITACCESS:
|
||||
case EXPR_BITASSIGN:
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
case EXPR_EMBED:
|
||||
case EXPR_GENERIC_IDENT:
|
||||
case EXPR_MACRO_BODY:
|
||||
@@ -10695,7 +10701,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty
|
||||
// Not found, so generate a new.
|
||||
if (!decl)
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, arg_expr)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, arg_expr, NULL)) return false;
|
||||
switch (sema_resolve_storage_type(context, arg_expr->type))
|
||||
{
|
||||
case STORAGE_ERROR:
|
||||
@@ -10721,14 +10727,14 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty
|
||||
// An expr argument, this means we copy and evaluate.
|
||||
ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), NULL), false);
|
||||
expr_replace(expr, copy_expr_single(arg_expr));
|
||||
return sema_analyse_inferred_expr(context, infer_type, expr);
|
||||
return sema_analyse_inferred_expr(context, infer_type, expr, NULL);
|
||||
}
|
||||
case TOKEN_CT_VACONST:
|
||||
{
|
||||
// An expr argument, this means we copy and evaluate.
|
||||
ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), NULL), false);
|
||||
arg_expr = copy_expr_single(arg_expr);
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, arg_expr)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, infer_type, arg_expr, NULL)) return false;
|
||||
if (!sema_cast_const(arg_expr))
|
||||
{
|
||||
RETURN_SEMA_ERROR(arg_expr, "This argument needs to be a compile time constant.");
|
||||
@@ -10801,7 +10807,7 @@ static inline bool sema_expr_analyse_assignable(SemaContext *context, Expr *expr
|
||||
}
|
||||
if (!type) RETURN_SEMA_ERROR(type_expr, "Expected a type or constant typeid here.");
|
||||
Expr *inner = exprptr(expr->assignable_expr.expr);
|
||||
if (!sema_analyse_inferred_expr(context, type, inner)) goto FAILED;
|
||||
if (!sema_analyse_inferred_expr(context, type, inner, NULL)) goto FAILED;
|
||||
bool ok = may_cast(context, inner, type, false, true);
|
||||
expr_rewrite_const_bool(expr, type_bool, ok);
|
||||
context->call_env.in_no_eval = in_no_eval;
|
||||
@@ -10980,7 +10986,7 @@ static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, b
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr, bool *no_match_ref)
|
||||
{
|
||||
TypeInfo *type_info = expr->expr_compound_literal.type_info;
|
||||
// We allow infering the size of arrays.
|
||||
@@ -10991,7 +10997,7 @@ static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr
|
||||
RETURN_SEMA_ERROR(type_info, "The type here should always be written as a plain type and not an optional, please remove the '?'.");
|
||||
}
|
||||
if (!sema_resolve_type_structure(context, type)) return false;
|
||||
if (!sema_expr_analyse_initializer_list(context, type, expr->expr_compound_literal.initializer)) return false;
|
||||
if (!sema_expr_analyse_initializer_list(context, type, expr->expr_compound_literal.initializer, no_match_ref)) return false;
|
||||
expr_replace(expr, expr->expr_compound_literal.initializer);
|
||||
return true;
|
||||
}
|
||||
@@ -11153,7 +11159,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
return sema_expr_analyse_force_unwrap(context, expr);
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
return sema_expr_analyse_compound_literal(context, expr);
|
||||
return sema_expr_analyse_compound_literal(context, expr, NULL);
|
||||
case EXPR_RETHROW:
|
||||
return sema_expr_analyse_rethrow(context, expr, NULL);
|
||||
case EXPR_CONST:
|
||||
@@ -11187,7 +11193,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
|
||||
return sema_expr_analyse_access(context, expr, NULL, check, false);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
return sema_expr_analyse_initializer_list(context, type_untypedlist, expr);
|
||||
return sema_expr_analyse_initializer_list(context, type_untypedlist, expr, NULL);
|
||||
case EXPR_CAST:
|
||||
return sema_expr_analyse_cast(context, expr, NULL);
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
@@ -11229,7 +11235,7 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, to, expr)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, to, expr, no_match_ref)) return false;
|
||||
}
|
||||
if (!sema_cast_rvalue(context, expr, true)) return false;
|
||||
if (to) to = type_no_optional(to);
|
||||
@@ -11761,7 +11767,7 @@ bool sema_cast_const(Expr *expr)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr)
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr, bool *no_match_ref)
|
||||
{
|
||||
Type *original_type = to;
|
||||
to = type_no_optional(to);
|
||||
@@ -11796,13 +11802,13 @@ RETRY:
|
||||
InliningSpan *old_span = context->inlined_at;
|
||||
context->inlined_at = new_span;
|
||||
expr_replace(expr, expr->expr_other_context.inner);
|
||||
bool success = sema_analyse_inferred_expr(context, original_type, expr);
|
||||
bool success = sema_analyse_inferred_expr(context, original_type, expr, no_match_ref);
|
||||
context->inlined_at = old_span;
|
||||
return success;
|
||||
}
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
if (!sema_expr_analyse_initializer_list(context, to, expr)) return expr_poison(expr);
|
||||
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);
|
||||
@@ -11828,7 +11834,7 @@ RETRY:
|
||||
case EXPR_UNARY:
|
||||
if (to && expr->unary_expr.operator == UNARYOP_TADDR && to->canonical->type_kind == TYPE_POINTER && to->canonical != type_voidptr)
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, type_get_indexed_type(to), expr->unary_expr.expr)) return expr_poison(expr);
|
||||
if (!sema_analyse_inferred_expr(context, type_get_indexed_type(to), expr->unary_expr.expr,NULL)) return expr_poison(expr);
|
||||
}
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
#include "sema_internal.h"
|
||||
|
||||
static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *context, Decl *assigned, Expr *initializer);
|
||||
static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *context, Decl *assigned, Expr *initializer, bool *no_match_ref);
|
||||
static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer);
|
||||
static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, Expr *initializer);
|
||||
Expr *initializer, bool *no_match_ref);
|
||||
static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, Expr *initializer, bool *no_match_ref);
|
||||
static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer);
|
||||
Expr *initializer, bool *no_match_ref);
|
||||
static inline void sema_not_enough_elements_error(SemaContext *context, Expr *initializer, int element);
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *assigned_type, Type *flattened, Expr *expr);
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *assigned_type, Type *flattened, Expr *expr, bool *no_match_ref);
|
||||
static void sema_create_const_initializer_from_designated_init(ConstInitializer *const_init, Expr *initializer);
|
||||
static Decl *sema_resolve_element_for_name(SemaContext *context, Decl **decls, DesignatorElement ***elements_ref, unsigned *index, bool is_substruct);
|
||||
static Type *sema_expr_analyse_designator(SemaContext *context, Type *current, Expr *expr, ArrayIndex *max_index, Decl **member_ptr);
|
||||
@@ -182,7 +182,7 @@ static inline void sema_not_enough_elements_error(SemaContext *context, Expr *in
|
||||
* Perform analysis for a plain initializer, that is one initializing all fields.
|
||||
* @return true if analysis succeeds.
|
||||
*/
|
||||
static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *context, Decl *assigned, Expr *initializer)
|
||||
static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *context, Decl *assigned, Expr *initializer, bool *no_match_ref)
|
||||
{
|
||||
ASSERT(assigned->resolve_status == RESOLVE_DONE);
|
||||
Expr **elements = initializer->initializer_list;
|
||||
@@ -198,6 +198,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
// 2. We don't support this actually, but we used to. Maybe we will in the future.
|
||||
if (elements_needed == 0)
|
||||
{
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
// Generate a nice error message for zero.
|
||||
RETURN_SEMA_ERROR(elements[0], "Too many elements in initializer, it must be empty.");
|
||||
}
|
||||
@@ -222,6 +223,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
// user pinpoint where they put the double elements.
|
||||
if (i >= elements_needed)
|
||||
{
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
ASSERT(i < size);
|
||||
RETURN_SEMA_ERROR(elements[i], "Too many elements in initializer, expected only %d.", elements_needed);
|
||||
}
|
||||
@@ -245,6 +247,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
}
|
||||
if (i >= size)
|
||||
{
|
||||
if (!no_match_ref) goto NO_MATCH;
|
||||
sema_not_enough_elements_error(context, initializer, (int)i);
|
||||
return false;
|
||||
}
|
||||
@@ -265,12 +268,13 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
}
|
||||
if (i >= size)
|
||||
{
|
||||
if (!no_match_ref) goto NO_MATCH;
|
||||
sema_not_enough_elements_error(context, initializer, i);
|
||||
return false;
|
||||
}
|
||||
Expr *element = elements[i];
|
||||
// 6. We know the required type, so resolve the expression.
|
||||
if (!sema_analyse_expr_rhs(context, members[i]->type, element, true, NULL, false)) return false;
|
||||
if (!sema_analyse_expr_rhs(context, members[i]->type, element, true, no_match_ref, false)) return false;
|
||||
if (member->decl_kind == DECL_VAR && member->var.kind == VARDECL_BITMEMBER)
|
||||
{
|
||||
if (!sema_bit_assignment_check(context, element, members[i])) return false;
|
||||
@@ -302,7 +306,9 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
|
||||
// 7. Done!
|
||||
return true;
|
||||
|
||||
NO_MATCH:;
|
||||
*no_match_ref = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Expr *sema_create_struct_from_expressions(Decl *struct_decl, SourceSpan span, Expr **exprs)
|
||||
@@ -316,7 +322,7 @@ Expr *sema_create_struct_from_expressions(Decl *struct_decl, SourceSpan span, Ex
|
||||
* @return true if analysis succeeds.
|
||||
*/
|
||||
static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer)
|
||||
Expr *initializer, bool *no_match_ref)
|
||||
{
|
||||
Expr **elements = initializer->initializer_list;
|
||||
bool inferred_len = type_len_is_inferred(flattened);
|
||||
@@ -338,9 +344,9 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
|
||||
if (expected_members == 0 && !inferred_len)
|
||||
{
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
// Generate a nice error message for zero.
|
||||
SEMA_ERROR(elements[0], "Too many elements in initializer, it must be empty.");
|
||||
return false;
|
||||
RETURN_SEMA_ERROR(elements[0], "Too many elements in initializer, it must be empty.");
|
||||
}
|
||||
|
||||
bool optional = false;
|
||||
@@ -353,12 +359,12 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
Expr *element = elements[i];
|
||||
if (!inferred_len && i >= expected_members)
|
||||
{
|
||||
SEMA_ERROR(element, "Too many elements in initializer, expected only %d.", expected_members);
|
||||
return false;
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(element, "Too many elements in initializer, expected only %d.", expected_members);
|
||||
}
|
||||
if (is_vector)
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, inner_type, element)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, inner_type, element, no_match_ref)) return false;
|
||||
Type *element_type = element->type;
|
||||
Type *element_flat = type_flatten(element_type);
|
||||
if (element_flat->type_kind == TYPE_VECTOR
|
||||
@@ -367,8 +373,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
unsigned len = element_flat->array.len;
|
||||
if (!inferred_len && i + len > expected_members)
|
||||
{
|
||||
SEMA_ERROR(element, "Too many elements in initializer when expanding, expected only %d.", expected_members);
|
||||
return false;
|
||||
RETURN_SEMA_ERROR(element, "Too many elements in initializer when expanding, expected only %d.", expected_members);
|
||||
}
|
||||
Expr *expr_two = expr_new_expr(EXPR_TWO, element);
|
||||
Decl *decl = decl_new_generated_var(element_type, VARDECL_LOCAL, element->span);
|
||||
@@ -394,19 +399,19 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
optional = optional || IS_OPTIONAL(element);
|
||||
continue;
|
||||
}
|
||||
if (!cast_implicit(context, element, inner_type, false)) return false;
|
||||
if (!cast_implicit_checked(context, element, inner_type, false, no_match_ref)) return false;
|
||||
optional = optional || IS_OPTIONAL(element);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_expr_rhs(context, inner_type, element, true, NULL, false)) return false;
|
||||
if (!sema_analyse_expr_rhs(context, inner_type, element, true, no_match_ref, false)) return false;
|
||||
if (inner_is_inferred)
|
||||
{
|
||||
if (inferred_element)
|
||||
{
|
||||
if (!cast_implicit(context, element, inferred_element, false))
|
||||
if (!cast_implicit_checked(context, element, inferred_element, false, no_match_ref))
|
||||
{
|
||||
SEMA_NOTE(elements[0], "Type inferred from here.");
|
||||
if (!no_match_ref) SEMA_NOTE(elements[0], "Type inferred from here.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -422,8 +427,8 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
{
|
||||
if (!inferred_element)
|
||||
{
|
||||
SEMA_ERROR(initializer, "Zero sized elements are not allowed when inferring size.");
|
||||
return false;
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(initializer, "Zero sized elements are not allowed when inferring size.");
|
||||
}
|
||||
inner_type = inferred_element;
|
||||
}
|
||||
@@ -441,8 +446,8 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
|
||||
if (!inferred_len && expected_members > count)
|
||||
{
|
||||
SEMA_ERROR(elements[count - 1], "Too few elements in initializer, %d elements are needed.", expected_members);
|
||||
return false;
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(elements[count - 1], "Too few elements in initializer, %d elements are needed.", expected_members);
|
||||
}
|
||||
|
||||
initializer->resolve_status = RESOLVE_DONE;
|
||||
@@ -464,9 +469,12 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
|
||||
// 7. Done!
|
||||
return true;
|
||||
NO_MATCH:;
|
||||
*no_match_ref = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, Expr *initializer)
|
||||
static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, Expr *initializer, bool *no_match_ref)
|
||||
{
|
||||
Expr **init_list = initializer->initializer_list;
|
||||
FOREACH(Expr *, element, init_list)
|
||||
@@ -474,6 +482,11 @@ static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, E
|
||||
if (!sema_analyse_expr(context, element)) return false;
|
||||
if (!sema_cast_const(element))
|
||||
{
|
||||
if (no_match_ref)
|
||||
{
|
||||
*no_match_ref = true;
|
||||
return false;
|
||||
}
|
||||
RETURN_SEMA_ERROR(element, "An untyped list can only have "
|
||||
"constant elements, you can try "
|
||||
"to type the list by prefixing the type and possibly enclosing it in parentheses, "
|
||||
@@ -488,7 +501,7 @@ static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, E
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type *assigned, Type *flattened,
|
||||
Expr *initializer)
|
||||
Expr *initializer, bool *no_match_ref)
|
||||
{
|
||||
Expr **init_expressions = initializer->designated_init_list;
|
||||
Type *original = flattened->canonical;
|
||||
@@ -513,7 +526,7 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
bitmember_count_without_value += 1;
|
||||
}
|
||||
if (!value) RETURN_SEMA_ERROR(expr, "This initializer needs a value.");
|
||||
if (!sema_analyse_expr_rhs(context, result, value, true, NULL, false)) return false;
|
||||
if (!sema_analyse_expr_rhs(context, result, value, true, no_match_ref, false)) return false;
|
||||
if (is_bitmember)
|
||||
{
|
||||
if (!sema_bit_assignment_check(context, value, member)) return false;
|
||||
@@ -525,7 +538,8 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
inner_type = type_no_optional(value->type);
|
||||
}
|
||||
}
|
||||
if (bitmember_count_without_value != 0 && bitmember_count_without_value != vec_size(init_expressions)) {
|
||||
if (bitmember_count_without_value != 0 && bitmember_count_without_value != vec_size(init_expressions))
|
||||
{
|
||||
RETURN_SEMA_ERROR(initializer, "Mixing the omission of initializers is not permitted.");
|
||||
}
|
||||
Type *type;
|
||||
@@ -549,7 +563,7 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *assigned_type, Type *flattened, Expr *expr)
|
||||
static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *assigned_type, Type *flattened, Expr *expr, bool *no_match_ref)
|
||||
{
|
||||
// Note at this point this we either have
|
||||
// EXPR_DESIGNATED_INITIALIZER_LIST
|
||||
@@ -559,13 +573,13 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass
|
||||
// 1. Designated initializer is separately evaluated.
|
||||
if (expr->expr_kind == EXPR_DESIGNATED_INITIALIZER_LIST)
|
||||
{
|
||||
return sema_expr_analyse_designated_initializer(context, assigned_type, flattened, expr);
|
||||
return sema_expr_analyse_designated_initializer(context, assigned_type, flattened, expr,NULL);
|
||||
}
|
||||
|
||||
if (expr->expr_kind == EXPR_CONST)
|
||||
{
|
||||
ASSERT(expr->const_expr.const_kind == CONST_INITIALIZER);
|
||||
return cast_implicit(context, expr, assigned_type, false);
|
||||
return cast_implicit_checked(context, expr, assigned_type, false, no_match_ref);
|
||||
}
|
||||
ASSERT(expr->expr_kind == EXPR_INITIALIZER_LIST);
|
||||
|
||||
@@ -583,8 +597,8 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass
|
||||
{
|
||||
if (type_len_is_inferred(assigned_type))
|
||||
{
|
||||
SEMA_ERROR(expr, "Zero length arrays / vectors are not permitted.");
|
||||
return false;
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(expr, "Zero length arrays / vectors are not permitted.");
|
||||
}
|
||||
if (flattened == type_untypedlist)
|
||||
{
|
||||
@@ -598,7 +612,7 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass
|
||||
// 4. We might have a complist, because were analyzing $foo = { ... } or similar.
|
||||
if (assigned_type == type_untypedlist)
|
||||
{
|
||||
return sema_expr_analyse_untyped_initializer(context, expr);
|
||||
return sema_expr_analyse_untyped_initializer(context, expr, no_match_ref);
|
||||
}
|
||||
|
||||
// 5. If not, then we see if we have an array.
|
||||
@@ -609,11 +623,14 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ass
|
||||
flattened->type_kind == TYPE_SLICE ||
|
||||
flattened->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
return sema_expr_analyse_array_plain_initializer(context, assigned_type, flattened, expr);
|
||||
return sema_expr_analyse_array_plain_initializer(context, assigned_type, flattened, expr, no_match_ref);
|
||||
}
|
||||
|
||||
expr->type = assigned_type;
|
||||
return sema_expr_analyse_struct_plain_initializer(context, flattened->decl, expr);
|
||||
return sema_expr_analyse_struct_plain_initializer(context, flattened->decl, expr, no_match_ref);
|
||||
NO_MATCH:;
|
||||
*no_match_ref = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,7 +790,7 @@ ConstInitializer *sema_merge_bitstruct_const_initializers(ConstInitializer *lhs,
|
||||
return lhs;
|
||||
}
|
||||
|
||||
bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr)
|
||||
bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr, bool *no_match_ref)
|
||||
{
|
||||
|
||||
if (!to) to = type_untypedlist;
|
||||
@@ -801,7 +818,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
case TYPE_VECTOR:
|
||||
return sema_expr_analyse_initializer(context, to, flattened, expr);
|
||||
return sema_expr_analyse_initializer(context, to, flattened, expr, no_match_ref);
|
||||
case TYPE_SLICE:
|
||||
{
|
||||
if (is_zero_init)
|
||||
@@ -811,7 +828,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
}
|
||||
// Resolve this as an inferred array.
|
||||
Type *type = type_get_inferred_array(flattened->array.base);
|
||||
if (!sema_expr_analyse_initializer(context, type, type, expr)) return false;
|
||||
if (!sema_expr_analyse_initializer(context, type, type, expr, no_match_ref)) return false;
|
||||
if (expr_is_const_initializer(expr))
|
||||
{
|
||||
ConstInitializer *init = expr->const_expr.initializer;
|
||||
@@ -823,6 +840,11 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
expr_insert_addr(expr);
|
||||
if (!sema_analyse_expr(context, expr)) return false;
|
||||
if (no_match_ref)
|
||||
{
|
||||
if (!cast_explicit_silent(context, expr, to)) goto NO_MATCH;
|
||||
return true;
|
||||
}
|
||||
return cast_explicit(context, expr, to);
|
||||
}
|
||||
case TYPE_POINTER:
|
||||
@@ -832,6 +854,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
expr_rewrite_to_const_zero(expr, to);
|
||||
return true;
|
||||
}
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(expr, "Pointers cannot be initialized using an initializer list, instead you need to take the address of an array.");
|
||||
case TYPE_VOID:
|
||||
case TYPE_POISONED:
|
||||
@@ -840,6 +863,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_MEMBER:
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(expr, "You cannot use %s with an initializer list.", type_quoted_error_string(to));
|
||||
default:
|
||||
if (is_zero_init)
|
||||
@@ -850,7 +874,11 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (no_match_ref) goto NO_MATCH;
|
||||
RETURN_SEMA_ERROR(expr, "You cannot use %s with a non-empty initializer list.", type_quoted_error_string(to));
|
||||
NO_MATCH:
|
||||
*no_match_ref = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value)
|
||||
|
||||
@@ -1494,7 +1494,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
|
||||
if (variable_type_info)
|
||||
{
|
||||
if (!sema_analyse_inferred_expr(context, inferred_type, enumerator)) return SCOPE_POP_ERROR();
|
||||
if (!sema_analyse_inferred_expr(context, inferred_type, enumerator,NULL)) return SCOPE_POP_ERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
23
test/test_suite/compile_time_introspection/defined_inits.c3t
Normal file
23
test/test_suite/compile_time_introspection/defined_inits.c3t
Normal file
@@ -0,0 +1,23 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
struct Test
|
||||
{
|
||||
int a;
|
||||
String b;
|
||||
}
|
||||
fn int main()
|
||||
{
|
||||
bool a = $defined(Test a = {"hello"});
|
||||
bool b = $defined((Test){"hello"});
|
||||
return 0;
|
||||
}
|
||||
/* #expect: test.ll
|
||||
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%a = alloca i8, align 1
|
||||
%b = alloca i8, align 1
|
||||
store i8 0, ptr %a, align 1
|
||||
store i8 0, ptr %b, align 1
|
||||
ret i32 0
|
||||
}
|
||||
Reference in New Issue
Block a user