Made function and namespace nodes typed to remove a crash (#3285)

Bug found by fuzzing. Problem was untyped SemIR nodes had an invalid
type id, which was retrieved by `HandlePrefixOperator` and then passed
to `context.GetUnqualifiedType`, ultimately performing an invalid access
in `semantics_ir_->GetNode`.

We prefer to make a placeholder type for functions and namespaces to
remove the need for checking for the untyped case everywhere. Eventually
functions will have their own types, but this approach will be needed
for namespaces (and perhaps other non-first-class entities like unbound
methods and interface members) long term.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
josh11b
2023-10-12 21:14:16 +00:00
committed by GitHub
co-authored by Richard Smith
parent 6ba8712fbd
commit 8d0831f431
133 changed files with 418 additions and 357 deletions
+3 -3
View File
@@ -13,8 +13,8 @@ fn Main() {
}
// CHECK:STDOUT: file "empty_struct.carbon" {
// CHECK:STDOUT: %Echo = fn_decl @Echo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Echo: <function> = fn_decl @Echo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Echo(%a: {}) -> {} {
@@ -25,7 +25,7 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Echo.ref = name_reference_untyped "Echo", package.%Echo
// CHECK:STDOUT: %Echo.ref: <function> = name_reference "Echo", package.%Echo
// CHECK:STDOUT: %.loc12_9.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc12_9.2: {} = struct_value %.loc12_9.1, ()
// CHECK:STDOUT: %.loc12_7: init {} = call @Echo(%.loc12_9.2)
+3 -3
View File
@@ -13,8 +13,8 @@ fn Main() {
}
// CHECK:STDOUT: file "empty_tuple.carbon" {
// CHECK:STDOUT: %Echo = fn_decl @Echo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Echo: <function> = fn_decl @Echo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Echo(%a: ()) -> () {
@@ -25,7 +25,7 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Echo.ref = name_reference_untyped "Echo", package.%Echo
// CHECK:STDOUT: %Echo.ref: <function> = name_reference "Echo", package.%Echo
// CHECK:STDOUT: %.loc12_9.1: () = tuple_literal ()
// CHECK:STDOUT: %.loc12_9.2: () = tuple_value %.loc12_9.1, ()
// CHECK:STDOUT: %.loc12_7: init () = call @Echo(%.loc12_9.2)
@@ -15,7 +15,7 @@ fn Run() {
}
// CHECK:STDOUT: file "fail_not_callable.carbon" {
// CHECK:STDOUT: %Run = fn_decl @Run
// CHECK:STDOUT: %Run: <function> = fn_decl @Run
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
@@ -56,10 +56,10 @@ fn Main() {
}
// CHECK:STDOUT: file "fail_param_count.carbon" {
// CHECK:STDOUT: %Run0 = fn_decl @Run0
// CHECK:STDOUT: %Run1 = fn_decl @Run1
// CHECK:STDOUT: %Run2 = fn_decl @Run2
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Run0: <function> = fn_decl @Run0
// CHECK:STDOUT: %Run1: <function> = fn_decl @Run1
// CHECK:STDOUT: %Run2: <function> = fn_decl @Run2
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run0() {
@@ -79,18 +79,18 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Run0.ref.loc18 = name_reference_untyped "Run0", package.%Run0
// CHECK:STDOUT: %Run0.ref.loc18: <function> = name_reference "Run0", package.%Run0
// CHECK:STDOUT: %.loc18_8: i32 = int_literal 1
// CHECK:STDOUT: %.loc18_7: type = tuple_type ()
// CHECK:STDOUT: %Run0.ref.loc25 = name_reference_untyped "Run0", package.%Run0
// CHECK:STDOUT: %Run0.ref.loc25: <function> = name_reference "Run0", package.%Run0
// CHECK:STDOUT: %.loc25_8: i32 = int_literal 0
// CHECK:STDOUT: %.loc25_11: i32 = int_literal 1
// CHECK:STDOUT: %Run1.ref.loc33 = name_reference_untyped "Run1", package.%Run1
// CHECK:STDOUT: %Run1.ref.loc40 = name_reference_untyped "Run1", package.%Run1
// CHECK:STDOUT: %Run1.ref.loc33: <function> = name_reference "Run1", package.%Run1
// CHECK:STDOUT: %Run1.ref.loc40: <function> = name_reference "Run1", package.%Run1
// CHECK:STDOUT: %.loc40_8: i32 = int_literal 0
// CHECK:STDOUT: %.loc40_11: i32 = int_literal 1
// CHECK:STDOUT: %Run2.ref.loc48 = name_reference_untyped "Run2", package.%Run2
// CHECK:STDOUT: %Run2.ref.loc55 = name_reference_untyped "Run2", package.%Run2
// CHECK:STDOUT: %Run2.ref.loc48: <function> = name_reference "Run2", package.%Run2
// CHECK:STDOUT: %Run2.ref.loc55: <function> = name_reference "Run2", package.%Run2
// CHECK:STDOUT: %.loc55: i32 = int_literal 0
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -17,8 +17,8 @@ fn F() {
}
// CHECK:STDOUT: file "fail_param_type.carbon" {
// CHECK:STDOUT: %G = fn_decl @G
// CHECK:STDOUT: %F = fn_decl @F
// CHECK:STDOUT: %G: <function> = fn_decl @G
// CHECK:STDOUT: %F: <function> = fn_decl @F
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G(%a: i32) {
@@ -28,7 +28,7 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %G.ref = name_reference_untyped "G", package.%G
// CHECK:STDOUT: %G.ref: <function> = name_reference "G", package.%G
// CHECK:STDOUT: %.loc16_5: f64 = real_literal 10e-1
// CHECK:STDOUT: %.loc16_4: type = tuple_type ()
// CHECK:STDOUT: return
@@ -14,8 +14,8 @@ fn Run() {
}
// CHECK:STDOUT: file "fail_return_type_mismatch.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Run = fn_decl @Run
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Run: <function> = fn_decl @Run
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo() -> f64 {
@@ -27,7 +27,7 @@ fn Run() {
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %x: ref i32 = var "x"
// CHECK:STDOUT: %Foo.ref = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc13: init f64 = call @Foo()
// CHECK:STDOUT: assign %x, <error>
// CHECK:STDOUT: return
+3 -3
View File
@@ -13,8 +13,8 @@ fn Main() {
}
// CHECK:STDOUT: file "i32.carbon" {
// CHECK:STDOUT: %Echo = fn_decl @Echo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Echo: <function> = fn_decl @Echo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Echo(%a: i32) -> i32 {
@@ -26,7 +26,7 @@ fn Main() {
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %b: ref i32 = var "b"
// CHECK:STDOUT: %Echo.ref = name_reference_untyped "Echo", package.%Echo
// CHECK:STDOUT: %Echo.ref: <function> = name_reference "Echo", package.%Echo
// CHECK:STDOUT: %.loc12_21: i32 = int_literal 1
// CHECK:STDOUT: %.loc12_20: init i32 = call @Echo(%.loc12_21)
// CHECK:STDOUT: assign %b, %.loc12_20
@@ -12,8 +12,8 @@ fn Main() {
}
// CHECK:STDOUT: file "more_param_ir.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32, %b: i32, %c: i32) {
@@ -23,7 +23,7 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Foo.ref = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc11_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc11_11: i32 = int_literal 2
// CHECK:STDOUT: %.loc11_9: i32 = add %.loc11_7, %.loc11_11
+3 -3
View File
@@ -11,8 +11,8 @@ fn Main() {
}
// CHECK:STDOUT: file "params_one.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32) {
@@ -22,7 +22,7 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Foo.ref = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc10_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_6.1: type = tuple_type ()
// CHECK:STDOUT: %.loc10_6.2: init () = call @Foo(%.loc10_7)
@@ -12,8 +12,8 @@ fn Main() {
}
// CHECK:STDOUT: file "params_one_comma.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32) {
@@ -23,11 +23,11 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Foo.ref.loc10 = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref.loc10: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc10_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_6.1: type = tuple_type ()
// CHECK:STDOUT: %.loc10_6.2: init () = call @Foo(%.loc10_7)
// CHECK:STDOUT: %Foo.ref.loc11 = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref.loc11: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc11_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc11_6: init () = call @Foo(%.loc11_7)
// CHECK:STDOUT: return
+3 -3
View File
@@ -11,8 +11,8 @@ fn Main() {
}
// CHECK:STDOUT: file "params_two.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32, %b: i32) {
@@ -22,7 +22,7 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Foo.ref = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc10_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_10: i32 = int_literal 2
// CHECK:STDOUT: %.loc10_6.1: type = tuple_type ()
@@ -12,8 +12,8 @@ fn Main() {
}
// CHECK:STDOUT: file "params_two_comma.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32, %b: i32) {
@@ -23,12 +23,12 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Foo.ref.loc10 = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref.loc10: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc10_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc10_10: i32 = int_literal 2
// CHECK:STDOUT: %.loc10_6.1: type = tuple_type ()
// CHECK:STDOUT: %.loc10_6.2: init () = call @Foo(%.loc10_7, %.loc10_10)
// CHECK:STDOUT: %Foo.ref.loc11 = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref.loc11: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc11_7: i32 = int_literal 1
// CHECK:STDOUT: %.loc11_10: i32 = int_literal 2
// CHECK:STDOUT: %.loc11_6: init () = call @Foo(%.loc11_7, %.loc11_10)
+3 -3
View File
@@ -11,8 +11,8 @@ fn Main() {
}
// CHECK:STDOUT: file "params_zero.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo() {
@@ -22,7 +22,7 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Main() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Foo.ref = name_reference_untyped "Foo", package.%Foo
// CHECK:STDOUT: %Foo.ref: <function> = name_reference "Foo", package.%Foo
// CHECK:STDOUT: %.loc10_6.1: type = tuple_type ()
// CHECK:STDOUT: %.loc10_6.2: init () = call @Foo()
// CHECK:STDOUT: return
@@ -12,8 +12,8 @@ fn Main() {
}
// CHECK:STDOUT: file "return_implicit.carbon" {
// CHECK:STDOUT: %MakeImplicitEmptyTuple = fn_decl @MakeImplicitEmptyTuple
// CHECK:STDOUT: %Main = fn_decl @Main
// CHECK:STDOUT: %MakeImplicitEmptyTuple: <function> = fn_decl @MakeImplicitEmptyTuple
// CHECK:STDOUT: %Main: <function> = fn_decl @Main
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @MakeImplicitEmptyTuple() {
@@ -26,7 +26,7 @@ fn Main() {
// CHECK:STDOUT: %.loc11_11.1: type = tuple_type ()
// CHECK:STDOUT: %.loc11_11.2: () = tuple_literal ()
// CHECK:STDOUT: %b: ref () = var "b"
// CHECK:STDOUT: %MakeImplicitEmptyTuple.ref = name_reference_untyped "MakeImplicitEmptyTuple", package.%MakeImplicitEmptyTuple
// CHECK:STDOUT: %MakeImplicitEmptyTuple.ref: <function> = name_reference "MakeImplicitEmptyTuple", package.%MakeImplicitEmptyTuple
// CHECK:STDOUT: %.loc11_37: init () = call @MakeImplicitEmptyTuple()
// CHECK:STDOUT: assign %b, %.loc11_37
// CHECK:STDOUT: return
@@ -9,15 +9,15 @@ fn F();
fn G() { F(); }
// CHECK:STDOUT: file "simple.carbon" {
// CHECK:STDOUT: %F = fn_decl @F
// CHECK:STDOUT: %G = fn_decl @G
// CHECK:STDOUT: %F: <function> = fn_decl @F
// CHECK:STDOUT: %G: <function> = fn_decl @G
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref = name_reference_untyped "F", package.%F
// CHECK:STDOUT: %F.ref: <function> = name_reference "F", package.%F
// CHECK:STDOUT: %.loc9_11.1: type = tuple_type ()
// CHECK:STDOUT: %.loc9_11.2: init () = call @F()
// CHECK:STDOUT: return
@@ -13,7 +13,7 @@
fn Bar(a: i32, a: i32) {}
// CHECK:STDOUT: file "fail_param_name_conflict.carbon" {
// CHECK:STDOUT: %Bar = fn_decl @Bar
// CHECK:STDOUT: %Bar: <function> = fn_decl @Bar
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Bar(%a.loc13_8: i32, %a.loc13_16: i32) {
+3 -3
View File
@@ -9,9 +9,9 @@ fn Bar() {}
fn Baz() {}
// CHECK:STDOUT: file "order.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Bar = fn_decl @Bar
// CHECK:STDOUT: %Baz = fn_decl @Baz
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Bar: <function> = fn_decl @Bar
// CHECK:STDOUT: %Baz: <function> = fn_decl @Baz
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo() {
@@ -7,7 +7,7 @@
fn Foo(a: i32) {}
// CHECK:STDOUT: file "params_one.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32) {
@@ -7,7 +7,7 @@
fn Foo(a: i32,) {}
// CHECK:STDOUT: file "params_one_comma.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32) {
@@ -7,7 +7,7 @@
fn Foo(a: i32, b: i32) {}
// CHECK:STDOUT: file "params_two.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32, %b: i32) {
@@ -7,7 +7,7 @@
fn Foo(a: i32, b: i32,) {}
// CHECK:STDOUT: file "params_two_comma.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32, %b: i32) {
@@ -7,7 +7,7 @@
fn Foo() {}
// CHECK:STDOUT: file "params_zero.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo() {
@@ -8,8 +8,8 @@ fn Foo(a: i32) {}
fn Bar(a: i32) {}
// CHECK:STDOUT: file "same_param_name.carbon" {
// CHECK:STDOUT: %Foo = fn_decl @Foo
// CHECK:STDOUT: %Bar = fn_decl @Bar
// CHECK:STDOUT: %Foo: <function> = fn_decl @Foo
// CHECK:STDOUT: %Bar: <function> = fn_decl @Bar
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Foo(%a: i32) {