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