aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-08-23 11:50:02 +0100
committergingerBill <bill@gingerbill.org>2021-08-23 11:50:02 +0100
commitcba0bd30f548c6a757a3ed5fb994380a4a10aa2e (patch)
tree2a531f0d0d4609e84ab5402f6604a1268fc125cf /src
parent276d4b8f0d5c5bcff4b83bab12746dd80e10fc90 (diff)
Add suggestions when trying to take the address the a value from a `for`/`switch` statement
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp12
-rw-r--r--src/check_stmt.cpp11
-rw-r--r--src/entity.cpp3
3 files changed, 21 insertions, 5 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 176685804..329bd0fc9 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1886,7 +1886,17 @@ void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) {
error(op, "Cannot take the pointer address of '%s' which is a swizzle intermediate array value", str);
break;
default:
- error(op, "Cannot take the pointer address of '%s'", str);
+ {
+ begin_error_block();
+ defer (end_error_block());
+ error(op, "Cannot take the pointer address of '%s'", str);
+ if (e != nullptr && (e->flags & EntityFlag_ForValue) != 0) {
+ error_line("\tSuggestion: Did you want to pass the iterable value to the for statement by pointer to get addressable semantics?\n");
+ }
+ if (e != nullptr && (e->flags & EntityFlag_SwitchValue) != 0) {
+ error_line("\tSuggestion: Did you want to pass the value to the switch statement by pointer to get addressable semantics?\n");
+ }
+ }
break;
}
}
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 2e407e6c6..6943f3d97 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1343,6 +1343,7 @@ void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
tag_var->flags |= EntityFlag_Used;
if (!is_reference) {
tag_var->flags |= EntityFlag_Value;
+ tag_var->flags |= EntityFlag_SwitchValue;
}
add_entity(ctx, ctx->scope, lhs, tag_var);
add_entity_use(ctx, lhs, tag_var);
@@ -1921,6 +1922,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
auto lhs = slice_make<Ast *>(temporary_allocator(), rhs.count);
slice_copy(&lhs, rs->vals);
+ isize addressable_index = cast(isize)is_map;
+
for_array(i, rhs) {
if (lhs[i] == nullptr) {
continue;
@@ -1940,11 +1943,11 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
if (found == nullptr) {
entity = alloc_entity_variable(ctx->scope, token, type, EntityState_Resolved);
entity->flags |= EntityFlag_Value;
- if (use_by_reference_for_value) {
- if (i == 0 && !is_map) {
- entity->flags &= ~EntityFlag_Value;
- } else if (i == 1 && is_map) {
+ if (i == addressable_index) {
+ if (use_by_reference_for_value) {
entity->flags &= ~EntityFlag_Value;
+ } else {
+ entity->flags |= EntityFlag_ForValue;
}
}
if (is_soa) {
diff --git a/src/entity.cpp b/src/entity.cpp
index 02b5f4a75..8343ba557 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -69,6 +69,9 @@ enum EntityFlag : u64 {
EntityFlag_Lazy = 1ull<<27, // Lazily type checked
+ EntityFlag_ForValue = 1ull<<28,
+ EntityFlag_SwitchValue = 1ull<<29,
+
EntityFlag_Test = 1ull<<30,
EntityFlag_Overridden = 1ull<<63,