SourceManagerTest.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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. #include "clang/Basic/SourceManager.h"
  9. #include "clang/Basic/Diagnostic.h"
  10. #include "clang/Basic/DiagnosticOptions.h"
  11. #include "clang/Basic/FileManager.h"
  12. #include "clang/Basic/LangOptions.h"
  13. #include "clang/Basic/TargetInfo.h"
  14. #include "clang/Basic/TargetOptions.h"
  15. #include "clang/Lex/HeaderSearch.h"
  16. #include "clang/Lex/HeaderSearchOptions.h"
  17. #include "clang/Lex/ModuleLoader.h"
  18. #include "clang/Lex/Preprocessor.h"
  19. #include "clang/Lex/PreprocessorOptions.h"
  20. #include "llvm/ADT/SmallString.h"
  21. #include "llvm/Config/llvm-config.h"
  22. #include "gtest/gtest.h"
  23. using namespace clang;
  24. namespace {
  25. // The test fixture.
  26. class SourceManagerTest : public ::testing::Test {
  27. protected:
  28. SourceManagerTest()
  29. : FileMgr(FileMgrOpts),
  30. DiagID(new DiagnosticIDs()),
  31. Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
  32. SourceMgr(Diags, FileMgr),
  33. TargetOpts(new TargetOptions) {
  34. TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
  35. Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
  36. }
  37. FileSystemOptions FileMgrOpts;
  38. FileManager FileMgr;
  39. IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
  40. DiagnosticsEngine Diags;
  41. SourceManager SourceMgr;
  42. LangOptions LangOpts;
  43. std::shared_ptr<TargetOptions> TargetOpts;
  44. IntrusiveRefCntPtr<TargetInfo> Target;
  45. };
  46. TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
  47. const char *source =
  48. "#define M(x) [x]\n"
  49. "M(foo)";
  50. std::unique_ptr<llvm::MemoryBuffer> Buf =
  51. llvm::MemoryBuffer::getMemBuffer(source);
  52. FileID mainFileID = SourceMgr.createFileID(std::move(Buf));
  53. SourceMgr.setMainFileID(mainFileID);
  54. TrivialModuleLoader ModLoader;
  55. HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
  56. Diags, LangOpts, &*Target);
  57. Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
  58. SourceMgr, HeaderInfo, ModLoader,
  59. /*IILookup =*/nullptr,
  60. /*OwnsHeaderSearch =*/false);
  61. PP.Initialize(*Target);
  62. PP.EnterMainSourceFile();
  63. std::vector<Token> toks;
  64. while (1) {
  65. Token tok;
  66. PP.Lex(tok);
  67. if (tok.is(tok::eof))
  68. break;
  69. toks.push_back(tok);
  70. }
  71. // Make sure we got the tokens that we expected.
  72. ASSERT_EQ(3U, toks.size());
  73. ASSERT_EQ(tok::l_square, toks[0].getKind());
  74. ASSERT_EQ(tok::identifier, toks[1].getKind());
  75. ASSERT_EQ(tok::r_square, toks[2].getKind());
  76. SourceLocation lsqrLoc = toks[0].getLocation();
  77. SourceLocation idLoc = toks[1].getLocation();
  78. SourceLocation rsqrLoc = toks[2].getLocation();
  79. SourceLocation macroExpStartLoc = SourceMgr.translateLineCol(mainFileID, 2, 1);
  80. SourceLocation macroExpEndLoc = SourceMgr.translateLineCol(mainFileID, 2, 6);
  81. ASSERT_TRUE(macroExpStartLoc.isFileID());
  82. ASSERT_TRUE(macroExpEndLoc.isFileID());
  83. SmallString<32> str;
  84. ASSERT_EQ("M", PP.getSpelling(macroExpStartLoc, str));
  85. ASSERT_EQ(")", PP.getSpelling(macroExpEndLoc, str));
  86. EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(lsqrLoc, idLoc));
  87. EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, rsqrLoc));
  88. EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(macroExpStartLoc, idLoc));
  89. EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, macroExpEndLoc));
  90. }
  91. TEST_F(SourceManagerTest, getColumnNumber) {
  92. const char *Source =
  93. "int x;\n"
  94. "int y;";
  95. std::unique_ptr<llvm::MemoryBuffer> Buf =
  96. llvm::MemoryBuffer::getMemBuffer(Source);
  97. FileID MainFileID = SourceMgr.createFileID(std::move(Buf));
  98. SourceMgr.setMainFileID(MainFileID);
  99. bool Invalid;
  100. Invalid = false;
  101. EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, &Invalid));
  102. EXPECT_TRUE(!Invalid);
  103. Invalid = false;
  104. EXPECT_EQ(5U, SourceMgr.getColumnNumber(MainFileID, 4, &Invalid));
  105. EXPECT_TRUE(!Invalid);
  106. Invalid = false;
  107. EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 7, &Invalid));
  108. EXPECT_TRUE(!Invalid);
  109. Invalid = false;
  110. EXPECT_EQ(5U, SourceMgr.getColumnNumber(MainFileID, 11, &Invalid));
  111. EXPECT_TRUE(!Invalid);
  112. Invalid = false;
  113. EXPECT_EQ(7U, SourceMgr.getColumnNumber(MainFileID, strlen(Source),
  114. &Invalid));
  115. EXPECT_TRUE(!Invalid);
  116. Invalid = false;
  117. SourceMgr.getColumnNumber(MainFileID, strlen(Source)+1, &Invalid);
  118. EXPECT_TRUE(Invalid);
  119. // Test invalid files
  120. Invalid = false;
  121. SourceMgr.getColumnNumber(FileID(), 0, &Invalid);
  122. EXPECT_TRUE(Invalid);
  123. Invalid = false;
  124. SourceMgr.getColumnNumber(FileID(), 1, &Invalid);
  125. EXPECT_TRUE(Invalid);
  126. // Test with no invalid flag.
  127. EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, nullptr));
  128. }
  129. TEST_F(SourceManagerTest, locationPrintTest) {
  130. const char *header = "#define IDENTITY(x) x\n";
  131. const char *Source = "int x;\n"
  132. "include \"test-header.h\"\n"
  133. "IDENTITY(int y);\n"
  134. "int z;";
  135. std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
  136. llvm::MemoryBuffer::getMemBuffer(header);
  137. std::unique_ptr<llvm::MemoryBuffer> Buf =
  138. llvm::MemoryBuffer::getMemBuffer(Source);
  139. const FileEntry *SourceFile =
  140. FileMgr.getVirtualFile("/mainFile.cpp", Buf->getBufferSize(), 0);
  141. SourceMgr.overrideFileContents(SourceFile, std::move(Buf));
  142. const FileEntry *HeaderFile =
  143. FileMgr.getVirtualFile("/test-header.h", HeaderBuf->getBufferSize(), 0);
  144. SourceMgr.overrideFileContents(HeaderFile, std::move(HeaderBuf));
  145. FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User);
  146. FileID HeaderFileID = SourceMgr.getOrCreateFileID(HeaderFile, SrcMgr::C_User);
  147. SourceMgr.setMainFileID(MainFileID);
  148. auto BeginLoc = SourceMgr.getLocForStartOfFile(MainFileID);
  149. auto EndLoc = SourceMgr.getLocForEndOfFile(MainFileID);
  150. auto BeginEOLLoc = SourceMgr.translateLineCol(MainFileID, 1, 7);
  151. auto HeaderLoc = SourceMgr.getLocForStartOfFile(HeaderFileID);
  152. EXPECT_EQ(BeginLoc.printToString(SourceMgr), "/mainFile.cpp:1:1");
  153. EXPECT_EQ(EndLoc.printToString(SourceMgr), "/mainFile.cpp:4:7");
  154. EXPECT_EQ(BeginEOLLoc.printToString(SourceMgr), "/mainFile.cpp:1:7");
  155. EXPECT_EQ(HeaderLoc.printToString(SourceMgr), "/test-header.h:1:1");
  156. EXPECT_EQ(SourceRange(BeginLoc, BeginLoc).printToString(SourceMgr),
  157. "</mainFile.cpp:1:1>");
  158. EXPECT_EQ(SourceRange(BeginLoc, BeginEOLLoc).printToString(SourceMgr),
  159. "</mainFile.cpp:1:1, col:7>");
  160. EXPECT_EQ(SourceRange(BeginLoc, EndLoc).printToString(SourceMgr),
  161. "</mainFile.cpp:1:1, line:4:7>");
  162. EXPECT_EQ(SourceRange(BeginLoc, HeaderLoc).printToString(SourceMgr),
  163. "</mainFile.cpp:1:1, /test-header.h:1:1>");
  164. }
  165. #if defined(LLVM_ON_UNIX)
  166. TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
  167. const char *header =
  168. "#define FM(x,y) x\n";
  169. const char *main =
  170. "#include \"/test-header.h\"\n"
  171. "#define VAL 0\n"
  172. "FM(VAL,0)\n"
  173. "FM(0,VAL)\n"
  174. "FM(FM(0,VAL),0)\n"
  175. "#define CONCAT(X, Y) X##Y\n"
  176. "CONCAT(1,1)\n";
  177. std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
  178. llvm::MemoryBuffer::getMemBuffer(header);
  179. std::unique_ptr<llvm::MemoryBuffer> MainBuf =
  180. llvm::MemoryBuffer::getMemBuffer(main);
  181. FileID mainFileID = SourceMgr.createFileID(std::move(MainBuf));
  182. SourceMgr.setMainFileID(mainFileID);
  183. const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
  184. HeaderBuf->getBufferSize(), 0);
  185. SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
  186. TrivialModuleLoader ModLoader;
  187. HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
  188. Diags, LangOpts, &*Target);
  189. Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
  190. SourceMgr, HeaderInfo, ModLoader,
  191. /*IILookup =*/nullptr,
  192. /*OwnsHeaderSearch =*/false);
  193. PP.Initialize(*Target);
  194. PP.EnterMainSourceFile();
  195. std::vector<Token> toks;
  196. while (1) {
  197. Token tok;
  198. PP.Lex(tok);
  199. if (tok.is(tok::eof))
  200. break;
  201. toks.push_back(tok);
  202. }
  203. // Make sure we got the tokens that we expected.
  204. ASSERT_EQ(4U, toks.size());
  205. ASSERT_EQ(tok::numeric_constant, toks[0].getKind());
  206. ASSERT_EQ(tok::numeric_constant, toks[1].getKind());
  207. ASSERT_EQ(tok::numeric_constant, toks[2].getKind());
  208. ASSERT_EQ(tok::numeric_constant, toks[3].getKind());
  209. SourceLocation defLoc = SourceMgr.translateLineCol(mainFileID, 2, 13);
  210. SourceLocation loc1 = SourceMgr.translateLineCol(mainFileID, 3, 8);
  211. SourceLocation loc2 = SourceMgr.translateLineCol(mainFileID, 4, 4);
  212. SourceLocation loc3 = SourceMgr.translateLineCol(mainFileID, 5, 7);
  213. SourceLocation defLoc2 = SourceMgr.translateLineCol(mainFileID, 6, 22);
  214. defLoc = SourceMgr.getMacroArgExpandedLocation(defLoc);
  215. loc1 = SourceMgr.getMacroArgExpandedLocation(loc1);
  216. loc2 = SourceMgr.getMacroArgExpandedLocation(loc2);
  217. loc3 = SourceMgr.getMacroArgExpandedLocation(loc3);
  218. defLoc2 = SourceMgr.getMacroArgExpandedLocation(defLoc2);
  219. EXPECT_TRUE(defLoc.isFileID());
  220. EXPECT_TRUE(loc1.isFileID());
  221. EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc2));
  222. EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc3));
  223. EXPECT_EQ(loc2, toks[1].getLocation());
  224. EXPECT_EQ(loc3, toks[2].getLocation());
  225. EXPECT_TRUE(defLoc2.isFileID());
  226. }
  227. namespace {
  228. struct MacroAction {
  229. enum Kind { kExpansion, kDefinition, kUnDefinition};
  230. SourceLocation Loc;
  231. std::string Name;
  232. unsigned MAKind : 3;
  233. MacroAction(SourceLocation Loc, StringRef Name, unsigned K)
  234. : Loc(Loc), Name(Name), MAKind(K) { }
  235. bool isExpansion() const { return MAKind == kExpansion; }
  236. bool isDefinition() const { return MAKind & kDefinition; }
  237. bool isUnDefinition() const { return MAKind & kUnDefinition; }
  238. };
  239. class MacroTracker : public PPCallbacks {
  240. std::vector<MacroAction> &Macros;
  241. public:
  242. explicit MacroTracker(std::vector<MacroAction> &Macros) : Macros(Macros) { }
  243. void MacroDefined(const Token &MacroNameTok,
  244. const MacroDirective *MD) override {
  245. Macros.push_back(MacroAction(MD->getLocation(),
  246. MacroNameTok.getIdentifierInfo()->getName(),
  247. MacroAction::kDefinition));
  248. }
  249. void MacroUndefined(const Token &MacroNameTok,
  250. const MacroDefinition &MD,
  251. const MacroDirective *UD) override {
  252. Macros.push_back(
  253. MacroAction(UD ? UD->getLocation() : SourceLocation(),
  254. MacroNameTok.getIdentifierInfo()->getName(),
  255. UD ? MacroAction::kDefinition | MacroAction::kUnDefinition
  256. : MacroAction::kUnDefinition));
  257. }
  258. void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
  259. SourceRange Range, const MacroArgs *Args) override {
  260. Macros.push_back(MacroAction(MacroNameTok.getLocation(),
  261. MacroNameTok.getIdentifierInfo()->getName(),
  262. MacroAction::kExpansion));
  263. }
  264. };
  265. }
  266. TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
  267. const char *header =
  268. "#define MACRO_IN_INCLUDE 0\n"
  269. "#define MACRO_DEFINED\n"
  270. "#undef MACRO_DEFINED\n"
  271. "#undef MACRO_UNDEFINED\n";
  272. const char *main =
  273. "#define M(x) x\n"
  274. "#define INC \"/test-header.h\"\n"
  275. "#include M(INC)\n"
  276. "#define INC2 </test-header.h>\n"
  277. "#include M(INC2)\n";
  278. std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
  279. llvm::MemoryBuffer::getMemBuffer(header);
  280. std::unique_ptr<llvm::MemoryBuffer> MainBuf =
  281. llvm::MemoryBuffer::getMemBuffer(main);
  282. SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(MainBuf)));
  283. const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
  284. HeaderBuf->getBufferSize(), 0);
  285. SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
  286. TrivialModuleLoader ModLoader;
  287. HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
  288. Diags, LangOpts, &*Target);
  289. Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
  290. SourceMgr, HeaderInfo, ModLoader,
  291. /*IILookup =*/nullptr,
  292. /*OwnsHeaderSearch =*/false);
  293. PP.Initialize(*Target);
  294. std::vector<MacroAction> Macros;
  295. PP.addPPCallbacks(llvm::make_unique<MacroTracker>(Macros));
  296. PP.EnterMainSourceFile();
  297. std::vector<Token> toks;
  298. while (1) {
  299. Token tok;
  300. PP.Lex(tok);
  301. if (tok.is(tok::eof))
  302. break;
  303. toks.push_back(tok);
  304. }
  305. // Make sure we got the tokens that we expected.
  306. ASSERT_EQ(0U, toks.size());
  307. ASSERT_EQ(15U, Macros.size());
  308. // #define M(x) x
  309. ASSERT_TRUE(Macros[0].isDefinition());
  310. ASSERT_EQ("M", Macros[0].Name);
  311. // #define INC "/test-header.h"
  312. ASSERT_TRUE(Macros[1].isDefinition());
  313. ASSERT_EQ("INC", Macros[1].Name);
  314. // M expansion in #include M(INC)
  315. ASSERT_FALSE(Macros[2].isDefinition());
  316. ASSERT_EQ("M", Macros[2].Name);
  317. // INC expansion in #include M(INC)
  318. ASSERT_TRUE(Macros[3].isExpansion());
  319. ASSERT_EQ("INC", Macros[3].Name);
  320. // #define MACRO_IN_INCLUDE 0
  321. ASSERT_TRUE(Macros[4].isDefinition());
  322. ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
  323. // #define MACRO_DEFINED
  324. ASSERT_TRUE(Macros[5].isDefinition());
  325. ASSERT_FALSE(Macros[5].isUnDefinition());
  326. ASSERT_EQ("MACRO_DEFINED", Macros[5].Name);
  327. // #undef MACRO_DEFINED
  328. ASSERT_TRUE(Macros[6].isDefinition());
  329. ASSERT_TRUE(Macros[6].isUnDefinition());
  330. ASSERT_EQ("MACRO_DEFINED", Macros[6].Name);
  331. // #undef MACRO_UNDEFINED
  332. ASSERT_FALSE(Macros[7].isDefinition());
  333. ASSERT_TRUE(Macros[7].isUnDefinition());
  334. ASSERT_EQ("MACRO_UNDEFINED", Macros[7].Name);
  335. // #define INC2 </test-header.h>
  336. ASSERT_TRUE(Macros[8].isDefinition());
  337. ASSERT_EQ("INC2", Macros[8].Name);
  338. // M expansion in #include M(INC2)
  339. ASSERT_FALSE(Macros[9].isDefinition());
  340. ASSERT_EQ("M", Macros[9].Name);
  341. // INC2 expansion in #include M(INC2)
  342. ASSERT_TRUE(Macros[10].isExpansion());
  343. ASSERT_EQ("INC2", Macros[10].Name);
  344. // #define MACRO_IN_INCLUDE 0
  345. ASSERT_TRUE(Macros[11].isDefinition());
  346. ASSERT_EQ("MACRO_IN_INCLUDE", Macros[11].Name);
  347. // The INC expansion in #include M(INC) comes before the first
  348. // MACRO_IN_INCLUDE definition of the included file.
  349. EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[3].Loc, Macros[4].Loc));
  350. // The INC2 expansion in #include M(INC2) comes before the second
  351. // MACRO_IN_INCLUDE definition of the included file.
  352. EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
  353. }
  354. #endif
  355. } // anonymous namespace