mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- !!foo now works same as as ! ! foo.
- Incorrectly allowed getting pointer to a macro #2049.
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
- Order of attribute declaration is changed for `alias`.
|
||||
- Added `LANGUAGE_DEV_VERSION` env constant.
|
||||
- Rename `anyfault` -> `fault`.
|
||||
- `!!foo` now works same as as `! ! foo`.
|
||||
|
||||
### Fixes
|
||||
- Fix address sanitizer to work on MachO targets (e.g. MacOS).
|
||||
@@ -48,6 +49,7 @@
|
||||
- Crash when trying to convert a struct slice to a vector #2039.
|
||||
- Crash resolving a method on `Foo[2]` when `Foo` is distinct #2042.
|
||||
- Bug due to missing cast when doing `$i[$x] = $z`.
|
||||
- Incorrectly allowed getting pointer to a macro #2049.
|
||||
|
||||
### Stdlib changes
|
||||
- `new_*` functions in general moved to version without `new_` prefix.
|
||||
|
||||
@@ -239,6 +239,7 @@ UnaryOp unary_op[TOKEN_LAST + 1] = {
|
||||
[TOKEN_AND] = UNARYOP_TADDR,
|
||||
[TOKEN_BIT_NOT] = UNARYOP_BITNEG,
|
||||
[TOKEN_BANG] = UNARYOP_NOT,
|
||||
[TOKEN_BANGBANG] = UNARYOP_NOT,
|
||||
[TOKEN_MINUS] = UNARYOP_NEG,
|
||||
[TOKEN_PLUS] = UNARYOP_PLUS,
|
||||
[TOKEN_PLUSPLUS] = UNARYOP_INC,
|
||||
|
||||
@@ -701,15 +701,21 @@ static Expr *parse_unary_expr(ParseContext *c, Expr *left)
|
||||
{
|
||||
ASSERT(!left && "Did not expect a left hand side!");
|
||||
|
||||
bool is_bangbang = tok_is(c, TOKEN_BANGBANG);
|
||||
Expr *unary = EXPR_NEW_TOKEN(EXPR_UNARY);
|
||||
unary->unary_expr.operator = unaryop_from_token(c->tok);
|
||||
advance(c);
|
||||
Expr *right_side = parse_precedence(c, PREC_UNARY);
|
||||
|
||||
CHECK_EXPR_OR_RET(right_side);
|
||||
|
||||
unary->unary_expr.expr = right_side;
|
||||
RANGE_EXTEND_PREV(unary);
|
||||
if (is_bangbang)
|
||||
{
|
||||
Expr *outer = expr_new_expr(EXPR_UNARY, unary);
|
||||
outer->unary_expr = (ExprUnary) { .expr = unary, .operator = UNARYOP_NOT };
|
||||
return outer;
|
||||
}
|
||||
return unary;
|
||||
}
|
||||
|
||||
@@ -757,7 +763,7 @@ static Expr *parse_ternary_expr(ParseContext *c, Expr *left_side)
|
||||
|
||||
// If we have no expression following *or* it is a '!' followed by no expression
|
||||
// in this case it's an optional expression.
|
||||
if (!rules[c->tok].prefix || (c->tok == TOKEN_BANG && !rules[peek(c)].prefix))
|
||||
if (!rules[c->tok].prefix || ((c->tok == TOKEN_BANG || c->tok == TOKEN_BANGBANG) && !rules[peek(c)].prefix))
|
||||
{
|
||||
expr->expr_kind = EXPR_OPTIONAL;
|
||||
expr->inner_expr = left_side;
|
||||
@@ -1958,7 +1964,7 @@ ParseRule rules[TOKEN_EOF + 1] = {
|
||||
[TOKEN_PLUSPLUS] = { parse_unary_expr, parse_post_unary, PREC_CALL },
|
||||
[TOKEN_MINUSMINUS] = { parse_unary_expr, parse_post_unary, PREC_CALL },
|
||||
[TOKEN_LPAREN] = { parse_grouping_expr, parse_call_expr, PREC_CALL },
|
||||
[TOKEN_BANGBANG] = { NULL, parse_force_unwrap_expr, PREC_CALL },
|
||||
[TOKEN_BANGBANG] = { parse_unary_expr, parse_force_unwrap_expr, PREC_CALL },
|
||||
[TOKEN_LBRACKET] = { NULL, parse_subscript_expr, PREC_CALL },
|
||||
[TOKEN_MINUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
|
||||
[TOKEN_PLUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
|
||||
|
||||
@@ -7193,12 +7193,16 @@ static const char *sema_addr_check_may_take(Expr *inner)
|
||||
case EXPR_ACCESS_RESOLVED:
|
||||
{
|
||||
Decl *decl = inner->access_resolved_expr.ref;
|
||||
if (decl->decl_kind == DECL_FUNC)
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
if (decl->func_decl.attr_interface_method) return NULL;
|
||||
return "Taking the address of a method should be done through the type e.g. '&Foo.method' not through the value.";
|
||||
case DECL_FUNC:
|
||||
if (decl->func_decl.attr_interface_method) return NULL;
|
||||
return "Taking the address of a method should be done through the type e.g. '&Foo.method' not through the value.";
|
||||
case DECL_MACRO:
|
||||
return "It's not possible to take the address of a macro.";
|
||||
default:
|
||||
return sema_addr_check_may_take(inner->access_resolved_expr.parent);
|
||||
}
|
||||
return sema_addr_check_may_take(inner->access_resolved_expr.parent);
|
||||
}
|
||||
case EXPR_SUBSCRIPT_ADDR:
|
||||
return NULL;
|
||||
|
||||
37
test/test_suite/expressions/negneg.c3t
Normal file
37
test/test_suite/expressions/negneg.c3t
Normal file
@@ -0,0 +1,37 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
import std;
|
||||
fn void test(bool b) {}
|
||||
fn void main()
|
||||
{
|
||||
int a;
|
||||
test(!a);
|
||||
test(!!a);
|
||||
test(!!!a);
|
||||
test(!!!!a);
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
%a = alloca i32, align 4
|
||||
store i32 0, ptr %a, align 4
|
||||
%0 = load i32, ptr %a, align 4
|
||||
%i2nb = icmp eq i32 %0, 0
|
||||
%1 = zext i1 %i2nb to i8
|
||||
call void @test.test(i8 zeroext %1)
|
||||
%2 = load i32, ptr %a, align 4
|
||||
%i2b = icmp ne i32 %2, 0
|
||||
%3 = zext i1 %i2b to i8
|
||||
call void @test.test(i8 zeroext %3)
|
||||
%4 = load i32, ptr %a, align 4
|
||||
%i2nb1 = icmp eq i32 %4, 0
|
||||
%5 = zext i1 %i2nb1 to i8
|
||||
call void @test.test(i8 zeroext %5)
|
||||
%6 = load i32, ptr %a, align 4
|
||||
%i2b2 = icmp ne i32 %6, 0
|
||||
%7 = zext i1 %i2b2 to i8
|
||||
call void @test.test(i8 zeroext %7)
|
||||
ret void
|
||||
}
|
||||
28
test/test_suite/macros/address_of_macro.c3
Normal file
28
test/test_suite/macros/address_of_macro.c3
Normal file
@@ -0,0 +1,28 @@
|
||||
import std::io;
|
||||
// Issue #2049
|
||||
struct Container
|
||||
{
|
||||
int[] items;
|
||||
}
|
||||
|
||||
macro int Container.get(&this, usz i) @operator([])
|
||||
{
|
||||
return this.items[i];
|
||||
}
|
||||
|
||||
fn int Container.get2(&this, usz i)
|
||||
{
|
||||
return this.items[i];
|
||||
}
|
||||
|
||||
alias ProcGetItem = fn int(usz);
|
||||
fn void process(int input, ProcGetItem getter)
|
||||
{
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
Container c = { .items = { 2, 3, 4, 5 } };
|
||||
process(10, &c.get); // #error: It's not possible to take the address
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user