Handle arrow operator (#3768)

This change implements the check behavior for the arrow operator.

`ptr->Foo()` is rewritten as `(*ptr).Foo()` and `ptr->(X.y)` is
rewritten as `(*ptr).(X.y)`
This commit is contained in:
CJ Johnson
2024-03-18 17:40:00 +00:00
committed by GitHub
parent 4421a75c36
commit d0e8afc51b
17 changed files with 365 additions and 89 deletions
@@ -9,14 +9,26 @@ fn Deref(n: i32) {
// CHECK:STDERR: *n;
// CHECK:STDERR: ^
*n;
// CHECK:STDERR: fail_deref_not_pointer.carbon:[[@LINE+3]]:4: ERROR: Cannot apply `->` operator to non-pointer type `i32`.
// CHECK:STDERR: n->foo;
// CHECK:STDERR: ^~
n->foo;
// CHECK:STDERR: fail_deref_not_pointer.carbon:[[@LINE+3]]:3: ERROR: Cannot dereference operand of non-pointer type `()`.
// CHECK:STDERR: *();
// CHECK:STDERR: ^
*();
// CHECK:STDERR: fail_deref_not_pointer.carbon:[[@LINE+3]]:5: ERROR: Cannot apply `->` operator to non-pointer type `()`.
// CHECK:STDERR: ()->foo;
// CHECK:STDERR: ^~
()->foo;
// CHECK:STDERR: fail_deref_not_pointer.carbon:[[@LINE+3]]:3: ERROR: Cannot dereference operand of non-pointer type `{}`.
// CHECK:STDERR: *{};
// CHECK:STDERR: ^
*{};
// CHECK:STDERR: fail_deref_not_pointer.carbon:[[@LINE+3]]:5: ERROR: Cannot apply `->` operator to non-pointer type `{}`.
// CHECK:STDERR: {}->foo;
// CHECK:STDERR: ^~
{}->foo;
}
// CHECK:STDOUT: --- fail_deref_not_pointer.carbon
@@ -40,16 +52,26 @@ fn Deref(n: i32) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Deref(%n: i32) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %n.ref: i32 = name_ref n, %n
// CHECK:STDOUT: %.loc11: ref <error> = deref %n.ref
// CHECK:STDOUT: %.loc15_5.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc15_5.2: () = tuple_value () [template = constants.%.2]
// CHECK:STDOUT: %.loc15_5.3: () = converted %.loc15_5.1, %.loc15_5.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc15_3: ref <error> = deref %.loc15_5.3
// CHECK:STDOUT: %.loc19_5.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc19_5.2: {} = struct_value () [template = constants.%.4]
// CHECK:STDOUT: %.loc19_5.3: {} = converted %.loc19_5.1, %.loc19_5.2 [template = constants.%.4]
// CHECK:STDOUT: %n.ref.loc11: i32 = name_ref n, %n
// CHECK:STDOUT: %.loc11: ref <error> = deref %n.ref.loc11
// CHECK:STDOUT: %n.ref.loc15: i32 = name_ref n, %n
// CHECK:STDOUT: %.loc15: ref <error> = deref %n.ref.loc15
// CHECK:STDOUT: %.loc19_5.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc19_5.2: () = tuple_value () [template = constants.%.2]
// CHECK:STDOUT: %.loc19_5.3: () = converted %.loc19_5.1, %.loc19_5.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc19_3: ref <error> = deref %.loc19_5.3
// CHECK:STDOUT: %.loc23_4.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc23_4.2: () = tuple_value () [template = constants.%.2]
// CHECK:STDOUT: %.loc23_4.3: () = converted %.loc23_4.1, %.loc23_4.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc23_5: ref <error> = deref %.loc23_4.3
// CHECK:STDOUT: %.loc27_5.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc27_5.2: {} = struct_value () [template = constants.%.4]
// CHECK:STDOUT: %.loc27_5.3: {} = converted %.loc27_5.1, %.loc27_5.2 [template = constants.%.4]
// CHECK:STDOUT: %.loc27_3: ref <error> = deref %.loc27_5.3
// CHECK:STDOUT: %.loc31_4.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc31_4.2: {} = struct_value () [template = constants.%.4]
// CHECK:STDOUT: %.loc31_4.3: {} = converted %.loc31_4.1, %.loc31_4.2 [template = constants.%.4]
// CHECK:STDOUT: %.loc31_5: ref <error> = deref %.loc31_4.3
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: