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