mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Prevent #hash arguments from taking code that modifies ct variables. #1794
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
- Allowed passing arguments to @test / @benchmark runners via `c3c test[benchmark] -- -o --opt1 <arg1>`
|
||||
- Handle bytes and string literals the same way in terms of zero termination.
|
||||
- Function comments are stored and displayed with -P.
|
||||
|
||||
- Prevent `#hash` arguments from taking code that modifies ct variables. #1794
|
||||
### Fixes
|
||||
- Fix case trying to initialize a `char[*]*` from a String.
|
||||
- Fix Map & HashMap `put_all_for_create` not copying all elements, causing `init_from_map` to create incomplete copy.
|
||||
|
||||
@@ -1679,6 +1679,7 @@ typedef struct
|
||||
bool ensures : 1;
|
||||
bool pure : 1;
|
||||
bool in_no_eval : 1;
|
||||
bool in_other : 1;
|
||||
SourceSpan in_if_resolution;
|
||||
Decl **opt_returns;
|
||||
union
|
||||
|
||||
@@ -5677,6 +5677,11 @@ static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *e
|
||||
// Evaluate right side to using inference from last type.
|
||||
if (!sema_analyse_inferred_expr(context, left->type, right)) return false;
|
||||
|
||||
if (context->call_env.in_other)
|
||||
{
|
||||
RETURN_SEMA_ERROR(left, "Compile time variables may only be modified in the scope they are defined in.");
|
||||
}
|
||||
|
||||
left->ct_ident_expr.decl->var.init_expr = right;
|
||||
expr_replace(expr, right);
|
||||
left->ct_ident_expr.decl->type = right->type;
|
||||
@@ -5696,6 +5701,12 @@ static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Ex
|
||||
|
||||
Decl *decl = sema_find_symbol(context, info->unresolved.name);
|
||||
if (!decl) RETURN_SEMA_ERROR(info, "'%s' is not defined in this scope yet.", info->unresolved.name);
|
||||
|
||||
if (context->call_env.in_other)
|
||||
{
|
||||
RETURN_SEMA_ERROR(left, "Compile time variables may only be modified in the scope they are defined in.");
|
||||
}
|
||||
|
||||
decl->var.init_expr = right;
|
||||
expr->expr_kind = EXPR_NOP;
|
||||
expr->type = type_void;
|
||||
@@ -5792,6 +5803,10 @@ static bool sema_binary_analyse_ct_common_assign(SemaContext *context, Expr *exp
|
||||
Decl *left_var = left->ct_ident_expr.decl;
|
||||
if (!sema_cast_ct_ident_rvalue(context, left)) return false;
|
||||
|
||||
if (context->call_env.in_other)
|
||||
{
|
||||
RETURN_SEMA_ERROR(left, "Compile time variables may only be modified in the scope they are defined in.");
|
||||
}
|
||||
expr->binary_expr.operator = binaryop_assign_base_op(expr->binary_expr.operator);
|
||||
|
||||
if (!sema_expr_analyse_binary(context, expr, NULL)) return false;
|
||||
@@ -9526,7 +9541,13 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
|
||||
if (expr->resolve_status == RESOLVE_DONE) return expr_ok(expr);
|
||||
ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_NOT_DONE);
|
||||
expr->resolve_status = RESOLVE_RUNNING;
|
||||
return sema_analyse_expr_dispatch(context, expr, check);
|
||||
{
|
||||
bool in_other = context->call_env.in_other;
|
||||
context->call_env.in_other = true;
|
||||
bool success = sema_analyse_expr_dispatch(context, expr, check);
|
||||
context->call_env.in_other = in_other;
|
||||
return success;
|
||||
}
|
||||
case EXPR_CT_CASTABLE:
|
||||
return sema_expr_analyse_castable(context, expr);
|
||||
case EXPR_EMBED:
|
||||
|
||||
23
test/test_suite/compile_time/mod_in_other_scope.c3
Normal file
23
test/test_suite/compile_time/mod_in_other_scope.c3
Normal file
@@ -0,0 +1,23 @@
|
||||
module test;
|
||||
|
||||
macro void @foo(#a)
|
||||
{
|
||||
#a;
|
||||
}
|
||||
|
||||
macro void @bar(#a)
|
||||
{
|
||||
$typeof(#a) x;
|
||||
}
|
||||
fn int main()
|
||||
{
|
||||
int $i;
|
||||
var $Type;
|
||||
@foo($Type = int); // #error: only be modified
|
||||
@foo($i = 2); // #error: only be modified
|
||||
@foo($i += 1); // #error: only be modified
|
||||
@bar($Type = int); // #error: only be modified
|
||||
@bar($i = 2); // #error: only be modified
|
||||
@bar($i += 1); // #error: only be modified
|
||||
return 0;
|
||||
}
|
||||
@@ -18,8 +18,8 @@ fn void main()
|
||||
int x = 0;
|
||||
@cofefe(x += 1);
|
||||
@cofefe(xx());
|
||||
@cofefe($x += 1);
|
||||
$assert $x == 2;
|
||||
$typeof($x += 1) xx;
|
||||
$assert $x == 1;
|
||||
@cofefe(y += 1); // #error: 'y' could not be found
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user