mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
* Require parenthesized assignment expressions in condition of 'if' statements #2716 * Move analysis to semantic checker and also check while. And update tests and release notes. --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
@@ -249,7 +249,7 @@ fn JsonTokenType? advance(JsonContext* context) @local
|
|||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
while WS: (c = read_next(context)!)
|
while WS: ((c = read_next(context)!))
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@@ -272,12 +272,12 @@ fn JsonTokenType? advance(JsonContext* context) @local
|
|||||||
while COMMENT: (true)
|
while COMMENT: (true)
|
||||||
{
|
{
|
||||||
// Skip to */
|
// Skip to */
|
||||||
while (c = read_next(context)!)
|
while ((c = read_next(context)!))
|
||||||
{
|
{
|
||||||
if (c == '\n') context.line++;
|
if (c == '\n') context.line++;
|
||||||
if (c != '*') continue;
|
if (c != '*') continue;
|
||||||
// Skip through all the '*'
|
// Skip through all the '*'
|
||||||
while (c = read_next(context)!)
|
while ((c = read_next(context)!))
|
||||||
{
|
{
|
||||||
if (c == '\n') context.line++;
|
if (c == '\n') context.line++;
|
||||||
if (c != '*') break;
|
if (c != '*') break;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
- Reduced memory usage for backtraces on Linux.
|
- Reduced memory usage for backtraces on Linux.
|
||||||
- On win32 utf-8 console output is now enabled by default in compiled programs
|
- On win32 utf-8 console output is now enabled by default in compiled programs
|
||||||
- Add `$$VERSION` and `$$PRERELEASE` compile time constants.
|
- Add `$$VERSION` and `$$PRERELEASE` compile time constants.
|
||||||
|
- Require () around assignment in conditionals. #2716
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Regression with npot vector in struct triggering an assert #2219.
|
- Regression with npot vector in struct triggering an assert #2219.
|
||||||
|
|||||||
@@ -1192,15 +1192,26 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
|||||||
{
|
{
|
||||||
RETURN_SEMA_ERROR(last->decl_expr->var.init_expr, "The expression needs to be convertible to a boolean.");
|
RETURN_SEMA_ERROR(last->decl_expr->var.init_expr, "The expression needs to be convertible to a boolean.");
|
||||||
}
|
}
|
||||||
|
|
||||||
cast_no_check(last, type_bool, false);
|
cast_no_check(last, type_bool, false);
|
||||||
}
|
}
|
||||||
if (cast_to_bool && expr_is_const_bool(init))
|
if (cast_to_bool && expr_is_const_bool(init))
|
||||||
{
|
{
|
||||||
*result = init->const_expr.b ? COND_TRUE : COND_FALSE;
|
*result = init->const_expr.b ? COND_TRUE : COND_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (cast_to_bool && last->expr_kind == EXPR_BINARY && last->binary_expr.operator >= BINARYOP_ASSIGN && !last->binary_expr.grouped)
|
||||||
|
{
|
||||||
|
if (vec_size(expr->cond_expr) > 1)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(last, "An assignment in the last conditional must be parenthesized - did you mean to use '==' instead?");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(last, "An assignment in a conditional must have an extra parenthesis - did you mean to use '==' instead?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 3a. Check for optional in case of an expression.
|
// 3a. Check for optional in case of an expression.
|
||||||
if (IS_OPTIONAL(last))
|
if (IS_OPTIONAL(last))
|
||||||
|
|||||||
@@ -266,13 +266,13 @@ fn double mathFunc(double x, double y, double z,
|
|||||||
|
|
||||||
|
|
||||||
fn void strcpy(char *s1, char *s2) {
|
fn void strcpy(char *s1, char *s2) {
|
||||||
while (*s1++ = *s2++);
|
while ((*s1++ = *s2++));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void strcat(char *s1, char *s2) {
|
fn void strcat(char *s1, char *s2) {
|
||||||
while (*s1++);
|
while (*s1++);
|
||||||
s1--;
|
s1--;
|
||||||
while (*s1++ = *s2++);
|
while ((*s1++ = *s2++));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int strcmp(char *s1, char *s2) {
|
fn int strcmp(char *s1, char *s2) {
|
||||||
|
|||||||
12
test/test_suite/statements/if_assign.c3
Normal file
12
test/test_suite/statements/if_assign.c3
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
fn void main()
|
||||||
|
{
|
||||||
|
int x = 5;
|
||||||
|
|
||||||
|
if (x = 1) {} // #error: An assignment in a conditional must have an extra parenthesis
|
||||||
|
|
||||||
|
if ((x = 1)) {}
|
||||||
|
|
||||||
|
while (x = 1) {} // #error: An assignment in a conditional must have an extra parenthesis
|
||||||
|
|
||||||
|
while (x = 1, x = 1) {} // #error: An assignment in the last conditional must be parenthesized
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ macro @thing(; @body())
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn void strcpy(char *s1, char *s2) {
|
fn void strcpy(char *s1, char *s2) {
|
||||||
while (*s1++ = *s2++);
|
while ((*s1++ = *s2++));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void main()
|
fn void main()
|
||||||
|
|||||||
Reference in New Issue
Block a user