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