1 | //===- ParserTest.cpp -----------------------------------------------------===// |
2 | // |
3 | // This file is licensed under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "mlir/Parser/Parser.h" |
10 | #include "mlir/AsmParser/AsmParser.h" |
11 | #include "mlir/IR/BuiltinOps.h" |
12 | #include "mlir/IR/Verifier.h" |
13 | |
14 | #include "gmock/gmock.h" |
15 | |
16 | using namespace mlir; |
17 | |
18 | namespace { |
19 | TEST(MLIRParser, ParseInvalidIR) { |
20 | std::string moduleStr = R"mlir( |
21 | module attributes {bad} {} |
22 | )mlir" ; |
23 | |
24 | MLIRContext context; |
25 | ParserConfig config(&context, /*verifyAfterParse=*/false); |
26 | |
27 | // Check that we properly parse the op, but it fails the verifier. |
28 | OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(moduleStr, config); |
29 | ASSERT_TRUE(module); |
30 | ASSERT_TRUE(failed(verify(*module))); |
31 | } |
32 | |
33 | TEST(MLIRParser, ParseAtEnd) { |
34 | std::string firstModuleStr = R"mlir( |
35 | "test.first"() : () -> () |
36 | )mlir" ; |
37 | std::string secondModuleStr = R"mlir( |
38 | "test.second"() : () -> () |
39 | )mlir" ; |
40 | |
41 | MLIRContext context; |
42 | context.allowUnregisteredDialects(); |
43 | Block block; |
44 | |
45 | // Parse the first module string. |
46 | LogicalResult firstParse = |
47 | parseSourceString(sourceStr: firstModuleStr, block: &block, config: &context); |
48 | EXPECT_TRUE(succeeded(firstParse)); |
49 | |
50 | // Parse the second module string. |
51 | LogicalResult secondParse = |
52 | parseSourceString(sourceStr: secondModuleStr, block: &block, config: &context); |
53 | EXPECT_TRUE(succeeded(secondParse)); |
54 | |
55 | // Check the we parse at the end. |
56 | EXPECT_EQ(block.front().getName().getStringRef(), "test.first" ); |
57 | EXPECT_EQ(block.back().getName().getStringRef(), "test.second" ); |
58 | } |
59 | |
60 | TEST(MLIRParser, ParseAttr) { |
61 | using namespace testing; |
62 | MLIRContext context; |
63 | Builder b(&context); |
64 | { // Successful parse |
65 | StringLiteral attrAsm = "array<i64: 1, 2, 3>" ; |
66 | size_t numRead = 0; |
67 | Attribute attr = parseAttribute(attrStr: attrAsm, context: &context, type: Type(), numRead: &numRead); |
68 | EXPECT_EQ(attr, b.getDenseI64ArrayAttr({1, 2, 3})); |
69 | EXPECT_EQ(numRead, attrAsm.size()); |
70 | } |
71 | { // Failed parse |
72 | std::vector<std::string> diagnostics; |
73 | ScopedDiagnosticHandler handler(&context, [&](Diagnostic &d) { |
74 | llvm::raw_string_ostream(diagnostics.emplace_back()) |
75 | << d.getLocation() << ": " << d; |
76 | }); |
77 | size_t numRead = 0; |
78 | EXPECT_FALSE(parseAttribute("dense<>" , &context, Type(), &numRead)); |
79 | EXPECT_THAT(diagnostics, ElementsAre("loc(\"dense<>\":1:7): expected ':'" )); |
80 | EXPECT_EQ(numRead, size_t(0)); |
81 | } |
82 | { // Parse with trailing characters |
83 | std::vector<std::string> diagnostics; |
84 | ScopedDiagnosticHandler handler(&context, [&](Diagnostic &d) { |
85 | llvm::raw_string_ostream(diagnostics.emplace_back()) |
86 | << d.getLocation() << ": " << d; |
87 | }); |
88 | EXPECT_FALSE(parseAttribute("10 foo" , &context)); |
89 | EXPECT_THAT( |
90 | diagnostics, |
91 | ElementsAre("loc(\"10 foo\":1:5): found trailing characters: 'foo'" )); |
92 | |
93 | size_t numRead = 0; |
94 | EXPECT_EQ(parseAttribute("10 foo" , &context, Type(), &numRead), |
95 | b.getI64IntegerAttr(10)); |
96 | EXPECT_EQ(numRead, size_t(4)); // includes trailing whitespace |
97 | } |
98 | { // Parse without null-terminator |
99 | StringRef attrAsm("999" , 1); |
100 | Attribute attr = parseAttribute(attrStr: attrAsm, context: &context); |
101 | EXPECT_EQ(attr, b.getI64IntegerAttr(9)); |
102 | } |
103 | } |
104 | } // namespace |
105 | |