xref: /llvm-project/clang/unittests/Basic/SourceManagerTest.cpp (revision b1aea98cfa357e23f4bb52232da5f41781f23bff)
1 //===- unittests/Basic/SourceManagerTest.cpp ------ SourceManager 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 "clang/Basic/SourceManager.h"
10 #include "clang/Basic/Diagnostic.h"
11 #include "clang/Basic/DiagnosticOptions.h"
12 #include "clang/Basic/FileManager.h"
13 #include "clang/Basic/LangOptions.h"
14 #include "clang/Basic/TargetInfo.h"
15 #include "clang/Basic/TargetOptions.h"
16 #include "clang/Lex/HeaderSearch.h"
17 #include "clang/Lex/HeaderSearchOptions.h"
18 #include "clang/Lex/ModuleLoader.h"
19 #include "clang/Lex/Preprocessor.h"
20 #include "clang/Lex/PreprocessorOptions.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/Config/llvm-config.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/Process.h"
25 #include "gtest/gtest.h"
26 #include <cstddef>
27 
28 using namespace clang;
29 
30 namespace clang {
31 class SourceManagerTestHelper {
32 public:
33   static FileID makeFileID(int ID) { return FileID::get(ID); }
34 };
35 } // namespace clang
36 
37 namespace {
38 
39 // The test fixture.
40 class SourceManagerTest : public ::testing::Test {
41 protected:
42   SourceManagerTest()
43     : FileMgr(FileMgrOpts),
44       DiagID(new DiagnosticIDs()),
45       Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
46       SourceMgr(Diags, FileMgr),
47       TargetOpts(new TargetOptions) {
48     TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
49     Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
50   }
51 
52   FileSystemOptions FileMgrOpts;
53   FileManager FileMgr;
54   IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
55   DiagnosticsEngine Diags;
56   SourceManager SourceMgr;
57   LangOptions LangOpts;
58   std::shared_ptr<TargetOptions> TargetOpts;
59   IntrusiveRefCntPtr<TargetInfo> Target;
60 };
61 
62 TEST_F(SourceManagerTest, isInMemoryBuffersNoSourceLocationInfo) {
63   // Check for invalid source location for each method
64   SourceLocation LocEmpty;
65   bool isWrittenInBuiltInFileFalse = SourceMgr.isWrittenInBuiltinFile(LocEmpty);
66   bool isWrittenInCommandLineFileFalse =
67       SourceMgr.isWrittenInCommandLineFile(LocEmpty);
68   bool isWrittenInScratchSpaceFalse =
69       SourceMgr.isWrittenInScratchSpace(LocEmpty);
70 
71   EXPECT_FALSE(isWrittenInBuiltInFileFalse);
72   EXPECT_FALSE(isWrittenInCommandLineFileFalse);
73   EXPECT_FALSE(isWrittenInScratchSpaceFalse);
74 
75   // Check for valid source location per filename for each method
76   const char *Source = "int x";
77 
78   std::unique_ptr<llvm::MemoryBuffer> BuiltInBuf =
79       llvm::MemoryBuffer::getMemBuffer(Source);
80   FileEntryRef BuiltInFile =
81       FileMgr.getVirtualFileRef("<built-in>", BuiltInBuf->getBufferSize(), 0);
82   SourceMgr.overrideFileContents(BuiltInFile, std::move(BuiltInBuf));
83   FileID BuiltInFileID =
84       SourceMgr.getOrCreateFileID(BuiltInFile, SrcMgr::C_User);
85   SourceMgr.setMainFileID(BuiltInFileID);
86   SourceLocation LocBuiltIn =
87       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
88   bool isWrittenInBuiltInFileTrue =
89       SourceMgr.isWrittenInBuiltinFile(LocBuiltIn);
90 
91   std::unique_ptr<llvm::MemoryBuffer> CommandLineBuf =
92       llvm::MemoryBuffer::getMemBuffer(Source);
93   FileEntryRef CommandLineFile = FileMgr.getVirtualFileRef(
94       "<command line>", CommandLineBuf->getBufferSize(), 0);
95   SourceMgr.overrideFileContents(CommandLineFile, std::move(CommandLineBuf));
96   FileID CommandLineFileID =
97       SourceMgr.getOrCreateFileID(CommandLineFile, SrcMgr::C_User);
98   SourceMgr.setMainFileID(CommandLineFileID);
99   SourceLocation LocCommandLine =
100       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
101   bool isWrittenInCommandLineFileTrue =
102       SourceMgr.isWrittenInCommandLineFile(LocCommandLine);
103 
104   std::unique_ptr<llvm::MemoryBuffer> ScratchSpaceBuf =
105       llvm::MemoryBuffer::getMemBuffer(Source);
106   FileEntryRef ScratchSpaceFile = FileMgr.getVirtualFileRef(
107       "<scratch space>", ScratchSpaceBuf->getBufferSize(), 0);
108   SourceMgr.overrideFileContents(ScratchSpaceFile, std::move(ScratchSpaceBuf));
109   FileID ScratchSpaceFileID =
110       SourceMgr.getOrCreateFileID(ScratchSpaceFile, SrcMgr::C_User);
111   SourceMgr.setMainFileID(ScratchSpaceFileID);
112   SourceLocation LocScratchSpace =
113       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
114   bool isWrittenInScratchSpaceTrue =
115       SourceMgr.isWrittenInScratchSpace(LocScratchSpace);
116 
117   EXPECT_TRUE(isWrittenInBuiltInFileTrue);
118   EXPECT_TRUE(isWrittenInCommandLineFileTrue);
119   EXPECT_TRUE(isWrittenInScratchSpaceTrue);
120 }
121 
122 TEST_F(SourceManagerTest, isInSystemHeader) {
123   // Check for invalid source location
124   SourceLocation LocEmpty;
125   bool isInSystemHeaderFalse = SourceMgr.isInSystemHeader(LocEmpty);
126   ASSERT_FALSE(isInSystemHeaderFalse);
127 }
128 
129 TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
130   const char *source =
131     "#define M(x) [x]\n"
132     "M(foo)";
133   std::unique_ptr<llvm::MemoryBuffer> Buf =
134       llvm::MemoryBuffer::getMemBuffer(source);
135   FileID mainFileID = SourceMgr.createFileID(std::move(Buf));
136   SourceMgr.setMainFileID(mainFileID);
137 
138   TrivialModuleLoader ModLoader;
139   HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
140                           Diags, LangOpts, &*Target);
141   Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
142                   SourceMgr, HeaderInfo, ModLoader,
143                   /*IILookup =*/nullptr,
144                   /*OwnsHeaderSearch =*/false);
145   PP.Initialize(*Target);
146   PP.EnterMainSourceFile();
147 
148   std::vector<Token> toks;
149   PP.LexTokensUntilEOF(&toks);
150 
151   // Make sure we got the tokens that we expected.
152   ASSERT_EQ(3U, toks.size());
153   ASSERT_EQ(tok::l_square, toks[0].getKind());
154   ASSERT_EQ(tok::identifier, toks[1].getKind());
155   ASSERT_EQ(tok::r_square, toks[2].getKind());
156 
157   SourceLocation lsqrLoc = toks[0].getLocation();
158   SourceLocation idLoc = toks[1].getLocation();
159   SourceLocation rsqrLoc = toks[2].getLocation();
160 
161   SourceLocation macroExpStartLoc = SourceMgr.translateLineCol(mainFileID, 2, 1);
162   SourceLocation macroExpEndLoc = SourceMgr.translateLineCol(mainFileID, 2, 6);
163   ASSERT_TRUE(macroExpStartLoc.isFileID());
164   ASSERT_TRUE(macroExpEndLoc.isFileID());
165 
166   SmallString<32> str;
167   ASSERT_EQ("M", PP.getSpelling(macroExpStartLoc, str));
168   ASSERT_EQ(")", PP.getSpelling(macroExpEndLoc, str));
169 
170   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(lsqrLoc, idLoc));
171   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, rsqrLoc));
172   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(macroExpStartLoc, idLoc));
173   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, macroExpEndLoc));
174 }
175 
176 TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithTokenSplit) {
177   const char *main = R"cpp(
178     #define ID(X) X
179     ID(
180       ID(a >> b)
181       c
182     )
183   )cpp";
184 
185   SourceMgr.setMainFileID(
186       SourceMgr.createFileID(llvm::MemoryBuffer::getMemBuffer(main)));
187 
188   TrivialModuleLoader ModLoader;
189   HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
190                           Diags, LangOpts, &*Target);
191   Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
192                   SourceMgr, HeaderInfo, ModLoader,
193                   /*IILookup =*/nullptr,
194                   /*OwnsHeaderSearch =*/false);
195   PP.Initialize(*Target);
196   PP.EnterMainSourceFile();
197   llvm::SmallString<8> Scratch;
198 
199   std::vector<Token> toks;
200   PP.LexTokensUntilEOF(&toks);
201 
202   // Make sure we got the tokens that we expected.
203   ASSERT_EQ(4U, toks.size()) << "a >> b c";
204   // Sanity check their order.
205   for (unsigned I = 0; I < toks.size() - 1; ++I) {
206     EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(toks[I].getLocation(),
207                                                     toks[I + 1].getLocation()));
208     EXPECT_FALSE(SourceMgr.isBeforeInTranslationUnit(toks[I + 1].getLocation(),
209                                                      toks[I].getLocation()));
210   }
211 
212   // Split the >> into two > tokens, as happens when parsing nested templates.
213   unsigned RightShiftIndex = 1;
214   SourceLocation RightShift = toks[RightShiftIndex].getLocation();
215   EXPECT_EQ(">>", Lexer::getSpelling(SourceMgr.getSpellingLoc(RightShift),
216                                      Scratch, SourceMgr, LangOpts));
217   SourceLocation Greater1 = PP.SplitToken(RightShift, /*Length=*/1);
218   SourceLocation Greater2 = RightShift.getLocWithOffset(1);
219   EXPECT_TRUE(Greater1.isMacroID());
220   EXPECT_EQ(">", Lexer::getSpelling(SourceMgr.getSpellingLoc(Greater1), Scratch,
221                                     SourceMgr, LangOpts));
222   EXPECT_EQ(">", Lexer::getSpelling(SourceMgr.getSpellingLoc(Greater2), Scratch,
223                                     SourceMgr, LangOpts));
224   EXPECT_EQ(SourceMgr.getImmediateExpansionRange(Greater1).getBegin(),
225             RightShift);
226 
227   for (unsigned I = 0; I < toks.size(); ++I) {
228     SCOPED_TRACE("Token " + std::to_string(I));
229     // Right-shift is the parent of Greater1, so it compares less.
230     EXPECT_EQ(
231         SourceMgr.isBeforeInTranslationUnit(toks[I].getLocation(), Greater1),
232         I <= RightShiftIndex);
233     EXPECT_EQ(
234         SourceMgr.isBeforeInTranslationUnit(toks[I].getLocation(), Greater2),
235         I <= RightShiftIndex);
236     EXPECT_EQ(
237         SourceMgr.isBeforeInTranslationUnit(Greater1, toks[I].getLocation()),
238         RightShiftIndex < I);
239     EXPECT_EQ(
240         SourceMgr.isBeforeInTranslationUnit(Greater2, toks[I].getLocation()),
241         RightShiftIndex < I);
242   }
243   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Greater1, Greater2));
244   EXPECT_FALSE(SourceMgr.isBeforeInTranslationUnit(Greater2, Greater1));
245 }
246 
247 TEST_F(SourceManagerTest, getColumnNumber) {
248   const char *Source =
249     "int x;\n"
250     "int y;";
251 
252   std::unique_ptr<llvm::MemoryBuffer> Buf =
253       llvm::MemoryBuffer::getMemBuffer(Source);
254   FileID MainFileID = SourceMgr.createFileID(std::move(Buf));
255   SourceMgr.setMainFileID(MainFileID);
256 
257   bool Invalid;
258 
259   Invalid = false;
260   EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, &Invalid));
261   EXPECT_TRUE(!Invalid);
262 
263   Invalid = false;
264   EXPECT_EQ(5U, SourceMgr.getColumnNumber(MainFileID, 4, &Invalid));
265   EXPECT_TRUE(!Invalid);
266 
267   Invalid = false;
268   EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 7, &Invalid));
269   EXPECT_TRUE(!Invalid);
270 
271   Invalid = false;
272   EXPECT_EQ(5U, SourceMgr.getColumnNumber(MainFileID, 11, &Invalid));
273   EXPECT_TRUE(!Invalid);
274 
275   Invalid = false;
276   EXPECT_EQ(7U, SourceMgr.getColumnNumber(MainFileID, strlen(Source),
277                                          &Invalid));
278   EXPECT_TRUE(!Invalid);
279 
280   Invalid = false;
281   SourceMgr.getColumnNumber(MainFileID, strlen(Source)+1, &Invalid);
282   EXPECT_TRUE(Invalid);
283 
284   // Test invalid files
285   Invalid = false;
286   SourceMgr.getColumnNumber(FileID(), 0, &Invalid);
287   EXPECT_TRUE(Invalid);
288 
289   Invalid = false;
290   SourceMgr.getColumnNumber(FileID(), 1, &Invalid);
291   EXPECT_TRUE(Invalid);
292 
293   // Test with no invalid flag.
294   EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, nullptr));
295 }
296 
297 TEST_F(SourceManagerTest, locationPrintTest) {
298   const char *header = "#define IDENTITY(x) x\n";
299 
300   const char *Source = "int x;\n"
301                        "include \"test-header.h\"\n"
302                        "IDENTITY(int y);\n"
303                        "int z;";
304 
305   std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
306       llvm::MemoryBuffer::getMemBuffer(header);
307   std::unique_ptr<llvm::MemoryBuffer> Buf =
308       llvm::MemoryBuffer::getMemBuffer(Source);
309 
310   FileEntryRef SourceFile =
311       FileMgr.getVirtualFileRef("/mainFile.cpp", Buf->getBufferSize(), 0);
312   SourceMgr.overrideFileContents(SourceFile, std::move(Buf));
313 
314   FileEntryRef HeaderFile = FileMgr.getVirtualFileRef(
315       "/test-header.h", HeaderBuf->getBufferSize(), 0);
316   SourceMgr.overrideFileContents(HeaderFile, std::move(HeaderBuf));
317 
318   FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User);
319   FileID HeaderFileID = SourceMgr.getOrCreateFileID(HeaderFile, SrcMgr::C_User);
320   SourceMgr.setMainFileID(MainFileID);
321 
322   auto BeginLoc = SourceMgr.getLocForStartOfFile(MainFileID);
323   auto EndLoc = SourceMgr.getLocForEndOfFile(MainFileID);
324 
325   auto BeginEOLLoc = SourceMgr.translateLineCol(MainFileID, 1, 7);
326 
327   auto HeaderLoc = SourceMgr.getLocForStartOfFile(HeaderFileID);
328 
329   EXPECT_EQ(BeginLoc.printToString(SourceMgr), "/mainFile.cpp:1:1");
330   EXPECT_EQ(EndLoc.printToString(SourceMgr), "/mainFile.cpp:4:7");
331 
332   EXPECT_EQ(BeginEOLLoc.printToString(SourceMgr), "/mainFile.cpp:1:7");
333   EXPECT_EQ(HeaderLoc.printToString(SourceMgr), "/test-header.h:1:1");
334 
335   EXPECT_EQ(SourceRange(BeginLoc, BeginLoc).printToString(SourceMgr),
336             "</mainFile.cpp:1:1>");
337   EXPECT_EQ(SourceRange(BeginLoc, BeginEOLLoc).printToString(SourceMgr),
338             "</mainFile.cpp:1:1, col:7>");
339   EXPECT_EQ(SourceRange(BeginLoc, EndLoc).printToString(SourceMgr),
340             "</mainFile.cpp:1:1, line:4:7>");
341   EXPECT_EQ(SourceRange(BeginLoc, HeaderLoc).printToString(SourceMgr),
342             "</mainFile.cpp:1:1, /test-header.h:1:1>");
343 }
344 
345 TEST_F(SourceManagerTest, getInvalidBOM) {
346   ASSERT_EQ(SrcMgr::ContentCache::getInvalidBOM(""), nullptr);
347   ASSERT_EQ(SrcMgr::ContentCache::getInvalidBOM("\x00\x00\x00"), nullptr);
348   ASSERT_EQ(SrcMgr::ContentCache::getInvalidBOM("\xFF\xFF\xFF"), nullptr);
349   ASSERT_EQ(SrcMgr::ContentCache::getInvalidBOM("#include <iostream>"),
350             nullptr);
351 
352   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
353                 "\xFE\xFF#include <iostream>")),
354             "UTF-16 (BE)");
355   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
356                 "\xFF\xFE#include <iostream>")),
357             "UTF-16 (LE)");
358   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
359                 "\x2B\x2F\x76#include <iostream>")),
360             "UTF-7");
361   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
362                 "\xF7\x64\x4C#include <iostream>")),
363             "UTF-1");
364   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
365                 "\xDD\x73\x66\x73#include <iostream>")),
366             "UTF-EBCDIC");
367   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
368                 "\x0E\xFE\xFF#include <iostream>")),
369             "SCSU");
370   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
371                 "\xFB\xEE\x28#include <iostream>")),
372             "BOCU-1");
373   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
374                 "\x84\x31\x95\x33#include <iostream>")),
375             "GB-18030");
376   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
377                 llvm::StringLiteral::withInnerNUL(
378                     "\x00\x00\xFE\xFF#include <iostream>"))),
379             "UTF-32 (BE)");
380   ASSERT_EQ(StringRef(SrcMgr::ContentCache::getInvalidBOM(
381                 llvm::StringLiteral::withInnerNUL(
382                     "\xFF\xFE\x00\x00#include <iostream>"))),
383             "UTF-32 (LE)");
384 }
385 
386 // Regression test - there was an out of bound access for buffers not terminated by zero.
387 TEST_F(SourceManagerTest, getLineNumber) {
388   const unsigned pageSize = llvm::sys::Process::getPageSizeEstimate();
389   std::unique_ptr<char[]> source(new char[pageSize]);
390   for(unsigned i = 0; i < pageSize; ++i) {
391     source[i] = 'a';
392   }
393 
394   std::unique_ptr<llvm::MemoryBuffer> Buf =
395       llvm::MemoryBuffer::getMemBuffer(
396         llvm::MemoryBufferRef(
397           llvm::StringRef(source.get(), 3), "whatever"
398         ),
399         false
400       );
401 
402   FileID mainFileID = SourceMgr.createFileID(std::move(Buf));
403   SourceMgr.setMainFileID(mainFileID);
404 
405   ASSERT_NO_FATAL_FAILURE(SourceMgr.getLineNumber(mainFileID, 1, nullptr));
406 }
407 
408 struct FakeExternalSLocEntrySource : ExternalSLocEntrySource {
409   bool ReadSLocEntry(int ID) override { return {}; }
410   int getSLocEntryID(SourceLocation::UIntTy SLocOffset) override { return 0; }
411   std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override {
412     return {};
413   }
414 };
415 
416 TEST_F(SourceManagerTest, loadedSLocEntryIsInTheSameTranslationUnit) {
417   auto InSameTU = [=](int LID, int RID) {
418     return SourceMgr.isInTheSameTranslationUnitImpl(
419         std::make_pair(SourceManagerTestHelper::makeFileID(LID), 0),
420         std::make_pair(SourceManagerTestHelper::makeFileID(RID), 0));
421   };
422 
423   FakeExternalSLocEntrySource ExternalSource;
424   SourceMgr.setExternalSLocEntrySource(&ExternalSource);
425 
426   unsigned ANumFileIDs = 10;
427   auto [AFirstID, X] = SourceMgr.AllocateLoadedSLocEntries(ANumFileIDs, 10);
428   int ALastID = AFirstID + ANumFileIDs - 1;
429   // FileID(-11)..FileID(-2)
430   ASSERT_EQ(AFirstID, -11);
431   ASSERT_EQ(ALastID, -2);
432 
433   unsigned BNumFileIDs = 20;
434   auto [BFirstID, Y] = SourceMgr.AllocateLoadedSLocEntries(BNumFileIDs, 20);
435   int BLastID = BFirstID + BNumFileIDs - 1;
436   // FileID(-31)..FileID(-12)
437   ASSERT_EQ(BFirstID, -31);
438   ASSERT_EQ(BLastID, -12);
439 
440   // Loaded vs local.
441   EXPECT_FALSE(InSameTU(-2, 1));
442 
443   // Loaded in the same allocation A.
444   EXPECT_TRUE(InSameTU(-11, -2));
445   EXPECT_TRUE(InSameTU(-11, -6));
446 
447   // Loaded in the same allocation B.
448   EXPECT_TRUE(InSameTU(-31, -12));
449   EXPECT_TRUE(InSameTU(-31, -16));
450 
451   // Loaded from different allocations A and B.
452   EXPECT_FALSE(InSameTU(-12, -11));
453 }
454 
455 #if defined(LLVM_ON_UNIX)
456 
457 // A single SourceManager instance is sometimes reused across multiple
458 // compilations. This test makes sure we're resetting caches built for tracking
459 // include locations that are based on FileIDs, to make sure we don't report
460 // wrong include locations when FileIDs coincide between two different runs.
461 TEST_F(SourceManagerTest, ResetsIncludeLocMap) {
462   auto ParseFile = [&] {
463     TrivialModuleLoader ModLoader;
464     HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
465                             Diags, LangOpts, &*Target);
466     Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
467                     SourceMgr, HeaderInfo, ModLoader,
468                     /*IILookup =*/nullptr,
469                     /*OwnsHeaderSearch =*/false);
470     PP.Initialize(*Target);
471     PP.EnterMainSourceFile();
472     PP.LexTokensUntilEOF();
473     EXPECT_FALSE(Diags.hasErrorOccurred());
474   };
475 
476   auto Buf = llvm::MemoryBuffer::getMemBuffer("");
477   FileEntryRef HeaderFile =
478       FileMgr.getVirtualFileRef("/foo.h", Buf->getBufferSize(), 0);
479   SourceMgr.overrideFileContents(HeaderFile, std::move(Buf));
480 
481   Buf = llvm::MemoryBuffer::getMemBuffer(R"cpp(#include "/foo.h")cpp");
482   FileEntryRef BarFile =
483       FileMgr.getVirtualFileRef("/bar.h", Buf->getBufferSize(), 0);
484   SourceMgr.overrideFileContents(BarFile, std::move(Buf));
485   SourceMgr.createFileID(BarFile, {}, clang::SrcMgr::C_User);
486 
487   Buf = llvm::MemoryBuffer::getMemBuffer(R"cpp(#include "/foo.h")cpp");
488   FileID MFID = SourceMgr.createFileID(std::move(Buf));
489   SourceMgr.setMainFileID(MFID);
490 
491   ParseFile();
492   auto FooFID = SourceMgr.getOrCreateFileID(HeaderFile, clang::SrcMgr::C_User);
493   auto IncFID = SourceMgr.getDecomposedIncludedLoc(FooFID).first;
494   EXPECT_EQ(IncFID, MFID);
495 
496   // Clean up source-manager state before we start next parse.
497   SourceMgr.clearIDTables();
498 
499   // Set up a new main file.
500   Buf = llvm::MemoryBuffer::getMemBuffer(R"cpp(
501   // silly comment 42
502   #include "/bar.h")cpp");
503   MFID = SourceMgr.createFileID(std::move(Buf));
504   SourceMgr.setMainFileID(MFID);
505 
506   ParseFile();
507   // Make sure foo.h got the same file-id in both runs.
508   EXPECT_EQ(FooFID,
509             SourceMgr.getOrCreateFileID(HeaderFile, clang::SrcMgr::C_User));
510   auto BarFID = SourceMgr.getOrCreateFileID(BarFile, clang::SrcMgr::C_User);
511   IncFID = SourceMgr.getDecomposedIncludedLoc(FooFID).first;
512   // Check that includer is bar.h during this run.
513   EXPECT_EQ(IncFID, BarFID);
514 }
515 
516 TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
517   const char *header =
518     "#define FM(x,y) x\n";
519 
520   const char *main =
521     "#include \"/test-header.h\"\n"
522     "#define VAL 0\n"
523     "FM(VAL,0)\n"
524     "FM(0,VAL)\n"
525     "FM(FM(0,VAL),0)\n"
526     "#define CONCAT(X, Y) X##Y\n"
527     "CONCAT(1,1)\n";
528 
529   std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
530       llvm::MemoryBuffer::getMemBuffer(header);
531   std::unique_ptr<llvm::MemoryBuffer> MainBuf =
532       llvm::MemoryBuffer::getMemBuffer(main);
533   FileID mainFileID = SourceMgr.createFileID(std::move(MainBuf));
534   SourceMgr.setMainFileID(mainFileID);
535 
536   FileEntryRef headerFile = FileMgr.getVirtualFileRef(
537       "/test-header.h", HeaderBuf->getBufferSize(), 0);
538   SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
539 
540   TrivialModuleLoader ModLoader;
541   HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
542                           Diags, LangOpts, &*Target);
543 
544   Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
545                   SourceMgr, HeaderInfo, ModLoader,
546                   /*IILookup =*/nullptr,
547                   /*OwnsHeaderSearch =*/false);
548   // Ensure we can get expanded locations in presence of implicit includes.
549   // These are different than normal includes since predefines buffer doesn't
550   // have a valid insertion location.
551   PP.setPredefines("#include \"/implicit-header.h\"");
552   FileMgr.getVirtualFileRef("/implicit-header.h", 0, 0);
553   PP.Initialize(*Target);
554   PP.EnterMainSourceFile();
555 
556   std::vector<Token> toks;
557   PP.LexTokensUntilEOF(&toks);
558 
559   // Make sure we got the tokens that we expected.
560   ASSERT_EQ(4U, toks.size());
561   ASSERT_EQ(tok::numeric_constant, toks[0].getKind());
562   ASSERT_EQ(tok::numeric_constant, toks[1].getKind());
563   ASSERT_EQ(tok::numeric_constant, toks[2].getKind());
564   ASSERT_EQ(tok::numeric_constant, toks[3].getKind());
565 
566   SourceLocation defLoc = SourceMgr.translateLineCol(mainFileID, 2, 13);
567   SourceLocation loc1 = SourceMgr.translateLineCol(mainFileID, 3, 8);
568   SourceLocation loc2 = SourceMgr.translateLineCol(mainFileID, 4, 4);
569   SourceLocation loc3 = SourceMgr.translateLineCol(mainFileID, 5, 7);
570   SourceLocation defLoc2 = SourceMgr.translateLineCol(mainFileID, 6, 22);
571   defLoc = SourceMgr.getMacroArgExpandedLocation(defLoc);
572   loc1 = SourceMgr.getMacroArgExpandedLocation(loc1);
573   loc2 = SourceMgr.getMacroArgExpandedLocation(loc2);
574   loc3 = SourceMgr.getMacroArgExpandedLocation(loc3);
575   defLoc2 = SourceMgr.getMacroArgExpandedLocation(defLoc2);
576 
577   EXPECT_TRUE(defLoc.isFileID());
578   EXPECT_TRUE(loc1.isFileID());
579   EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc2));
580   EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc3));
581   EXPECT_EQ(loc2, toks[1].getLocation());
582   EXPECT_EQ(loc3, toks[2].getLocation());
583   EXPECT_TRUE(defLoc2.isFileID());
584 }
585 
586 namespace {
587 
588 struct MacroAction {
589   enum Kind { kExpansion, kDefinition, kUnDefinition};
590 
591   SourceLocation Loc;
592   std::string Name;
593   LLVM_PREFERRED_TYPE(Kind)
594   unsigned MAKind : 3;
595 
596   MacroAction(SourceLocation Loc, StringRef Name, unsigned K)
597       : Loc(Loc), Name(std::string(Name)), MAKind(K) {}
598 
599   bool isExpansion() const { return MAKind == kExpansion; }
600   bool isDefinition() const { return MAKind & kDefinition; }
601   bool isUnDefinition() const { return MAKind & kUnDefinition; }
602 };
603 
604 class MacroTracker : public PPCallbacks {
605   std::vector<MacroAction> &Macros;
606 
607 public:
608   explicit MacroTracker(std::vector<MacroAction> &Macros) : Macros(Macros) { }
609 
610   void MacroDefined(const Token &MacroNameTok,
611                     const MacroDirective *MD) override {
612     Macros.push_back(MacroAction(MD->getLocation(),
613                                  MacroNameTok.getIdentifierInfo()->getName(),
614                                  MacroAction::kDefinition));
615   }
616   void MacroUndefined(const Token &MacroNameTok,
617                       const MacroDefinition &MD,
618                       const MacroDirective  *UD) override {
619     Macros.push_back(
620         MacroAction(UD ? UD->getLocation() : SourceLocation(),
621                     MacroNameTok.getIdentifierInfo()->getName(),
622                     UD ? MacroAction::kDefinition | MacroAction::kUnDefinition
623                        : MacroAction::kUnDefinition));
624   }
625   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
626                     SourceRange Range, const MacroArgs *Args) override {
627     Macros.push_back(MacroAction(MacroNameTok.getLocation(),
628                                  MacroNameTok.getIdentifierInfo()->getName(),
629                                  MacroAction::kExpansion));
630   }
631 };
632 
633 }
634 
635 TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
636   const char *header =
637     "#define MACRO_IN_INCLUDE 0\n"
638     "#define MACRO_DEFINED\n"
639     "#undef MACRO_DEFINED\n"
640     "#undef MACRO_UNDEFINED\n";
641 
642   const char *main =
643     "#define M(x) x\n"
644     "#define INC \"/test-header.h\"\n"
645     "#include M(INC)\n"
646     "#define INC2 </test-header.h>\n"
647     "#include M(INC2)\n";
648 
649   std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
650       llvm::MemoryBuffer::getMemBuffer(header);
651   std::unique_ptr<llvm::MemoryBuffer> MainBuf =
652       llvm::MemoryBuffer::getMemBuffer(main);
653   SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(MainBuf)));
654 
655   FileEntryRef headerFile = FileMgr.getVirtualFileRef(
656       "/test-header.h", HeaderBuf->getBufferSize(), 0);
657   SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
658 
659   TrivialModuleLoader ModLoader;
660   HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
661                           Diags, LangOpts, &*Target);
662   Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
663                   SourceMgr, HeaderInfo, ModLoader,
664                   /*IILookup =*/nullptr,
665                   /*OwnsHeaderSearch =*/false);
666   PP.Initialize(*Target);
667 
668   std::vector<MacroAction> Macros;
669   PP.addPPCallbacks(std::make_unique<MacroTracker>(Macros));
670 
671   PP.EnterMainSourceFile();
672 
673   std::vector<Token> toks;
674   PP.LexTokensUntilEOF(&toks);
675 
676   // Make sure we got the tokens that we expected.
677   ASSERT_EQ(0U, toks.size());
678 
679   ASSERT_EQ(15U, Macros.size());
680   // #define M(x) x
681   ASSERT_TRUE(Macros[0].isDefinition());
682   ASSERT_EQ("M", Macros[0].Name);
683   // #define INC "/test-header.h"
684   ASSERT_TRUE(Macros[1].isDefinition());
685   ASSERT_EQ("INC", Macros[1].Name);
686   // M expansion in #include M(INC)
687   ASSERT_FALSE(Macros[2].isDefinition());
688   ASSERT_EQ("M", Macros[2].Name);
689   // INC expansion in #include M(INC)
690   ASSERT_TRUE(Macros[3].isExpansion());
691   ASSERT_EQ("INC", Macros[3].Name);
692   // #define MACRO_IN_INCLUDE 0
693   ASSERT_TRUE(Macros[4].isDefinition());
694   ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
695   // #define MACRO_DEFINED
696   ASSERT_TRUE(Macros[5].isDefinition());
697   ASSERT_FALSE(Macros[5].isUnDefinition());
698   ASSERT_EQ("MACRO_DEFINED", Macros[5].Name);
699   // #undef MACRO_DEFINED
700   ASSERT_TRUE(Macros[6].isDefinition());
701   ASSERT_TRUE(Macros[6].isUnDefinition());
702   ASSERT_EQ("MACRO_DEFINED", Macros[6].Name);
703   // #undef MACRO_UNDEFINED
704   ASSERT_FALSE(Macros[7].isDefinition());
705   ASSERT_TRUE(Macros[7].isUnDefinition());
706   ASSERT_EQ("MACRO_UNDEFINED", Macros[7].Name);
707   // #define INC2 </test-header.h>
708   ASSERT_TRUE(Macros[8].isDefinition());
709   ASSERT_EQ("INC2", Macros[8].Name);
710   // M expansion in #include M(INC2)
711   ASSERT_FALSE(Macros[9].isDefinition());
712   ASSERT_EQ("M", Macros[9].Name);
713   // INC2 expansion in #include M(INC2)
714   ASSERT_TRUE(Macros[10].isExpansion());
715   ASSERT_EQ("INC2", Macros[10].Name);
716   // #define MACRO_IN_INCLUDE 0
717   ASSERT_TRUE(Macros[11].isDefinition());
718   ASSERT_EQ("MACRO_IN_INCLUDE", Macros[11].Name);
719 
720   // The INC expansion in #include M(INC) comes before the first
721   // MACRO_IN_INCLUDE definition of the included file.
722   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[3].Loc, Macros[4].Loc));
723 
724   // The INC2 expansion in #include M(INC2) comes before the second
725   // MACRO_IN_INCLUDE definition of the included file.
726   EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
727 }
728 
729 TEST_F(SourceManagerTest, isMainFile) {
730   const char *Source = "int x;";
731 
732   std::unique_ptr<llvm::MemoryBuffer> Buf =
733       llvm::MemoryBuffer::getMemBuffer(Source);
734   FileEntryRef SourceFile =
735       FileMgr.getVirtualFileRef("mainFile.cpp", Buf->getBufferSize(), 0);
736   SourceMgr.overrideFileContents(SourceFile, std::move(Buf));
737 
738   std::unique_ptr<llvm::MemoryBuffer> Buf2 =
739       llvm::MemoryBuffer::getMemBuffer(Source);
740   FileEntryRef SecondFile =
741       FileMgr.getVirtualFileRef("file2.cpp", Buf2->getBufferSize(), 0);
742   SourceMgr.overrideFileContents(SecondFile, std::move(Buf2));
743 
744   FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User);
745   SourceMgr.setMainFileID(MainFileID);
746 
747   EXPECT_TRUE(SourceMgr.isMainFile(*SourceFile));
748   EXPECT_TRUE(SourceMgr.isMainFile(*SourceFile));
749   EXPECT_FALSE(SourceMgr.isMainFile(*SecondFile));
750 }
751 
752 #endif
753 
754 } // anonymous namespace
755