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