Browse Source

Add suggestions when trying to take the address the a value from a `for`/`switch` statement

gingerBill 4 years ago
parent
commit
cba0bd30f5
3 changed files with 21 additions and 5 deletions
  1. 11 1
      src/check_expr.cpp
  2. 7 4
      src/check_stmt.cpp
  3. 3 0
      src/entity.cpp

+ 11 - 1
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;
 					}
 				}

+ 7 - 4
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) {

+ 3 - 0
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,