[MemProf] Templatize CallStackRadixTreeBuilder (NFC) (#117014)
[llvm-project.git] / llvm / unittests / TableGen / CodeExpanderTest.cpp
blob1528884ffdf65b7dcffe85d44786e8ffcb64eadc
1 //===- llvm/unittest/TableGen/CodeExpanderTest.cpp - Tests ----------------===//
2 //
3 // Part of the LLVM Project, 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 //===----------------------------------------------------------------------===//
9 #include "Common/GlobalISel/CodeExpander.h"
10 #include "Common/GlobalISel/CodeExpansions.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include "llvm/TableGen/Error.h"
14 #include "gtest/gtest.h"
16 using namespace llvm;
18 static StringRef bufferize(StringRef Str) {
19 std::unique_ptr<MemoryBuffer> Buffer =
20 MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
21 StringRef StrBufferRef = Buffer->getBuffer();
22 SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
23 return StrBufferRef;
26 class RAIIDiagnosticChecker {
27 std::string EmittedDiags;
28 raw_string_ostream OS;
29 std::vector<SMDiagnostic> Expected;
30 std::vector<SMDiagnostic> Received;
32 public:
33 RAIIDiagnosticChecker() : OS(EmittedDiags) {
34 SrcMgr.setDiagHandler(handler, this);
36 ~RAIIDiagnosticChecker() {
37 SrcMgr.setDiagHandler(nullptr);
38 EXPECT_EQ(Received.size(), Expected.size());
39 for (unsigned i = 0; i < Received.size() && i < Expected.size(); ++i) {
40 EXPECT_EQ(Received[i].getLoc(), Expected[i].getLoc());
41 EXPECT_EQ(Received[i].getFilename(), Expected[i].getFilename());
42 EXPECT_EQ(Received[i].getKind(), Expected[i].getKind());
43 EXPECT_EQ(Received[i].getLineNo(), Expected[i].getLineNo());
44 EXPECT_EQ(Received[i].getColumnNo(), Expected[i].getColumnNo());
45 EXPECT_EQ(Received[i].getMessage(), Expected[i].getMessage());
46 EXPECT_EQ(Received[i].getLineContents(), Expected[i].getLineContents());
47 EXPECT_EQ(Received[i].getRanges(), Expected[i].getRanges());
50 if (testing::Test::HasFailure())
51 errs() << "Emitted diagnostic:\n" << OS.str();
54 void expect(SMDiagnostic D) { Expected.push_back(D); }
56 void diag(const SMDiagnostic &D) {
57 Received.push_back(D);
60 static void handler(const SMDiagnostic &D, void *Context) {
61 RAIIDiagnosticChecker *Self = static_cast<RAIIDiagnosticChecker *>(Context);
62 Self->diag(D);
63 SrcMgr.setDiagHandler(nullptr);
64 SrcMgr.PrintMessage(Self->OS, D);
65 SrcMgr.setDiagHandler(handler, Context);
69 TEST(CodeExpander, NoExpansions) {
70 std::string Result;
71 raw_string_ostream OS(Result);
72 CodeExpansions Expansions;
74 RAIIDiagnosticChecker DiagChecker;
75 CodeExpander("No expansions", Expansions, SMLoc(), false).emit(OS);
76 EXPECT_EQ(OS.str(), "No expansions");
79 // Indentation is applied to all lines except the first
80 TEST(CodeExpander, Indentation) {
81 std::string Result;
82 raw_string_ostream OS(Result);
83 CodeExpansions Expansions;
85 RAIIDiagnosticChecker DiagChecker;
86 CodeExpander("No expansions\nsecond line\nthird line", Expansions, SMLoc(),
87 false, " ")
88 .emit(OS);
89 EXPECT_EQ(OS.str(), "No expansions\n second line\n third line");
92 // \ is an escape character that removes special meanings from the next
93 // character.
94 TEST(CodeExpander, Escape) {
95 std::string Result;
96 raw_string_ostream OS(Result);
97 CodeExpansions Expansions;
99 RAIIDiagnosticChecker DiagChecker;
100 CodeExpander("\\\\\\a\\$", Expansions, SMLoc(), false).emit(OS);
101 EXPECT_EQ(OS.str(), "\\a$");
104 // $foo is not an expansion. It should warn though.
105 TEST(CodeExpander, NotAnExpansion) {
106 std::string Result;
107 raw_string_ostream OS(Result);
108 CodeExpansions Expansions;
110 RAIIDiagnosticChecker DiagChecker;
111 StringRef In = bufferize(" $foo");
112 CodeExpander(" $foo", Expansions, SMLoc::getFromPointer(In.data()), false)
113 .emit(OS);
114 EXPECT_EQ(OS.str(), " $foo");
115 DiagChecker.expect(SMDiagnostic(
116 SrcMgr, SMLoc::getFromPointer(In.data()), "TestBuffer", 1, 0,
117 SourceMgr::DK_Warning, "Assuming missing escape character: \\$", " $foo", {}));
120 // \$foo is not an expansion but shouldn't warn as it's using the escape.
121 TEST(CodeExpander, EscapedNotAnExpansion) {
122 std::string Result;
123 raw_string_ostream OS(Result);
124 CodeExpansions Expansions;
126 RAIIDiagnosticChecker DiagChecker;
127 CodeExpander("\\$foo", Expansions, SMLoc(), false).emit(OS);
128 EXPECT_EQ(OS.str(), "$foo");
131 // \${foo is not an expansion but shouldn't warn as it's using the escape.
132 TEST(CodeExpander, EscapedUnterminatedExpansion) {
133 std::string Result;
134 raw_string_ostream OS(Result);
135 CodeExpansions Expansions;
137 RAIIDiagnosticChecker DiagChecker;
138 CodeExpander("\\${foo", Expansions, SMLoc(), false).emit(OS);
139 EXPECT_EQ(OS.str(), "${foo");
142 // \${foo is not an expansion but shouldn't warn as it's using the escape.
143 TEST(CodeExpander, EscapedExpansion) {
144 std::string Result;
145 raw_string_ostream OS(Result);
146 CodeExpansions Expansions;
148 RAIIDiagnosticChecker DiagChecker;
149 CodeExpander("\\${foo}", Expansions, SMLoc(), false).emit(OS);
150 EXPECT_EQ(OS.str(), "${foo}");
153 // ${foo} is an undefined expansion and should error.
154 TEST(CodeExpander, UndefinedExpansion) {
155 std::string Result;
156 raw_string_ostream OS(Result);
157 CodeExpansions Expansions;
158 Expansions.declare("bar", "expansion");
160 RAIIDiagnosticChecker DiagChecker;
161 CodeExpander("${foo}${bar}", Expansions, SMLoc(), false).emit(OS);
162 EXPECT_EQ(OS.str(), "expansion");
163 DiagChecker.expect(
164 SMDiagnostic(SrcMgr, SMLoc(), "<unknown>", 0, -1, SourceMgr::DK_Error,
165 "Attempt to expand an undeclared variable 'foo'", "", {}));
168 // ${bar is an unterminated expansion. Warn and implicitly terminate it.
169 TEST(CodeExpander, UnterminatedExpansion) {
170 std::string Result;
171 raw_string_ostream OS(Result);
172 CodeExpansions Expansions;
173 Expansions.declare("bar", "expansion");
175 RAIIDiagnosticChecker DiagChecker;
176 StringRef In = bufferize(" ${bar");
177 CodeExpander(In, Expansions, SMLoc::getFromPointer(In.data()), false)
178 .emit(OS);
179 EXPECT_EQ(OS.str(), " expansion");
180 DiagChecker.expect(SMDiagnostic(SrcMgr, SMLoc::getFromPointer(In.data()),
181 "TestBuffer", 1, 0, SourceMgr::DK_Warning,
182 "Unterminated expansion '${bar'", " ${bar", {}));