xref: /llvm-project/mlir/test/mlir-tblgen/op-format-invalid.td (revision 378e1793379c9c63a4265ecf55c47308410ed25d)
1// RUN: mlir-tblgen -gen-op-decls -asmformat-error-is-fatal=false -I %S/../../include %s -o=%t 2>&1 | FileCheck %s
2
3// This file contains tests for the specification of the declarative op format.
4
5include "mlir/IR/OpBase.td"
6include "mlir/Interfaces/InferTypeOpInterface.td"
7
8def TestDialect : Dialect {
9  let name = "test";
10}
11class TestFormat_Op<string fmt, list<Trait> traits = []>
12    : Op<TestDialect, "format_op", traits> {
13  let assemblyFormat = fmt;
14}
15
16//===----------------------------------------------------------------------===//
17// Directives
18//===----------------------------------------------------------------------===//
19
20//===----------------------------------------------------------------------===//
21// attr-dict
22
23// CHECK: error: 'attr-dict' directive not found
24def DirectiveAttrDictInvalidA : TestFormat_Op<[{
25}]>;
26// CHECK: error: 'attr-dict' directive has already been seen
27def DirectiveAttrDictInvalidB : TestFormat_Op<[{
28  attr-dict attr-dict
29}]>;
30// CHECK: error: 'attr-dict' directive has already been seen
31def DirectiveAttrDictInvalidC : TestFormat_Op<[{
32  attr-dict attr-dict-with-keyword
33}]>;
34// CHECK: error: 'attr-dict' directive can only be used as a top-level directive
35def DirectiveAttrDictInvalidD : TestFormat_Op<[{
36  type(attr-dict)
37}]>;
38
39//===----------------------------------------------------------------------===//
40// custom
41
42// CHECK: error: expected '<' before custom directive name
43def DirectiveCustomInvalidA : TestFormat_Op<[{
44  custom(
45}]>;
46// CHECK: error: expected custom directive name identifier
47def DirectiveCustomInvalidB : TestFormat_Op<[{
48  custom<>
49}]>;
50// CHECK: error: expected '>' after custom directive name
51def DirectiveCustomInvalidC : TestFormat_Op<[{
52  custom<MyDirective(
53}]>;
54// CHECK: error: expected '(' before custom directive parameters
55def DirectiveCustomInvalidD : TestFormat_Op<[{
56  custom<MyDirective>)
57}]>;
58// CHECK: error: only variables and types may be used as parameters to a custom directive
59def DirectiveCustomInvalidE : TestFormat_Op<[{
60  custom<MyDirective>(operands)
61}]>;
62// CHECK: error: expected ')' after custom directive parameters
63def DirectiveCustomInvalidF : TestFormat_Op<[{
64  custom<MyDirective>($operand<
65}]>, Arguments<(ins I64:$operand)>;
66// CHECK: error: type directives within a custom directive may only refer to variables
67def DirectiveCustomInvalidH : TestFormat_Op<[{
68  custom<MyDirective>(type(operands))
69}]>;
70
71//===----------------------------------------------------------------------===//
72// functional-type
73
74// CHECK: error: 'functional-type' is only valid as a top-level directive
75def DirectiveFunctionalTypeInvalidA : TestFormat_Op<[{
76  functional-type(functional-type)
77}]>;
78// CHECK: error: expected '(' before argument list
79def DirectiveFunctionalTypeInvalidB : TestFormat_Op<[{
80  functional-type
81}]>;
82// CHECK: error: expected literal, variable, directive, or optional group
83def DirectiveFunctionalTypeInvalidC : TestFormat_Op<[{
84  functional-type(
85}]>;
86// CHECK: error: expected ',' after inputs argument
87def DirectiveFunctionalTypeInvalidD : TestFormat_Op<[{
88  functional-type(operands
89}]>;
90// CHECK: error: expected literal, variable, directive, or optional group
91def DirectiveFunctionalTypeInvalidE : TestFormat_Op<[{
92  functional-type(operands,
93}]>;
94// CHECK: error: expected ')' after argument list
95def DirectiveFunctionalTypeInvalidF : TestFormat_Op<[{
96  functional-type(operands, results
97}]>;
98
99//===----------------------------------------------------------------------===//
100// operands
101
102// CHECK: error: 'operands' directive creates overlap in format
103def DirectiveOperandsInvalidA : TestFormat_Op<[{
104  operands operands
105}]>;
106// CHECK: error: 'operands' directive creates overlap in format
107def DirectiveOperandsInvalidB : TestFormat_Op<[{
108  $operand operands
109}]>, Arguments<(ins I64:$operand)>;
110
111//===----------------------------------------------------------------------===//
112// ref
113
114// CHECK: error: 'ref' is only valid within a `custom` directive
115def DirectiveRefInvalidA : TestFormat_Op<[{
116  ref(type($operand))
117}]>, Arguments<(ins I64:$operand)>;
118
119// CHECK: error: 'ref' of 'type($operand)' is not bound by a prior 'type' directive
120def DirectiveRefInvalidB : TestFormat_Op<[{
121  custom<Foo>(ref(type($operand)))
122}]>, Arguments<(ins I64:$operand)>;
123
124// CHECK: error: 'ref' of 'type(operands)' is not bound by a prior 'type' directive
125def DirectiveRefInvalidC : TestFormat_Op<[{
126  custom<Foo>(ref(type(operands)))
127}]>;
128
129// CHECK: error: 'ref' of 'type($result)' is not bound by a prior 'type' directive
130def DirectiveRefInvalidD : TestFormat_Op<[{
131  custom<Foo>(ref(type($result)))
132}]>, Results<(outs I64:$result)>;
133
134// CHECK: error: 'ref' of 'type(results)' is not bound by a prior 'type' directive
135def DirectiveRefInvalidE : TestFormat_Op<[{
136  custom<Foo>(ref(type(results)))
137}]>;
138
139// CHECK: error: 'ref' of 'successors' is not bound by a prior 'successors' directive
140def DirectiveRefInvalidF : TestFormat_Op<[{
141  custom<Foo>(ref(successors))
142}]>;
143
144// CHECK: error: 'ref' of 'regions' is not bound by a prior 'regions' directive
145def DirectiveRefInvalidG : TestFormat_Op<[{
146  custom<Foo>(ref(regions))
147}]>;
148
149// CHECK: error: expected '(' before argument list
150def DirectiveRefInvalidH : TestFormat_Op<[{
151  custom<Foo>(ref)
152}]>;
153
154// CHECK: error: expected ')' after argument list
155def DirectiveRefInvalidI : TestFormat_Op<[{
156  operands custom<Foo>(ref(operands(
157}]>;
158
159// CHECK: error: 'ref' of 'operands' is not bound by a prior 'operands' directive
160def DirectiveRefInvalidJ : TestFormat_Op<[{
161  custom<Foo>(ref(operands))
162}]>;
163
164// CHECK: error: 'ref' of 'attr-dict' is not bound by a prior 'attr-dict' directive
165def DirectiveRefInvalidK : TestFormat_Op<[{
166  custom<Foo>(ref(attr-dict))
167}]>;
168
169// CHECK: error: successor 'successor' must be bound before it is referenced
170def DirectiveRefInvalidL : TestFormat_Op<[{
171  custom<Foo>(ref($successor))
172}]> {
173  let successors = (successor AnySuccessor:$successor);
174}
175
176// CHECK: error: region 'region' must be bound before it is referenced
177def DirectiveRefInvalidM : TestFormat_Op<[{
178  custom<Foo>(ref($region))
179}]> {
180  let regions = (region AnyRegion:$region);
181}
182
183// CHECK: error: attribute 'attr' must be bound before it is referenced
184def DirectiveRefInvalidN : TestFormat_Op<[{
185  custom<Foo>(ref($attr))
186}]>, Arguments<(ins I64Attr:$attr)>;
187
188
189// CHECK: error: operand 'operand' must be bound before it is referenced
190def DirectiveRefInvalidO : TestFormat_Op<[{
191  custom<Foo>(ref($operand))
192}]>, Arguments<(ins I64:$operand)>;
193
194//===----------------------------------------------------------------------===//
195// regions
196
197// CHECK: error: 'regions' directive creates overlap in format
198def DirectiveRegionsInvalidA : TestFormat_Op<[{
199  regions regions attr-dict
200}]>;
201// CHECK: error: 'regions' directive creates overlap in format
202def DirectiveRegionsInvalidB : TestFormat_Op<[{
203  $region regions attr-dict
204}]> {
205  let regions = (region AnyRegion:$region);
206}
207// CHECK: error: 'regions' is only valid as a top-level directive
208def DirectiveRegionsInvalidC : TestFormat_Op<[{
209  type(regions)
210}]>;
211// CHECK: error: format ambiguity caused by `attr-dict` directive followed by region `foo`
212// CHECK: note: try using `attr-dict-with-keyword` instead
213def DirectiveRegionsInvalidD : TestFormat_Op<[{
214  attr-dict $foo
215}]> {
216  let regions = (region AnyRegion:$foo);
217}
218
219//===----------------------------------------------------------------------===//
220// results
221
222// CHECK: error: 'results' directive can can only be used as a child to a 'type' directive
223def DirectiveResultsInvalidA : TestFormat_Op<[{
224  results
225}]>;
226
227//===----------------------------------------------------------------------===//
228// successors
229
230// CHECK: error: 'successors' is only valid as a top-level directive
231def DirectiveSuccessorsInvalidA : TestFormat_Op<[{
232  type(successors)
233}]>;
234
235//===----------------------------------------------------------------------===//
236// type
237
238// CHECK: error: expected '(' before argument list
239def DirectiveTypeInvalidA : TestFormat_Op<[{
240  type
241}]>;
242// CHECK: error: expected literal, variable, directive, or optional group
243def DirectiveTypeInvalidB : TestFormat_Op<[{
244  type(
245}]>;
246// CHECK: error: expected ')' after argument list
247def DirectiveTypeInvalidC : TestFormat_Op<[{
248  type(operands
249}]>;
250
251//===----------------------------------------------------------------------===//
252// functional-type/type operands
253
254// CHECK: error: literals may only be used in the top-level section of the format
255def DirectiveTypeZOperandInvalidA : TestFormat_Op<[{
256  type(`literal`)
257}]>;
258// CHECK: error: 'operands' 'type' is already bound
259def DirectiveTypeZOperandInvalidB : TestFormat_Op<[{
260  type(operands) type(operands)
261}]>;
262// CHECK: error: 'operands' 'type' is already bound
263def DirectiveTypeZOperandInvalidC : TestFormat_Op<[{
264  type($operand) type(operands)
265}]>, Arguments<(ins I64:$operand)>;
266// CHECK: error: 'type' of 'operand' is already bound
267def DirectiveTypeZOperandInvalidD : TestFormat_Op<[{
268  type(operands) type($operand)
269}]>, Arguments<(ins I64:$operand)>;
270// CHECK: error: 'type' of 'operand' is already bound
271def DirectiveTypeZOperandInvalidE : TestFormat_Op<[{
272  type($operand) type($operand)
273}]>, Arguments<(ins I64:$operand)>;
274// CHECK: error: 'results' 'type' is already bound
275def DirectiveTypeZOperandInvalidF : TestFormat_Op<[{
276  type(results) type(results)
277}]>;
278// CHECK: error: 'results' 'type' is already bound
279def DirectiveTypeZOperandInvalidG : TestFormat_Op<[{
280  type($result) type(results)
281}]>, Results<(outs I64:$result)>;
282// CHECK: error: 'type' of 'result' is already bound
283def DirectiveTypeZOperandInvalidH : TestFormat_Op<[{
284  type(results) type($result)
285}]>, Results<(outs I64:$result)>;
286// CHECK: error: 'type' of 'result' is already bound
287def DirectiveTypeZOperandInvalidI : TestFormat_Op<[{
288  type($result) type($result)
289}]>, Results<(outs I64:$result)>;
290
291//===----------------------------------------------------------------------===//
292// Literals
293//===----------------------------------------------------------------------===//
294
295// Test all of the valid literals.
296// CHECK: error: expected valid literal but got 'a:': keywords should contain only alphanum, '_', '$', or '.' characters
297def LiteralInvalidA : TestFormat_Op<[{
298  `a:`
299}]>;
300// CHECK: error: expected valid literal but got '1': single character literal must be a letter or one of '_:,=<>()[]{}?+*'
301def LiteralInvalidB : TestFormat_Op<[{
302  `1`
303}]>;
304// CHECK: error: expected valid literal but got ':abc': valid keyword starts with a letter or '_'
305def LiteralInvalidC : TestFormat_Op<[{
306  `:abc`
307}]>;
308
309// CHECK: error: unexpected end of file in literal
310// CHECK: error: expected literal, variable, directive, or optional group
311def LiteralInvalidD : TestFormat_Op<[{
312  `
313}]>;
314
315//===----------------------------------------------------------------------===//
316// OIList Element
317//===----------------------------------------------------------------------===//
318
319// CHECK: error: format ambiguity because bar is used in two adjacent oilist elements.
320def OIListAdjacentOIList : TestFormat_Op<[{
321  oilist ( `foo` | `bar` ) oilist ( `bar` | `buzz` ) attr-dict
322}]>;
323// CHECK: error: expected literal, but got ')'
324def OIListErrorExpectedLiteral : TestFormat_Op<[{
325  oilist( `keyword` | ) attr-dict
326}]>;
327// CHECK: error: expected literal, but got ')'
328def OIListErrorExpectedEmpty : TestFormat_Op<[{
329  oilist() attr-dict
330}]>;
331// CHECK: error: expected literal, but got '$arg0'
332def OIListErrorNoLiteral : TestFormat_Op<[{
333  oilist( $arg0 `:` type($arg0) | $arg1 `:` type($arg1) ) attr-dict
334}], [AttrSizedOperandSegments]>, Arguments<(ins Optional<AnyType>:$arg0, Optional<AnyType>:$arg1)>;
335// CHECK: error: format ambiguity because foo is used both in oilist element and the adjacent literal.
336def OIListLiteralAmbiguity : TestFormat_Op<[{
337  oilist( `foo` | `bar` ) `foo` attr-dict
338}]>;
339// CHECK: error: expected '(' before oilist argument list
340def OIListStartingToken : TestFormat_Op<[{
341  oilist `wrong` attr-dict
342}]>;
343
344//===----------------------------------------------------------------------===//
345// Optional Groups
346//===----------------------------------------------------------------------===//
347
348// CHECK: error: optional groups can only be used as top-level elements
349def OptionalInvalidA : TestFormat_Op<[{
350  type(($attr^)?) attr-dict
351}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
352// CHECK: error: expected literal, variable, directive, or optional group
353def OptionalInvalidB : TestFormat_Op<[{
354  () attr-dict
355}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
356// CHECK: error: optional group has no anchor element
357def OptionalInvalidC : TestFormat_Op<[{
358  ($attr)? attr-dict
359}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
360// CHECK: error: first parsable element of an optional group must be a literal, variable, or custom directive
361def OptionalInvalidD : TestFormat_Op<[{
362  (type($operand) $operand^)? attr-dict
363}]>, Arguments<(ins Optional<I64>:$operand)>;
364// CHECK: error: only literals, types, and variables can be used within an optional group
365def OptionalInvalidE : TestFormat_Op<[{
366  (`,` $attr^ type(operands))? attr-dict
367}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr)>;
368// CHECK: error: only one element can be marked as the anchor of an optional group
369def OptionalInvalidF : TestFormat_Op<[{
370  ($attr^ $attr2^)? attr-dict
371}]>, Arguments<(ins OptionalAttr<I64Attr>:$attr, OptionalAttr<I64Attr>:$attr2)>;
372// CHECK: error: only optional or default-valued attributes can be used to anchor an optional group
373def OptionalInvalidG : TestFormat_Op<[{
374  ($attr^)? attr-dict
375}]>, Arguments<(ins I64Attr:$attr)>;
376// CHECK: error: only variable length operands can be used within an optional group
377def OptionalInvalidH : TestFormat_Op<[{
378  ($arg^)? attr-dict
379}]>, Arguments<(ins I64:$arg)>;
380// CHECK: error: only literals, types, and variables can be used within an optional group
381def OptionalInvalidI : TestFormat_Op<[{
382  (functional-type($arg, results)^)? attr-dict
383}]>, Arguments<(ins Variadic<I64>:$arg)>;
384// CHECK: error: only literals, types, and variables can be used within an optional group
385def OptionalInvalidJ : TestFormat_Op<[{
386  (attr-dict^)?
387}]>;
388// CHECK: error: expected '?' after optional group
389def OptionalInvalidK : TestFormat_Op<[{
390  ($arg^)
391}]>, Arguments<(ins Variadic<I64>:$arg)>;
392// CHECK: error: only variable length operands can be used within an optional group
393def OptionalInvalidL : TestFormat_Op<[{
394  (custom<MyDirective>($arg)^)?
395}]>, Arguments<(ins I64:$arg)>;
396// CHECK: error: only variables and types can be used to anchor an optional group
397def OptionalInvalidM : TestFormat_Op<[{
398  (` `^)?
399}]>, Arguments<(ins)>;
400// CHECK: error: expected '(' to start else branch of optional group
401def OptionalInvalidN : TestFormat_Op<[{
402  ($arg^):
403}]>, Arguments<(ins Variadic<I64>:$arg)>;
404// CHECK: error: expected literal, variable, directive, or optional group
405def OptionalInvalidO : TestFormat_Op<[{
406  ($arg^):(`test`
407}]>, Arguments<(ins Variadic<I64>:$arg)>;
408// CHECK: error: expected '?' after optional group
409def OptionalInvalidP : TestFormat_Op<[{
410  ($arg^):(`test`)
411}]>, Arguments<(ins Variadic<I64>:$arg)>;
412
413//===----------------------------------------------------------------------===//
414// Strings
415//===----------------------------------------------------------------------===//
416
417// CHECK: error: strings may only be used as 'custom' directive arguments
418def StringInvalidA : TestFormat_Op<[{ "foo" }]>;
419
420//===----------------------------------------------------------------------===//
421// Variables
422//===----------------------------------------------------------------------===//
423
424// CHECK: error: expected variable to refer to an argument, region, result, or successor
425def VariableInvalidA : TestFormat_Op<[{
426  $unknown_arg attr-dict
427}]>;
428// CHECK: error: attribute 'attr' is already bound
429def VariableInvalidB : TestFormat_Op<[{
430  $attr $attr attr-dict
431}]>, Arguments<(ins I64Attr:$attr)>;
432// CHECK: error: operand 'operand' is already bound
433def VariableInvalidC : TestFormat_Op<[{
434  $operand $operand attr-dict
435}]>, Arguments<(ins I64:$operand)>;
436// CHECK: error: operand 'operand' is already bound
437def VariableInvalidD : TestFormat_Op<[{
438  operands $operand attr-dict
439}]>, Arguments<(ins I64:$operand)>;
440// CHECK: error: result variables can can only be used as a child to a 'type' directive
441def VariableInvalidE : TestFormat_Op<[{
442  $result attr-dict
443}]>, Results<(outs I64:$result)>;
444// CHECK: error: successor 'successor' is already bound
445def VariableInvalidF : TestFormat_Op<[{
446  $successor $successor attr-dict
447}]> {
448  let successors = (successor AnySuccessor:$successor);
449}
450// CHECK: error: successor 'successor' is already bound
451def VariableInvalidG : TestFormat_Op<[{
452  successors $successor attr-dict
453}]> {
454  let successors = (successor AnySuccessor:$successor);
455}
456// CHECK: error: region 'region' is already bound
457def VariableInvalidK : TestFormat_Op<[{
458  $region $region attr-dict
459}]> {
460  let regions = (region AnyRegion:$region);
461}
462// CHECK: error: region 'region' is already bound
463def VariableInvalidL : TestFormat_Op<[{
464  regions $region attr-dict
465}]> {
466  let regions = (region AnyRegion:$region);
467}
468// CHECK: error: regions can only be used at the top level
469def VariableInvalidM : TestFormat_Op<[{
470  type($region)
471}]> {
472  let regions = (region AnyRegion:$region);
473}
474// CHECK: error: region #0, named 'region', not found
475def VariableInvalidN : TestFormat_Op<[{
476  attr-dict
477}]> {
478  let regions = (region AnyRegion:$region);
479}
480
481// CHECK: error: property 'prop' is already bound
482def VariableInvalidO : TestFormat_Op<[{
483  custom<Test>($prop, $prop) attr-dict
484}]>, Arguments<(ins IntProp<"int64_t">:$prop)>;
485
486// CHECK: error: property 'prop' must be bound before it is referenced
487def VariableInvalidP : TestFormat_Op<[{
488  custom<Test>(ref($prop)) attr-dict
489}]>, Arguments<(ins IntProp<"int64_t">:$prop)>;
490
491//===----------------------------------------------------------------------===//
492// Coverage Checks
493//===----------------------------------------------------------------------===//
494
495// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred
496// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format
497def ZCoverageInvalidA : TestFormat_Op<[{
498  attr-dict
499}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
500// CHECK: error: operand #0, named 'operand', not found
501// CHECK: note: suggest adding a '$operand' directive to the custom assembly format
502def ZCoverageInvalidB : TestFormat_Op<[{
503  type($result) attr-dict
504}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
505// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred
506// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format
507def ZCoverageInvalidC : TestFormat_Op<[{
508  $operand type($result) attr-dict
509}]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
510// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred
511// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format
512def ZCoverageInvalidD : TestFormat_Op<[{
513  operands attr-dict
514}]>, Arguments<(ins Variadic<I64>:$operand)>;
515// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred
516// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format
517def ZCoverageInvalidE : TestFormat_Op<[{
518  attr-dict
519}]>, Results<(outs Variadic<I64>:$result)>;
520// CHECK: error: successor #0, named 'successor', not found
521// CHECK: note: suggest adding a '$successor' directive to the custom assembly format
522def ZCoverageInvalidF : TestFormat_Op<[{
523	 attr-dict
524}]> {
525  let successors = (successor AnySuccessor:$successor);
526}
527// CHECK: error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred
528// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format
529def ZCoverageInvalidG : TestFormat_Op<[{
530  operands attr-dict
531}]>, Arguments<(ins Optional<I64>:$operand)>;
532// CHECK: error: type of result #0, named 'result', is not buildable and a buildable type cannot be inferred
533// CHECK: note: suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format
534def ZCoverageInvalidH : TestFormat_Op<[{
535  attr-dict
536}]>, Results<(outs Optional<I64>:$result)>;
537