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

source code of llvm/unittests/Support/SourceMgrTest.cpp