llvm/mlir/test/IR/invalid.mlir

// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics

// Check different error cases.

func.func @bad_branch() {
^bb12:
  cf.br ^missing  // expected-error {{reference to an undefined block}}
}

// -----

func.func @block_redef() {
^bb42:
  return
^bb42:        // expected-error {{redefinition of block '^bb42'}}
  return
}

// -----

func.func @no_terminator() {   // expected-error {{empty block: expect at least a terminator}}
^bb40:
  return
^bb41:
^bb42:
  return
}

// -----

func.func @block_no_rparen() {
^bb42 (%bb42 : i32: // expected-error {{expected ')'}}
  return
}

// -----

func.func @block_arg_no_ssaid() {
^bb42 (i32): // expected-error {{expected SSA operand}}
  return
}

// -----

func.func @block_arg_no_type() {
^bb42 (%0): // expected-error {{expected ':' and type for SSA operand}}
  return
}

// -----

func.func @block_arg_no_close_paren() {
^bb42:
  cf.br ^bb2( // expected-error {{expected ':'}}
  return
}

// -----

func.func @block_first_has_predecessor() {
// expected-error@-1 {{entry block of region may not have predecessors}}
^bb42:
  cf.br ^bb43
^bb43:
  cf.br ^bb42
}

// -----

func.func @no_return() {
  %x = arith.constant 0 : i32
  %y = arith.constant 1 : i32  // expected-error {{block with no terminator}}
}

// -----

func.func @no_terminator() {
  cf.br ^bb1
^bb1:
  %x = arith.constant 0 : i32
  %y = arith.constant 1 : i32  // expected-error {{block with no terminator}}
}

// -----

func.func @no_block_arg_enclosing_parens() {
^bb %x: i32 : // expected-error {{expected ':' after block name}}
  return
}

// -----

func.func @bad_op_type() {
^bb40:
  "foo"() : i32  // expected-error {{expected function type}}
  return
}
// -----

func.func @no_terminator() {
^bb40:
  "foo"() : ()->()
  ""() : ()->()  // expected-error {{empty operation name is invalid}}
  return
}

// -----

func.func @non_operation() {
  test.asd   // expected-error {{custom op 'test.asd' is unknown}}
}

// -----

func.func @unknown_dialect_operation() {
  // expected-error@below {{Dialect `foo' not found for custom op 'foo.asd'}}
  // expected-note-re@below {{Registered dialects:{{.*}} test{{.*}}}}
  foo.asd
}

// -----

func.func @non_operation() {
  // expected-error@+1 {{custom op 'asd' is unknown (tried 'func.asd' as well)}}
  asd
}

// -----

func.func @test() {
^bb40:
  %1 = "foo"() : (i32)->i64 // expected-error {{expected 0 operand types but had 1}}
  return
}

// -----

func.func @redef() {
^bb42:
  %x = "xxx"(){index = 0} : ()->i32 // expected-note {{previously defined here}}
  %x = "xxx"(){index = 0} : ()->i32 // expected-error {{redefinition of SSA value '%x'}}
  return
}

// -----

func.func @undef() {
^bb42:
  %x = "xxx"(%y) : (i32)->i32   // expected-error {{use of undeclared SSA value}}
  return
}

// -----

func.func @malformed_type(%a : intt) { // expected-error {{expected non-function type}}
}

// -----

func.func @argError() {
^bb1(%a: i64):  // expected-note {{previously defined here}}
  cf.br ^bb2
^bb2(%a: i64):  // expected-error{{redefinition of SSA value '%a'}}
  return
}

// -----

func.func @br_mismatch() {
^bb0:
  %0:2 = "foo"() : () -> (i1, i17)
  // expected-error @+1 {{branch has 2 operands for successor #0, but target block has 1}}
  cf.br ^bb1(%0#1, %0#0 : i17, i1)

^bb1(%x: i17):
  return
}

// -----

func.func @succ_arg_type_mismatch() {
^bb0:
  %0 = "getBool"() : () -> i1
  // expected-error @+1 {{type mismatch for bb argument #0 of successor #0}}
  cf.br ^bb1(%0 : i1)

^bb1(%x: i32):
  return
}


// -----

func.func @condbr_notbool() {
^bb0:
  %a = "foo"() : () -> i32 // expected-note {{prior use here}}
  cf.cond_br %a, ^bb0, ^bb0 // expected-error {{use of value '%a' expects different type than prior uses: 'i1' vs 'i32'}}
}

// -----

func.func @condbr_badtype() {
^bb0:
  %c = "foo"() : () -> i1
  %a = "foo"() : () -> i32
  cf.cond_br %c, ^bb0(%a, %a : i32, ^bb0) // expected-error {{expected non-function type}}
}

// -----

func.func @condbr_a_bb_is_not_a_type() {
^bb0:
  %c = "foo"() : () -> i1
  %a = "foo"() : () -> i32
  cf.cond_br %c, ^bb0(%a, %a : i32, i32), i32 // expected-error {{expected block name}}
}

// -----

func.func @successors_in_non_terminator(%a : i32, %b : i32) {
  %c = "arith.addi"(%a, %b)[^bb1] : () -> () // expected-error {{successors in non-terminator}}
^bb1:
  return
}

// -----

func.func @undef() {
^bb0:
  %x = "xxx"(%y) : (i32)->i32   // expected-error {{use of undeclared SSA value name}}
  return
}

// -----

func.func @undef() {
  %x = "xxx"(%y) : (i32)->i32   // expected-error {{use of undeclared SSA value name}}
  return
}

// -----

func.func @duplicate_induction_var() {
  affine.for %i = 1 to 10 {   // expected-note {{previously referenced here}}
    affine.for %i = 1 to 10 { // expected-error {{region entry argument '%i' is already in use}}
    }
  }
  return
}

// -----

func.func @name_scope_failure() {
  affine.for %i = 1 to 10 {
  }
  "xxx"(%i) : (index)->()   // expected-error {{use of undeclared SSA value name}}
  return
}

// -----

func.func @dominance_failure() {
^bb0:
  "foo"(%x) : (i32) -> ()    // expected-error {{operand #0 does not dominate this use}}
  cf.br ^bb1
^bb1:
  %x = "bar"() : () -> i32    // expected-note {{operand defined here (op in the same region)}}
  return
}

// -----

func.func @dominance_failure() {
^bb0:
  "foo"(%x) : (i32) -> ()    // expected-error {{operand #0 does not dominate this use}}
  %x = "bar"() : () -> i32    // expected-note {{operand defined here (op in the same block)}}
  cf.br ^bb1
^bb1:
  return
}

// -----

func.func @dominance_failure() {
  "foo"() ({
    "foo"(%x) : (i32) -> ()    // expected-error {{operand #0 does not dominate this use}}
  }) : () -> ()
  %x = "bar"() : () -> i32    // expected-note {{operand defined here (op in a parent region)}}
  return
}

// -----

func.func @dominance_failure() {  //  expected-note {{operand defined as a block argument (block #1 in the same region)}}
^bb0:
  cf.br ^bb1(%x : i32)    // expected-error {{operand #0 does not dominate this use}}
^bb1(%x : i32):
  return
}

// -----

func.func @dominance_failure() {  //  expected-note {{operand defined as a block argument (block #1 in a parent region)}}
^bb0:
  %f = "foo"() ({
    "foo"(%x) : (i32) -> ()    // expected-error {{operand #0 does not dominate this use}}
  }) : () -> (i32)
  cf.br ^bb1(%f : i32)
^bb1(%x : i32):
  return
}

// -----

// expected-error@+1 {{expected three consecutive dots for an ellipsis}}
func.func @malformed_ellipsis_one(.)

// -----

// expected-error@+1 {{expected three consecutive dots for an ellipsis}}
func.func @malformed_ellipsis_two(..)

// -----

func.func private @redef()  // expected-note {{see existing symbol definition here}}
func.func private @redef()  // expected-error {{redefinition of symbol named 'redef'}}

// -----

func.func @calls(%arg0: i32) {
  // expected-error@+1 {{expected non-function type}}
  %z = "casdasda"(%x) : (ppop32) -> i32
}

// -----

// expected-error@+1 {{expected SSA operand}}
func.func @n(){^b(

// -----

// This used to crash the parser, but should just error out by interpreting
// `tensor` as operator rather than as a type.
func.func @f(f32) {
^bb0(%a : f32):
  %18 = arith.cmpi slt, %idx, %idx : index
  tensor<42 x index  // expected-error {{custom op 'tensor' is unknown (tried 'func.tensor' as well)}}
  return
}

// -----

func.func @f(%m : memref<?x?xf32>) {
  affine.for %i0 = 0 to 42 {
    // expected-note@+1 {{previously referenced here}}
    %x = memref.load %m[%i0, %i1] : memref<?x?xf32>
  }
  // expected-error@+1 {{region entry argument '%i1' is already in use}}
  affine.for %i1 = 0 to 42 {
  }
  return
}

// -----

func.func @dialect_type_empty_namespace(!<"">) -> () { // expected-error {{invalid type identifier}}
  return
}

// -----

func.func @dialect_type_missing_greater(!foo<) -> () { // expected-error {{unbalanced '<' character in pretty dialect name}}
  return

// -----

func.func @type_alias_unknown(!unknown_alias) -> () { // expected-error {{undefined symbol alias id 'unknown_alias'}}
  return
}

// -----

// expected-error @+1 {{type names with a '.' are reserved for dialect-defined names}}
!foo.bar = i32

// -----

!missing_eq_alias i32 // expected-error {{expected '=' in type alias definition}}

// -----

!missing_type_alias = // expected-error {{expected non-function type}}

// -----

!redef_alias = i32
!redef_alias = i32 // expected-error {{redefinition of type alias id 'redef_alias'}}

// -----

func.func @invalid_nested_dominance() {
  "test.ssacfg_region"() ({
    // expected-error @+1 {{operand #0 does not dominate this use}}
    "foo.use" (%1) : (i32) -> ()
    cf.br ^bb2

  ^bb2:
    // expected-note @+1 {{operand defined here}}
    %1 = arith.constant 0 : i32
    "foo.yield" () : () -> ()
  }) : () -> ()
  return
}

// -----

// expected-error @+1 {{unbalanced '<' character in pretty dialect name}}
func.func @invalid_unknown_type_dialect_name() -> !invalid.dialect<!x@#]!@#>

// -----

// expected-error @+1 {{expected '<' in tuple type}}
func.func @invalid_tuple_missing_less(tuple i32>)

// -----

// expected-error @+1 {{expected '>' in tuple type}}
func.func @invalid_tuple_missing_greater(tuple<i32)

// -----

// Should not crash because of deletion order here.
func.func @invalid_region_dominance() {
  "foo.use" (%1) : (i32) -> ()
  "foo.region"() ({
    %1 = arith.constant 0 : i32  // This value is used outside of the region.
    "foo.yield" () : () -> ()
  }, {
    // expected-error @+1 {{expected operation name in quotes}}
    %2 = arith.constant 1 i32  // Syntax error causes region deletion.
  }) : () -> ()
  return
}

// -----

// Should not crash because of deletion order here.
func.func @invalid_region_block() {
  "foo.branch"()[^bb2] : () -> ()  // Attempt to jump into the region.

^bb1:
  "foo.region"() ({
    ^bb2:
      "foo.yield"() : () -> ()
  }, {
    // expected-error @+1 {{expected operation name in quotes}}
    %2 = arith.constant 1 i32  // Syntax error causes region deletion.
  }) : () -> ()
}

// -----

// Should not crash because of deletion order here.
func.func @invalid_region_dominance() {
  "foo.use" (%1) : (i32) -> ()
  "foo.region"() ({
    "foo.region"() ({
      %1 = arith.constant 0 : i32  // This value is used outside of the region.
      "foo.yield" () : () -> ()
    }) : () -> ()
  }, {
    // expected-error @+1 {{expected operation name in quotes}}
    %2 = arith.constant 1 i32  // Syntax error causes region deletion.
  }) : () -> ()
  return
}

// -----

func.func @unfinished_region_list() {
  // expected-error@+1 {{expected ')' to end region list}}
  "region"() ({},{},{} : () -> ()
}

// -----

func.func @multi_result_missing_count() {
  // expected-error@+1 {{expected integer number of results}}
  %0: = "foo" () : () -> (i32, i32)
  return
}

// -----

func.func @multi_result_zero_count() {
  // expected-error@+1 {{expected named operation to have at least 1 result}}
  %0:0 = "foo" () : () -> (i32, i32)
  return
}

// -----

func.func @multi_result_invalid_identifier() {
  // expected-error@+1 {{expected valid ssa identifier}}
  %0, = "foo" () : () -> (i32, i32)
  return
}

// -----

func.func @multi_result_mismatch_count() {
  // expected-error@+1 {{operation defines 2 results but was provided 1 to bind}}
  %0:1 = "foo" () : () -> (i32, i32)
  return
}

// -----

func.func @multi_result_mismatch_count() {
  // expected-error@+1 {{operation defines 2 results but was provided 3 to bind}}
  %0, %1, %3 = "foo" () : () -> (i32, i32)
  return
}

// -----

func.func @no_result_with_name() {
  // expected-error@+1 {{cannot name an operation with no results}}
  %0 = "foo" () : () -> ()
  return
}

// -----

func.func @conflicting_names() {
  // expected-note@+1 {{previously defined here}}
  %foo, %bar  = "foo" () : () -> (i32, i32)

  // expected-error@+1 {{redefinition of SSA value '%bar'}}
  %bar, %baz  = "foo" () : () -> (i32, i32)
  return
}

// -----

func.func @ssa_name_missing_eq() {
  // expected-error@+1 {{expected '=' after SSA name}}
  %0:2 "foo" () : () -> (i32, i32)
  return
}

// -----

// expected-error @+1 {{attribute names with a '.' are reserved for dialect-defined names}}
#foo.attr = i32

// -----

func.func @invalid_region_dominance() {
  "test.ssacfg_region"() ({
    // expected-error @+1 {{operand #0 does not dominate this use}}
    "foo.use" (%def) : (i32) -> ()
    "foo.yield" () : () -> ()
  }, {
    // expected-note @+1 {{operand defined here}}
    %def = "foo.def" () : () -> i32
  }) : () -> ()
  return
}

// -----

func.func @invalid_region_dominance() {
  // expected-note @+1 {{operand defined here}}
  %def = "test.ssacfg_region"() ({
    // expected-error @+1 {{operand #0 does not dominate this use}}
    "foo.use" (%def) : (i32) -> ()
    "foo.yield" () : () -> ()
  }) : () -> (i32)
  return
}

// -----

// expected-error @+1 {{unbalanced '<' character in pretty dialect name}}
func.func @bad_arrow(%arg : !unreg.ptr<(i32)->)

// -----

func.func @forward_reference_type_check() -> (i8) {
  cf.br ^bb2

^bb1:
  // expected-note @+1 {{previously used here with type 'i8'}}
  return %1 : i8

^bb2:
  // expected-error @+1 {{definition of SSA value '%1#0' has type 'f32'}}
  %1 = "bar"() : () -> (f32)
  cf.br ^bb1
}

// -----

func.func @dominance_error_in_unreachable_op() -> i1 {
  %c = arith.constant false
  return %c : i1
^bb0:
  "test.ssacfg_region" () ({ // unreachable
    ^bb1:
// expected-error @+1 {{operand #0 does not dominate this use}}
      %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
      cf.br ^bb4
    ^bb2:
      cf.br ^bb2
    ^bb4:
      %1 = "foo"() : ()->i64   // expected-note {{operand defined here}}
  }) : () -> ()
  return %c : i1
}

// -----

func.func @invalid_region_dominance_with_dominance_free_regions() {
  test.graph_region {
    "foo.use" (%1) : (i32) -> ()
    "foo.region"() ({
      %1 = arith.constant 0 : i32  // This value is used outside of the region.
      "foo.yield" () : () -> ()
    }, {
      // expected-error @+1 {{expected operation name in quotes}}
      %2 = arith.constant 1 i32  // Syntax error causes region deletion.
    }) : () -> ()
  }
  return
}

// -----

// expected-error@+1 {{expected valid attribute name}}
"t"(){""}

// -----

// This makes sure we emit an error at the end of the correct line, the : is
// expected at the end of foo, not on the return line.
func.func @error_at_end_of_line() {
  // expected-error@+1 {{expected ':' followed by operation type}}
  %0 = "foo"()
  return
}

// -----

// This makes sure we emit an error at the end of the correct line, the : is
// expected at the end of foo, not on the return line.
func.func @error_at_end_of_line() {
  %0 = "foo"()
  // expected-error@-1 {{expected ':' followed by operation type}}

  // This is a comment and so is the thing above.
  return
}

// -----

// This makes sure we emit an error at the end of the correct line, the : is
// expected at the end of foo, not on the return line.
// This shows that it backs up to before the comment.
func.func @error_at_end_of_line() {
  %0 = "foo"()  // expected-error {{expected ':' followed by operation type}}
  return
}

// -----

@foo   // expected-error {{expected operation name in quotes}}