mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Update to fix with splat.
This commit is contained in:
@@ -315,6 +315,11 @@ void decl_append_links_to_global_during_codegen(Decl *decl)
|
||||
}
|
||||
}
|
||||
|
||||
bool decl_is_defaulted_var(Decl *decl)
|
||||
{
|
||||
return decl->decl_kind == DECL_VAR && decl->var.no_init && decl->var.defaulted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the expected number of elements needed for an initializer
|
||||
* by folding any anonymous structs and unions.
|
||||
|
||||
@@ -2324,6 +2324,7 @@ const char *decl_safe_name(Decl *decl);
|
||||
const char *decl_to_name(Decl *decl);
|
||||
const char *decl_to_a_name(Decl *decl);
|
||||
int decl_count_elements(Decl *structlike);
|
||||
bool decl_is_defaulted_var(Decl *decl);
|
||||
void decl_append_links_to_global_during_codegen(Decl *decl);
|
||||
|
||||
INLINE bool decl_ok(Decl *decl);
|
||||
|
||||
@@ -1281,10 +1281,13 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
SEMA_ERROR(expr, message);
|
||||
return false;
|
||||
RETURN_SEMA_ERROR(expr, message);
|
||||
}
|
||||
}
|
||||
if (decl_is_defaulted_var(decl))
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "The parameter '%s' was not provided by the caller.", decl->name);
|
||||
}
|
||||
if (decl->resolve_status != RESOLVE_DONE)
|
||||
{
|
||||
if (!sema_analyse_decl(context, decl)) return decl_poison(decl);
|
||||
@@ -1348,6 +1351,10 @@ static inline bool sema_expr_resolve_ct_identifier(SemaContext *context, Expr *e
|
||||
return expr_poison(expr);
|
||||
}
|
||||
|
||||
if (decl_is_defaulted_var(decl))
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "The parameter '%s' was not provided by the caller.", decl->name);
|
||||
}
|
||||
ASSERT_SPAN(expr, decl->decl_kind == DECL_VAR);
|
||||
ASSERT_SPAN(expr, decl->resolve_status == RESOLVE_DONE);
|
||||
|
||||
@@ -1830,7 +1837,7 @@ static SplatResult sema_splat_optional_argument(SemaContext *context, Expr *expr
|
||||
if (!candidate->var.no_init) return SPLAT_NONE;
|
||||
// We found it, it's a valid variable.
|
||||
Decl *local = sema_find_local(context, candidate->name);
|
||||
if (local && local->var.kind == candidate->var.kind) return SPLAT_ONE;
|
||||
if (local && local->var.kind == candidate->var.kind && !decl_is_defaulted_var(local)) return SPLAT_ONE;
|
||||
// It's missing! Let's splat-zero
|
||||
return SPLAT_ZERO;
|
||||
}
|
||||
@@ -2923,8 +2930,8 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
{
|
||||
// Skip raw vararg
|
||||
if (!param) continue;
|
||||
if (param->var.no_init && param->var.defaulted) continue;
|
||||
if (!sema_add_local(¯o_context, param)) goto EXIT_FAIL;
|
||||
if (param->var.no_init && param->var.defaulted) continue;
|
||||
if (param->var.init_expr)
|
||||
{
|
||||
Type *param_type = param->type;
|
||||
@@ -6854,6 +6861,10 @@ static bool sema_expr_fold_hash(SemaContext *context, Expr *expr)
|
||||
ASSERT_SPAN(expr, decl->decl_kind == DECL_VAR);
|
||||
DEBUG_LOG("Replacing expr (%p) with '%s' (%p) expression resolve: %d", expr, expr_kind_to_string(decl->var.init_expr->expr_kind), decl->var.init_expr, decl->var.init_expr->resolve_status);
|
||||
bool is_ref = expr->hash_ident_expr.is_ref;
|
||||
if (decl_is_defaulted_var(decl))
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "The parameter '%s' was not provided by the caller.", decl->name);
|
||||
}
|
||||
expr_replace(expr, copy_expr_single(decl->var.init_expr));
|
||||
if (is_ref) expr_set_to_ref(expr);
|
||||
REMINDER("Handle inlining at");
|
||||
@@ -10756,7 +10767,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
{
|
||||
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;
|
||||
success = decl != NULL && !decl_is_defaulted_var(decl);
|
||||
break;
|
||||
}
|
||||
case EXPR_HASH_IDENT:
|
||||
@@ -10765,6 +10776,11 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
{
|
||||
Decl *decl = sema_resolve_symbol(active_context, main_expr->hash_ident_expr.identifier, NULL, main_expr->span);
|
||||
if (!decl) goto FAIL;
|
||||
if (decl_is_defaulted_var(decl))
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
bool is_ref = main_expr->hash_ident_expr.is_ref;
|
||||
main_expr = copy_expr_single(decl->var.init_expr);
|
||||
if (is_ref) expr_set_to_ref(main_expr);
|
||||
@@ -10772,7 +10788,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
}
|
||||
Decl *decl = sema_find_symbol(active_context, main_expr->hash_ident_expr.identifier);
|
||||
if (!decl_ok(decl)) goto FAIL;
|
||||
success = decl != NULL;
|
||||
success = decl != NULL && !decl_is_defaulted_var(decl);
|
||||
break;
|
||||
}
|
||||
case EXPR_COMPILER_CONST:
|
||||
@@ -10837,7 +10853,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
{
|
||||
Decl *decl = sema_find_symbol(active_context, main_expr->ct_ident_expr.identifier);
|
||||
if (!decl_ok(decl)) goto FAIL;
|
||||
success = decl != NULL;
|
||||
success = decl != NULL && !decl_is_defaulted_var(decl);
|
||||
break;
|
||||
}
|
||||
case EXPR_CALL:
|
||||
|
||||
@@ -1217,7 +1217,7 @@ static inline bool sema_analyse_ct_type_assign_stmt(SemaContext *context, Ast *s
|
||||
|
||||
Decl *decl = sema_find_symbol(context, statement->ct_type_assign_stmt.var_name);
|
||||
if (!decl) RETURN_SEMA_ERROR(statement, "'%s' is not defined in this scope yet.", statement->ct_type_assign_stmt.var_name);
|
||||
|
||||
if (decl_is_defaulted_var(decl)) RETURN_SEMA_ERROR(statement, "The parameter '%s' was not provided by the caller.", decl->name);
|
||||
decl->var.init_expr = right;
|
||||
statement->ast_kind = AST_NOP_STMT;
|
||||
|
||||
|
||||
@@ -258,6 +258,10 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
|
||||
Expr *init_expr = decl->var.init_expr;
|
||||
if (!init_expr)
|
||||
{
|
||||
if (decl_is_defaulted_var(decl))
|
||||
{
|
||||
RETURN_SEMA_ERROR(type_info, "The parameter '%s' was not provided by the caller.", decl->name);
|
||||
}
|
||||
RETURN_SEMA_ERROR(type_info, "You need to assign a type to '%s' before using it.", decl->name);
|
||||
}
|
||||
ASSERT_SPAN(init_expr, expr_is_const_typeid(init_expr));
|
||||
|
||||
62
test/test_suite/functions/splat_err.c3
Normal file
62
test/test_suite/functions/splat_err.c3
Normal file
@@ -0,0 +1,62 @@
|
||||
import std;
|
||||
fn int test1()
|
||||
{
|
||||
@test1();
|
||||
}
|
||||
|
||||
fn int test2()
|
||||
{
|
||||
@test2();
|
||||
}
|
||||
|
||||
fn int test3()
|
||||
{
|
||||
@test3();
|
||||
}
|
||||
|
||||
fn int test4()
|
||||
{
|
||||
@test4();
|
||||
}
|
||||
|
||||
fn void test5()
|
||||
{
|
||||
@test5();
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
@test6();
|
||||
}
|
||||
|
||||
macro @test1($Foo = ...)
|
||||
{
|
||||
return $Foo.typeid; // #error: The parameter '$Foo' was not provided by the caller.
|
||||
}
|
||||
|
||||
macro @test2(#foo = ...)
|
||||
{
|
||||
return #foo; // #error: The parameter '#foo' was not provided by the caller
|
||||
}
|
||||
|
||||
macro @test3(foo = ...)
|
||||
{
|
||||
return foo; // #error: The parameter 'foo' was not provided by the caller.
|
||||
}
|
||||
|
||||
macro @test4($foo = ...)
|
||||
{
|
||||
return $foo; // #error: The parameter '$foo' was not provided by the caller
|
||||
}
|
||||
|
||||
macro @test5($Foo = ...)
|
||||
{
|
||||
$Foo = int; // #error: The parameter '$Foo' was not provided by the caller
|
||||
return $Foo.typeid;
|
||||
}
|
||||
|
||||
macro @test6(foo = ...)
|
||||
{
|
||||
foo = 1; // #error: The parameter 'foo' was not provided by the caller
|
||||
return foo;
|
||||
}
|
||||
30
test/test_suite/lambda/lambda_splat_macro2.c3t
Normal file
30
test/test_suite/lambda/lambda_splat_macro2.c3t
Normal file
@@ -0,0 +1,30 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
import std;
|
||||
fn int main()
|
||||
{
|
||||
bool x = test1a()();
|
||||
return 0;
|
||||
}
|
||||
|
||||
macro test1a(bool $a = ...) => fn bool()
|
||||
{
|
||||
return test1b(...$a);
|
||||
};
|
||||
macro test1b(bool $a = ...) => $defined($a) ??? $a : false;
|
||||
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
entry:
|
||||
%x = alloca i8, align 1
|
||||
%0 = call i8 @"test.test1a$lambda1"()
|
||||
store i8 %0, ptr %x, align 1
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define internal zeroext i8 @"test.test1a$lambda1"() #0 {
|
||||
entry:
|
||||
ret i8 0
|
||||
}
|
||||
Reference in New Issue
Block a user