xref: /llvm-project/llvm/unittests/Support/SourceMgrTest.cpp (revision 38818b60c58c76ba89b990978cdfd2d7b6799260)
1 //===- unittests/Support/SourceMgrTest.cpp - SourceMgr 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 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Support/SourceMgr.h"
10 #include "llvm/Support/MemoryBuffer.h"
11 #include "llvm/Support/raw_ostream.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 
16 namespace {
17 
18 class SourceMgrTest : public testing::Test {
19 public:
20   SourceMgr SM;
21   unsigned MainBufferID;
22   std::string Output;
23 
24   void setMainBuffer(StringRef Text, StringRef BufferName) {
25     std::unique_ptr<MemoryBuffer> MainBuffer =
26         MemoryBuffer::getMemBuffer(Text, BufferName);
27     MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc());
28   }
29 
30   SMLoc getLoc(unsigned Offset) {
31     return SMLoc::getFromPointer(
32         SM.getMemoryBuffer(MainBufferID)->getBufferStart() + Offset);
33   }
34 
35   SMRange getRange(unsigned Offset, unsigned Length) {
36     return SMRange(getLoc(Offset), getLoc(Offset + Length));
37   }
38 
39   void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
40                     const Twine &Msg, ArrayRef<SMRange> Ranges,
41                     ArrayRef<SMFixIt> FixIts) {
42     raw_string_ostream OS(Output);
43     SM.PrintMessage(OS, Loc, Kind, Msg, Ranges, FixIts);
44   }
45 };
46 
47 } // unnamed namespace
48 
49 TEST_F(SourceMgrTest, BasicError) {
50   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
51   printMessage(getLoc(4), SourceMgr::DK_Error, "message", std::nullopt,
52                std::nullopt);
53 
54   EXPECT_EQ("file.in:1:5: error: message\n"
55             "aaa bbb\n"
56             "    ^\n",
57             Output);
58 }
59 
60 TEST_F(SourceMgrTest, BasicWarning) {
61   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
62   printMessage(getLoc(4), SourceMgr::DK_Warning, "message", std::nullopt,
63                std::nullopt);
64 
65   EXPECT_EQ("file.in:1:5: warning: message\n"
66             "aaa bbb\n"
67             "    ^\n",
68             Output);
69 }
70 
71 TEST_F(SourceMgrTest, BasicRemark) {
72   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
73   printMessage(getLoc(4), SourceMgr::DK_Remark, "message", std::nullopt,
74                std::nullopt);
75 
76   EXPECT_EQ("file.in:1:5: remark: message\n"
77             "aaa bbb\n"
78             "    ^\n",
79             Output);
80 }
81 
82 TEST_F(SourceMgrTest, BasicNote) {
83   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
84   printMessage(getLoc(4), SourceMgr::DK_Note, "message", std::nullopt,
85                std::nullopt);
86 
87   EXPECT_EQ("file.in:1:5: note: message\n"
88             "aaa bbb\n"
89             "    ^\n",
90             Output);
91 }
92 
93 TEST_F(SourceMgrTest, LocationAtEndOfLine) {
94   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
95   printMessage(getLoc(6), SourceMgr::DK_Error, "message", std::nullopt,
96                std::nullopt);
97 
98   EXPECT_EQ("file.in:1:7: error: message\n"
99             "aaa bbb\n"
100             "      ^\n",
101             Output);
102 }
103 
104 TEST_F(SourceMgrTest, LocationAtNewline) {
105   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
106   printMessage(getLoc(7), SourceMgr::DK_Error, "message", std::nullopt,
107                std::nullopt);
108 
109   EXPECT_EQ("file.in:1:8: error: message\n"
110             "aaa bbb\n"
111             "       ^\n",
112             Output);
113 }
114 
115 TEST_F(SourceMgrTest, LocationAtEmptyBuffer) {
116   setMainBuffer("", "file.in");
117   printMessage(getLoc(0), SourceMgr::DK_Error, "message", std::nullopt,
118                std::nullopt);
119 
120   EXPECT_EQ("file.in:1:1: error: message\n"
121             "\n"
122             "^\n",
123             Output);
124 }
125 
126 TEST_F(SourceMgrTest, LocationJustOnSoleNewline) {
127   setMainBuffer("\n", "file.in");
128   printMessage(getLoc(0), SourceMgr::DK_Error, "message", std::nullopt,
129                std::nullopt);
130 
131   EXPECT_EQ("file.in:1:1: error: message\n"
132             "\n"
133             "^\n",
134             Output);
135 }
136 
137 TEST_F(SourceMgrTest, LocationJustAfterSoleNewline) {
138   setMainBuffer("\n", "file.in");
139   printMessage(getLoc(1), SourceMgr::DK_Error, "message", std::nullopt,
140                std::nullopt);
141 
142   EXPECT_EQ("file.in:2:1: error: message\n"
143             "\n"
144             "^\n",
145             Output);
146 }
147 
148 TEST_F(SourceMgrTest, LocationJustAfterNonNewline) {
149   setMainBuffer("123", "file.in");
150   printMessage(getLoc(3), SourceMgr::DK_Error, "message", std::nullopt,
151                std::nullopt);
152 
153   EXPECT_EQ("file.in:1:4: error: message\n"
154             "123\n"
155             "   ^\n",
156             Output);
157 }
158 
159 TEST_F(SourceMgrTest, LocationOnFirstLineOfMultiline) {
160   setMainBuffer("1234\n6789\n", "file.in");
161   printMessage(getLoc(3), SourceMgr::DK_Error, "message", std::nullopt,
162                std::nullopt);
163 
164   EXPECT_EQ("file.in:1:4: error: message\n"
165             "1234\n"
166             "   ^\n",
167             Output);
168 }
169 
170 TEST_F(SourceMgrTest, LocationOnEOLOfFirstLineOfMultiline) {
171   setMainBuffer("1234\n6789\n", "file.in");
172   printMessage(getLoc(4), SourceMgr::DK_Error, "message", std::nullopt,
173                std::nullopt);
174 
175   EXPECT_EQ("file.in:1:5: error: message\n"
176             "1234\n"
177             "    ^\n",
178             Output);
179 }
180 
181 TEST_F(SourceMgrTest, LocationOnSecondLineOfMultiline) {
182   setMainBuffer("1234\n6789\n", "file.in");
183   printMessage(getLoc(5), SourceMgr::DK_Error, "message", std::nullopt,
184                std::nullopt);
185 
186   EXPECT_EQ("file.in:2:1: error: message\n"
187             "6789\n"
188             "^\n",
189             Output);
190 }
191 
192 TEST_F(SourceMgrTest, LocationOnSecondLineOfMultilineNoSecondEOL) {
193   setMainBuffer("1234\n6789", "file.in");
194   printMessage(getLoc(5), SourceMgr::DK_Error, "message", std::nullopt,
195                std::nullopt);
196 
197   EXPECT_EQ("file.in:2:1: error: message\n"
198             "6789\n"
199             "^\n",
200             Output);
201 }
202 
203 TEST_F(SourceMgrTest, LocationOnEOLOfSecondSecondLineOfMultiline) {
204   setMainBuffer("1234\n6789\n", "file.in");
205   printMessage(getLoc(9), SourceMgr::DK_Error, "message", std::nullopt,
206                std::nullopt);
207 
208   EXPECT_EQ("file.in:2:5: error: message\n"
209             "6789\n"
210             "    ^\n",
211             Output);
212 }
213 
214 #define STRING_LITERAL_253_BYTES \
215   "1234567890\n1234567890\n" \
216   "1234567890\n1234567890\n" \
217   "1234567890\n1234567890\n" \
218   "1234567890\n1234567890\n" \
219   "1234567890\n1234567890\n" \
220   "1234567890\n1234567890\n" \
221   "1234567890\n1234567890\n" \
222   "1234567890\n1234567890\n" \
223   "1234567890\n1234567890\n" \
224   "1234567890\n1234567890\n" \
225   "1234567890\n1234567890\n" \
226   "1234567890\n"
227 
228 //===----------------------------------------------------------------------===//
229 // 255-byte buffer tests
230 //===----------------------------------------------------------------------===//
231 
232 TEST_F(SourceMgrTest, LocationBeforeEndOf255ByteBuffer) {
233   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
234                 "12"                       // + 2 = 255 bytes
235                 , "file.in");
236   printMessage(getLoc(253), SourceMgr::DK_Error, "message", std::nullopt,
237                std::nullopt);
238   EXPECT_EQ("file.in:24:1: error: message\n"
239             "12\n"
240             "^\n",
241             Output);
242 }
243 
244 TEST_F(SourceMgrTest, LocationAtEndOf255ByteBuffer) {
245   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
246                 "12"                       // + 2 = 255 bytes
247                 , "file.in");
248   printMessage(getLoc(254), SourceMgr::DK_Error, "message", std::nullopt,
249                std::nullopt);
250   EXPECT_EQ("file.in:24:2: error: message\n"
251             "12\n"
252             " ^\n",
253             Output);
254 }
255 
256 TEST_F(SourceMgrTest, LocationPastEndOf255ByteBuffer) {
257   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
258                 "12"                       // + 2 = 255 bytes
259                 , "file.in");
260   printMessage(getLoc(255), SourceMgr::DK_Error, "message", std::nullopt,
261                std::nullopt);
262   EXPECT_EQ("file.in:24:3: error: message\n"
263             "12\n"
264             "  ^\n",
265             Output);
266 }
267 
268 TEST_F(SourceMgrTest, LocationBeforeEndOf255ByteBufferEndingInNewline) {
269   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
270                 "1\n"                      // + 2 = 255 bytes
271                 , "file.in");
272   printMessage(getLoc(253), SourceMgr::DK_Error, "message", std::nullopt,
273                std::nullopt);
274   EXPECT_EQ("file.in:24:1: error: message\n"
275             "1\n"
276             "^\n",
277             Output);
278 }
279 
280 TEST_F(SourceMgrTest, LocationAtEndOf255ByteBufferEndingInNewline) {
281   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
282                 "1\n"                      // + 2 = 255 bytes
283                 , "file.in");
284   printMessage(getLoc(254), SourceMgr::DK_Error, "message", std::nullopt,
285                std::nullopt);
286   EXPECT_EQ("file.in:24:2: error: message\n"
287             "1\n"
288             " ^\n",
289             Output);
290 }
291 
292 TEST_F(SourceMgrTest, LocationPastEndOf255ByteBufferEndingInNewline) {
293   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
294                 "1\n"                      // + 2 = 255 bytes
295                 , "file.in");
296   printMessage(getLoc(255), SourceMgr::DK_Error, "message", std::nullopt,
297                std::nullopt);
298   EXPECT_EQ("file.in:25:1: error: message\n"
299             "\n"
300             "^\n",
301             Output);
302 }
303 
304 //===----------------------------------------------------------------------===//
305 // 256-byte buffer tests
306 //===----------------------------------------------------------------------===//
307 
308 TEST_F(SourceMgrTest, LocationBeforeEndOf256ByteBuffer) {
309   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
310                 "123"                      // + 3 = 256 bytes
311                 , "file.in");
312   printMessage(getLoc(254), SourceMgr::DK_Error, "message", std::nullopt,
313                std::nullopt);
314   EXPECT_EQ("file.in:24:2: error: message\n"
315             "123\n"
316             " ^\n",
317             Output);
318 }
319 
320 TEST_F(SourceMgrTest, LocationAtEndOf256ByteBuffer) {
321   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
322                 "123"                      // + 3 = 256 bytes
323                 , "file.in");
324   printMessage(getLoc(255), SourceMgr::DK_Error, "message", std::nullopt,
325                std::nullopt);
326   EXPECT_EQ("file.in:24:3: error: message\n"
327             "123\n"
328             "  ^\n",
329             Output);
330 }
331 
332 TEST_F(SourceMgrTest, LocationPastEndOf256ByteBuffer) {
333   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
334                 "123"                      // + 3 = 256 bytes
335                 , "file.in");
336   printMessage(getLoc(256), SourceMgr::DK_Error, "message", std::nullopt,
337                std::nullopt);
338   EXPECT_EQ("file.in:24:4: error: message\n"
339             "123\n"
340             "   ^\n",
341             Output);
342 }
343 
344 TEST_F(SourceMgrTest, LocationBeforeEndOf256ByteBufferEndingInNewline) {
345   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
346                 "12\n"                     // + 3 = 256 bytes
347                 , "file.in");
348   printMessage(getLoc(254), SourceMgr::DK_Error, "message", std::nullopt,
349                std::nullopt);
350   EXPECT_EQ("file.in:24:2: error: message\n"
351             "12\n"
352             " ^\n",
353             Output);
354 }
355 
356 TEST_F(SourceMgrTest, LocationAtEndOf256ByteBufferEndingInNewline) {
357   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
358                 "12\n"                     // + 3 = 256 bytes
359                 , "file.in");
360   printMessage(getLoc(255), SourceMgr::DK_Error, "message", std::nullopt,
361                std::nullopt);
362   EXPECT_EQ("file.in:24:3: error: message\n"
363             "12\n"
364             "  ^\n",
365             Output);
366 }
367 
368 TEST_F(SourceMgrTest, LocationPastEndOf256ByteBufferEndingInNewline) {
369   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
370                 "12\n"                     // + 3 = 256 bytes
371                 , "file.in");
372   printMessage(getLoc(256), SourceMgr::DK_Error, "message", std::nullopt,
373                std::nullopt);
374   EXPECT_EQ("file.in:25:1: error: message\n"
375             "\n"
376             "^\n",
377             Output);
378 }
379 
380 //===----------------------------------------------------------------------===//
381 // 257-byte buffer tests
382 //===----------------------------------------------------------------------===//
383 
384 TEST_F(SourceMgrTest, LocationBeforeEndOf257ByteBuffer) {
385   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
386                 "1234"                     // + 4 = 257 bytes
387                 , "file.in");
388   printMessage(getLoc(255), SourceMgr::DK_Error, "message", std::nullopt,
389                std::nullopt);
390   EXPECT_EQ("file.in:24:3: error: message\n"
391             "1234\n"
392             "  ^\n",
393             Output);
394 }
395 
396 TEST_F(SourceMgrTest, LocationAtEndOf257ByteBuffer) {
397   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
398                 "1234"                     // + 4 = 257 bytes
399                 , "file.in");
400   printMessage(getLoc(256), SourceMgr::DK_Error, "message", std::nullopt,
401                std::nullopt);
402   EXPECT_EQ("file.in:24:4: error: message\n"
403             "1234\n"
404             "   ^\n",
405             Output);
406 }
407 
408 TEST_F(SourceMgrTest, LocationPastEndOf257ByteBuffer) {
409   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
410                 "1234"                     // + 4 = 257 bytes
411                 , "file.in");
412   printMessage(getLoc(257), SourceMgr::DK_Error, "message", std::nullopt,
413                std::nullopt);
414   EXPECT_EQ("file.in:24:5: error: message\n"
415             "1234\n"
416             "    ^\n",
417             Output);
418 }
419 
420 TEST_F(SourceMgrTest, LocationBeforeEndOf257ByteBufferEndingInNewline) {
421   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
422                 "123\n"                    // + 4 = 257 bytes
423                 , "file.in");
424   printMessage(getLoc(255), SourceMgr::DK_Error, "message", std::nullopt,
425                std::nullopt);
426   EXPECT_EQ("file.in:24:3: error: message\n"
427             "123\n"
428             "  ^\n",
429             Output);
430 }
431 
432 TEST_F(SourceMgrTest, LocationAtEndOf257ByteBufferEndingInNewline) {
433   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
434                 "123\n"                    // + 4 = 257 bytes
435                 , "file.in");
436   printMessage(getLoc(256), SourceMgr::DK_Error, "message", std::nullopt,
437                std::nullopt);
438   EXPECT_EQ("file.in:24:4: error: message\n"
439             "123\n"
440             "   ^\n",
441             Output);
442 }
443 
444 TEST_F(SourceMgrTest, LocationPastEndOf257ByteBufferEndingInNewline) {
445   setMainBuffer(STRING_LITERAL_253_BYTES   // first 253 bytes
446                 "123\n"                    // + 4 = 257 bytes
447                 , "file.in");
448   printMessage(getLoc(257), SourceMgr::DK_Error, "message", std::nullopt,
449                std::nullopt);
450   EXPECT_EQ("file.in:25:1: error: message\n"
451             "\n"
452             "^\n",
453             Output);
454 }
455 
456 TEST_F(SourceMgrTest, BasicRange) {
457   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
458   printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 3),
459                std::nullopt);
460 
461   EXPECT_EQ("file.in:1:5: error: message\n"
462             "aaa bbb\n"
463             "    ^~~\n",
464             Output);
465 }
466 
467 TEST_F(SourceMgrTest, RangeWithTab) {
468   setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
469   printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(3, 3),
470                std::nullopt);
471 
472   EXPECT_EQ("file.in:1:5: error: message\n"
473             "aaa     bbb\n"
474             "   ~~~~~^~\n",
475             Output);
476 }
477 
478 TEST_F(SourceMgrTest, MultiLineRange) {
479   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
480   printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 7),
481                std::nullopt);
482 
483   EXPECT_EQ("file.in:1:5: error: message\n"
484             "aaa bbb\n"
485             "    ^~~\n",
486             Output);
487 }
488 
489 TEST_F(SourceMgrTest, MultipleRanges) {
490   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
491   SMRange Ranges[] = { getRange(0, 3), getRange(4, 3) };
492   printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, std::nullopt);
493 
494   EXPECT_EQ("file.in:1:5: error: message\n"
495             "aaa bbb\n"
496             "~~~ ^~~\n",
497             Output);
498 }
499 
500 TEST_F(SourceMgrTest, OverlappingRanges) {
501   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
502   SMRange Ranges[] = { getRange(0, 3), getRange(2, 4) };
503   printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, std::nullopt);
504 
505   EXPECT_EQ("file.in:1:5: error: message\n"
506             "aaa bbb\n"
507             "~~~~^~\n",
508             Output);
509 }
510 
511 TEST_F(SourceMgrTest, BasicFixit) {
512   setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
513   printMessage(getLoc(4), SourceMgr::DK_Error, "message", std::nullopt,
514                ArrayRef(SMFixIt(getRange(4, 3), "zzz")));
515 
516   EXPECT_EQ("file.in:1:5: error: message\n"
517             "aaa bbb\n"
518             "    ^~~\n"
519             "    zzz\n",
520             Output);
521 }
522 
523 TEST_F(SourceMgrTest, FixitForTab) {
524   setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
525   printMessage(getLoc(3), SourceMgr::DK_Error, "message", std::nullopt,
526                ArrayRef(SMFixIt(getRange(3, 1), "zzz")));
527 
528   EXPECT_EQ("file.in:1:4: error: message\n"
529             "aaa     bbb\n"
530             "   ^^^^^\n"
531             "   zzz\n",
532             Output);
533 }
534 
535