LibclangTest.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. //===- unittests/libclang/LibclangTest.cpp --- libclang 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-c/Index.h"
  9. #include "llvm/ADT/StringRef.h"
  10. #include "llvm/Support/Debug.h"
  11. #include "llvm/Support/FileSystem.h"
  12. #include "llvm/Support/Path.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. #include "gtest/gtest.h"
  15. #include "TestUtils.h"
  16. #include <fstream>
  17. #include <functional>
  18. #include <map>
  19. #include <memory>
  20. #include <set>
  21. #define DEBUG_TYPE "libclang-test"
  22. TEST(libclang, clang_parseTranslationUnit2_InvalidArgs) {
  23. EXPECT_EQ(CXError_InvalidArguments,
  24. clang_parseTranslationUnit2(nullptr, nullptr, nullptr, 0, nullptr,
  25. 0, 0, nullptr));
  26. }
  27. TEST(libclang, clang_createTranslationUnit_InvalidArgs) {
  28. EXPECT_EQ(nullptr, clang_createTranslationUnit(nullptr, nullptr));
  29. }
  30. TEST(libclang, clang_createTranslationUnit2_InvalidArgs) {
  31. EXPECT_EQ(CXError_InvalidArguments,
  32. clang_createTranslationUnit2(nullptr, nullptr, nullptr));
  33. CXTranslationUnit TU = reinterpret_cast<CXTranslationUnit>(1);
  34. EXPECT_EQ(CXError_InvalidArguments,
  35. clang_createTranslationUnit2(nullptr, nullptr, &TU));
  36. EXPECT_EQ(nullptr, TU);
  37. }
  38. namespace {
  39. struct TestVFO {
  40. const char *Contents;
  41. CXVirtualFileOverlay VFO;
  42. TestVFO(const char *Contents) : Contents(Contents) {
  43. VFO = clang_VirtualFileOverlay_create(0);
  44. }
  45. void map(const char *VPath, const char *RPath) {
  46. CXErrorCode Err = clang_VirtualFileOverlay_addFileMapping(VFO, VPath, RPath);
  47. EXPECT_EQ(Err, CXError_Success);
  48. }
  49. void mapError(const char *VPath, const char *RPath, CXErrorCode ExpErr) {
  50. CXErrorCode Err = clang_VirtualFileOverlay_addFileMapping(VFO, VPath, RPath);
  51. EXPECT_EQ(Err, ExpErr);
  52. }
  53. ~TestVFO() {
  54. if (Contents) {
  55. char *BufPtr;
  56. unsigned BufSize;
  57. clang_VirtualFileOverlay_writeToBuffer(VFO, 0, &BufPtr, &BufSize);
  58. std::string BufStr(BufPtr, BufSize);
  59. EXPECT_STREQ(Contents, BufStr.c_str());
  60. clang_free(BufPtr);
  61. }
  62. clang_VirtualFileOverlay_dispose(VFO);
  63. }
  64. };
  65. }
  66. TEST(libclang, VirtualFileOverlay_Basic) {
  67. const char *contents =
  68. "{\n"
  69. " 'version': 0,\n"
  70. " 'roots': [\n"
  71. " {\n"
  72. " 'type': 'directory',\n"
  73. " 'name': \"/path/virtual\",\n"
  74. " 'contents': [\n"
  75. " {\n"
  76. " 'type': 'file',\n"
  77. " 'name': \"foo.h\",\n"
  78. " 'external-contents': \"/real/foo.h\"\n"
  79. " }\n"
  80. " ]\n"
  81. " }\n"
  82. " ]\n"
  83. "}\n";
  84. TestVFO T(contents);
  85. T.map("/path/virtual/foo.h", "/real/foo.h");
  86. }
  87. TEST(libclang, VirtualFileOverlay_Unicode) {
  88. const char *contents =
  89. "{\n"
  90. " 'version': 0,\n"
  91. " 'roots': [\n"
  92. " {\n"
  93. " 'type': 'directory',\n"
  94. " 'name': \"/path/\\u266B\",\n"
  95. " 'contents': [\n"
  96. " {\n"
  97. " 'type': 'file',\n"
  98. " 'name': \"\\u2602.h\",\n"
  99. " 'external-contents': \"/real/\\u2602.h\"\n"
  100. " }\n"
  101. " ]\n"
  102. " }\n"
  103. " ]\n"
  104. "}\n";
  105. TestVFO T(contents);
  106. T.map("/path/♫/☂.h", "/real/☂.h");
  107. }
  108. TEST(libclang, VirtualFileOverlay_InvalidArgs) {
  109. TestVFO T(nullptr);
  110. T.mapError("/path/./virtual/../foo.h", "/real/foo.h",
  111. CXError_InvalidArguments);
  112. }
  113. TEST(libclang, VirtualFileOverlay_RemapDirectories) {
  114. const char *contents =
  115. "{\n"
  116. " 'version': 0,\n"
  117. " 'roots': [\n"
  118. " {\n"
  119. " 'type': 'directory',\n"
  120. " 'name': \"/another/dir\",\n"
  121. " 'contents': [\n"
  122. " {\n"
  123. " 'type': 'file',\n"
  124. " 'name': \"foo2.h\",\n"
  125. " 'external-contents': \"/real/foo2.h\"\n"
  126. " }\n"
  127. " ]\n"
  128. " },\n"
  129. " {\n"
  130. " 'type': 'directory',\n"
  131. " 'name': \"/path/virtual/dir\",\n"
  132. " 'contents': [\n"
  133. " {\n"
  134. " 'type': 'file',\n"
  135. " 'name': \"foo1.h\",\n"
  136. " 'external-contents': \"/real/foo1.h\"\n"
  137. " },\n"
  138. " {\n"
  139. " 'type': 'file',\n"
  140. " 'name': \"foo3.h\",\n"
  141. " 'external-contents': \"/real/foo3.h\"\n"
  142. " },\n"
  143. " {\n"
  144. " 'type': 'directory',\n"
  145. " 'name': \"in/subdir\",\n"
  146. " 'contents': [\n"
  147. " {\n"
  148. " 'type': 'file',\n"
  149. " 'name': \"foo4.h\",\n"
  150. " 'external-contents': \"/real/foo4.h\"\n"
  151. " }\n"
  152. " ]\n"
  153. " }\n"
  154. " ]\n"
  155. " }\n"
  156. " ]\n"
  157. "}\n";
  158. TestVFO T(contents);
  159. T.map("/path/virtual/dir/foo1.h", "/real/foo1.h");
  160. T.map("/another/dir/foo2.h", "/real/foo2.h");
  161. T.map("/path/virtual/dir/foo3.h", "/real/foo3.h");
  162. T.map("/path/virtual/dir/in/subdir/foo4.h", "/real/foo4.h");
  163. }
  164. TEST(libclang, VirtualFileOverlay_CaseInsensitive) {
  165. const char *contents =
  166. "{\n"
  167. " 'version': 0,\n"
  168. " 'case-sensitive': 'false',\n"
  169. " 'roots': [\n"
  170. " {\n"
  171. " 'type': 'directory',\n"
  172. " 'name': \"/path/virtual\",\n"
  173. " 'contents': [\n"
  174. " {\n"
  175. " 'type': 'file',\n"
  176. " 'name': \"foo.h\",\n"
  177. " 'external-contents': \"/real/foo.h\"\n"
  178. " }\n"
  179. " ]\n"
  180. " }\n"
  181. " ]\n"
  182. "}\n";
  183. TestVFO T(contents);
  184. T.map("/path/virtual/foo.h", "/real/foo.h");
  185. clang_VirtualFileOverlay_setCaseSensitivity(T.VFO, false);
  186. }
  187. TEST(libclang, VirtualFileOverlay_SharedPrefix) {
  188. const char *contents =
  189. "{\n"
  190. " 'version': 0,\n"
  191. " 'roots': [\n"
  192. " {\n"
  193. " 'type': 'directory',\n"
  194. " 'name': \"/path/foo\",\n"
  195. " 'contents': [\n"
  196. " {\n"
  197. " 'type': 'file',\n"
  198. " 'name': \"bar\",\n"
  199. " 'external-contents': \"/real/bar\"\n"
  200. " },\n"
  201. " {\n"
  202. " 'type': 'file',\n"
  203. " 'name': \"bar.h\",\n"
  204. " 'external-contents': \"/real/bar.h\"\n"
  205. " }\n"
  206. " ]\n"
  207. " },\n"
  208. " {\n"
  209. " 'type': 'directory',\n"
  210. " 'name': \"/path/foobar\",\n"
  211. " 'contents': [\n"
  212. " {\n"
  213. " 'type': 'file',\n"
  214. " 'name': \"baz.h\",\n"
  215. " 'external-contents': \"/real/baz.h\"\n"
  216. " }\n"
  217. " ]\n"
  218. " },\n"
  219. " {\n"
  220. " 'type': 'directory',\n"
  221. " 'name': \"/path\",\n"
  222. " 'contents': [\n"
  223. " {\n"
  224. " 'type': 'file',\n"
  225. " 'name': \"foobarbaz.h\",\n"
  226. " 'external-contents': \"/real/foobarbaz.h\"\n"
  227. " }\n"
  228. " ]\n"
  229. " }\n"
  230. " ]\n"
  231. "}\n";
  232. TestVFO T(contents);
  233. T.map("/path/foo/bar.h", "/real/bar.h");
  234. T.map("/path/foo/bar", "/real/bar");
  235. T.map("/path/foobar/baz.h", "/real/baz.h");
  236. T.map("/path/foobarbaz.h", "/real/foobarbaz.h");
  237. }
  238. TEST(libclang, VirtualFileOverlay_AdjacentDirectory) {
  239. const char *contents =
  240. "{\n"
  241. " 'version': 0,\n"
  242. " 'roots': [\n"
  243. " {\n"
  244. " 'type': 'directory',\n"
  245. " 'name': \"/path/dir1\",\n"
  246. " 'contents': [\n"
  247. " {\n"
  248. " 'type': 'file',\n"
  249. " 'name': \"foo.h\",\n"
  250. " 'external-contents': \"/real/foo.h\"\n"
  251. " },\n"
  252. " {\n"
  253. " 'type': 'directory',\n"
  254. " 'name': \"subdir\",\n"
  255. " 'contents': [\n"
  256. " {\n"
  257. " 'type': 'file',\n"
  258. " 'name': \"bar.h\",\n"
  259. " 'external-contents': \"/real/bar.h\"\n"
  260. " }\n"
  261. " ]\n"
  262. " }\n"
  263. " ]\n"
  264. " },\n"
  265. " {\n"
  266. " 'type': 'directory',\n"
  267. " 'name': \"/path/dir2\",\n"
  268. " 'contents': [\n"
  269. " {\n"
  270. " 'type': 'file',\n"
  271. " 'name': \"baz.h\",\n"
  272. " 'external-contents': \"/real/baz.h\"\n"
  273. " }\n"
  274. " ]\n"
  275. " }\n"
  276. " ]\n"
  277. "}\n";
  278. TestVFO T(contents);
  279. T.map("/path/dir1/foo.h", "/real/foo.h");
  280. T.map("/path/dir1/subdir/bar.h", "/real/bar.h");
  281. T.map("/path/dir2/baz.h", "/real/baz.h");
  282. }
  283. TEST(libclang, VirtualFileOverlay_TopLevel) {
  284. const char *contents =
  285. "{\n"
  286. " 'version': 0,\n"
  287. " 'roots': [\n"
  288. " {\n"
  289. " 'type': 'directory',\n"
  290. " 'name': \"/\",\n"
  291. " 'contents': [\n"
  292. " {\n"
  293. " 'type': 'file',\n"
  294. " 'name': \"foo.h\",\n"
  295. " 'external-contents': \"/real/foo.h\"\n"
  296. " }\n"
  297. " ]\n"
  298. " }\n"
  299. " ]\n"
  300. "}\n";
  301. TestVFO T(contents);
  302. T.map("/foo.h", "/real/foo.h");
  303. }
  304. TEST(libclang, VirtualFileOverlay_Empty) {
  305. const char *contents =
  306. "{\n"
  307. " 'version': 0,\n"
  308. " 'roots': [\n"
  309. " ]\n"
  310. "}\n";
  311. TestVFO T(contents);
  312. }
  313. TEST(libclang, ModuleMapDescriptor) {
  314. const char *Contents =
  315. "framework module TestFrame {\n"
  316. " umbrella header \"TestFrame.h\"\n"
  317. "\n"
  318. " export *\n"
  319. " module * { export * }\n"
  320. "}\n";
  321. CXModuleMapDescriptor MMD = clang_ModuleMapDescriptor_create(0);
  322. clang_ModuleMapDescriptor_setFrameworkModuleName(MMD, "TestFrame");
  323. clang_ModuleMapDescriptor_setUmbrellaHeader(MMD, "TestFrame.h");
  324. char *BufPtr;
  325. unsigned BufSize;
  326. clang_ModuleMapDescriptor_writeToBuffer(MMD, 0, &BufPtr, &BufSize);
  327. std::string BufStr(BufPtr, BufSize);
  328. EXPECT_STREQ(Contents, BufStr.c_str());
  329. clang_free(BufPtr);
  330. clang_ModuleMapDescriptor_dispose(MMD);
  331. }
  332. TEST_F(LibclangParseTest, AllSkippedRanges) {
  333. std::string Header = "header.h", Main = "main.cpp";
  334. WriteFile(Header,
  335. "#ifdef MANGOS\n"
  336. "printf(\"mmm\");\n"
  337. "#endif");
  338. WriteFile(Main,
  339. "#include \"header.h\"\n"
  340. "#ifdef KIWIS\n"
  341. "printf(\"mmm!!\");\n"
  342. "#endif");
  343. ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
  344. nullptr, 0, TUFlags);
  345. CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
  346. EXPECT_EQ(2U, Ranges->count);
  347. CXSourceLocation cxl;
  348. unsigned line;
  349. cxl = clang_getRangeStart(Ranges->ranges[0]);
  350. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  351. EXPECT_EQ(1U, line);
  352. cxl = clang_getRangeEnd(Ranges->ranges[0]);
  353. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  354. EXPECT_EQ(3U, line);
  355. cxl = clang_getRangeStart(Ranges->ranges[1]);
  356. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  357. EXPECT_EQ(2U, line);
  358. cxl = clang_getRangeEnd(Ranges->ranges[1]);
  359. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  360. EXPECT_EQ(4U, line);
  361. clang_disposeSourceRangeList(Ranges);
  362. }
  363. TEST_F(LibclangParseTest, EvaluateChildExpression) {
  364. std::string Main = "main.m";
  365. WriteFile(Main, "#define kFOO @\"foo\"\n"
  366. "void foobar(void) {\n"
  367. " {kFOO;}\n"
  368. "}\n");
  369. ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr,
  370. 0, TUFlags);
  371. CXCursor C = clang_getTranslationUnitCursor(ClangTU);
  372. clang_visitChildren(
  373. C,
  374. [](CXCursor cursor, CXCursor parent,
  375. CXClientData client_data) -> CXChildVisitResult {
  376. if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) {
  377. int numberedStmt = 0;
  378. clang_visitChildren(
  379. cursor,
  380. [](CXCursor cursor, CXCursor parent,
  381. CXClientData client_data) -> CXChildVisitResult {
  382. int &numberedStmt = *((int *)client_data);
  383. if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) {
  384. if (numberedStmt) {
  385. CXEvalResult RE = clang_Cursor_Evaluate(cursor);
  386. EXPECT_NE(RE, nullptr);
  387. EXPECT_EQ(clang_EvalResult_getKind(RE),
  388. CXEval_ObjCStrLiteral);
  389. clang_EvalResult_dispose(RE);
  390. return CXChildVisit_Break;
  391. }
  392. numberedStmt++;
  393. }
  394. return CXChildVisit_Recurse;
  395. },
  396. &numberedStmt);
  397. EXPECT_EQ(numberedStmt, 1);
  398. }
  399. return CXChildVisit_Continue;
  400. },
  401. nullptr);
  402. }
  403. class LibclangReparseTest : public LibclangParseTest {
  404. public:
  405. void DisplayDiagnostics() {
  406. unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
  407. for (unsigned i = 0; i < NumDiagnostics; ++i) {
  408. auto Diag = clang_getDiagnostic(ClangTU, i);
  409. LLVM_DEBUG(llvm::dbgs()
  410. << clang_getCString(clang_formatDiagnostic(
  411. Diag, clang_defaultDiagnosticDisplayOptions()))
  412. << "\n");
  413. clang_disposeDiagnostic(Diag);
  414. }
  415. }
  416. bool ReparseTU(unsigned num_unsaved_files, CXUnsavedFile* unsaved_files) {
  417. if (clang_reparseTranslationUnit(ClangTU, num_unsaved_files, unsaved_files,
  418. clang_defaultReparseOptions(ClangTU))) {
  419. LLVM_DEBUG(llvm::dbgs() << "Reparse failed\n");
  420. return false;
  421. }
  422. DisplayDiagnostics();
  423. return true;
  424. }
  425. };
  426. TEST_F(LibclangReparseTest, FileName) {
  427. std::string CppName = "main.cpp";
  428. WriteFile(CppName, "int main() {}");
  429. ClangTU = clang_parseTranslationUnit(Index, CppName.c_str(), nullptr, 0,
  430. nullptr, 0, TUFlags);
  431. CXFile cxf = clang_getFile(ClangTU, CppName.c_str());
  432. CXString cxname = clang_getFileName(cxf);
  433. ASSERT_STREQ(clang_getCString(cxname), CppName.c_str());
  434. clang_disposeString(cxname);
  435. cxname = clang_File_tryGetRealPathName(cxf);
  436. ASSERT_TRUE(llvm::StringRef(clang_getCString(cxname)).endswith("main.cpp"));
  437. clang_disposeString(cxname);
  438. }
  439. TEST_F(LibclangReparseTest, Reparse) {
  440. const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
  441. const char *HeaderBottom = "\n};\n#endif\n";
  442. const char *CppFile = "#include \"HeaderFile.h\"\nint main() {"
  443. " Foo foo; foo.bar = 7; foo.baz = 8; }\n";
  444. std::string HeaderName = "HeaderFile.h";
  445. std::string CppName = "CppFile.cpp";
  446. WriteFile(CppName, CppFile);
  447. WriteFile(HeaderName, std::string(HeaderTop) + HeaderBottom);
  448. ClangTU = clang_parseTranslationUnit(Index, CppName.c_str(), nullptr, 0,
  449. nullptr, 0, TUFlags);
  450. EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));
  451. DisplayDiagnostics();
  452. // Immedaitely reparse.
  453. ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  454. EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));
  455. std::string NewHeaderContents =
  456. std::string(HeaderTop) + "int baz;" + HeaderBottom;
  457. WriteFile(HeaderName, NewHeaderContents);
  458. // Reparse after fix.
  459. ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  460. EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
  461. }
  462. TEST_F(LibclangReparseTest, ReparseWithModule) {
  463. const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
  464. const char *HeaderBottom = "\n};\n#endif\n";
  465. const char *MFile = "#include \"HeaderFile.h\"\nint main() {"
  466. " struct Foo foo; foo.bar = 7; foo.baz = 8; }\n";
  467. const char *ModFile = "module A { header \"HeaderFile.h\" }\n";
  468. std::string HeaderName = "HeaderFile.h";
  469. std::string MName = "MFile.m";
  470. std::string ModName = "module.modulemap";
  471. WriteFile(MName, MFile);
  472. WriteFile(HeaderName, std::string(HeaderTop) + HeaderBottom);
  473. WriteFile(ModName, ModFile);
  474. std::string ModulesCache = std::string("-fmodules-cache-path=") + TestDir;
  475. const char *Args[] = { "-fmodules", ModulesCache.c_str(),
  476. "-I", TestDir.c_str() };
  477. int NumArgs = sizeof(Args) / sizeof(Args[0]);
  478. ClangTU = clang_parseTranslationUnit(Index, MName.c_str(), Args, NumArgs,
  479. nullptr, 0, TUFlags);
  480. EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));
  481. DisplayDiagnostics();
  482. // Immedaitely reparse.
  483. ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  484. EXPECT_EQ(1U, clang_getNumDiagnostics(ClangTU));
  485. std::string NewHeaderContents =
  486. std::string(HeaderTop) + "int baz;" + HeaderBottom;
  487. WriteFile(HeaderName, NewHeaderContents);
  488. // Reparse after fix.
  489. ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  490. EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
  491. }
  492. TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
  493. // Provide a fake GCC 99.9.9 standard library that always overrides any local
  494. // GCC installation.
  495. std::string EmptyFiles[] = {"lib/gcc/arm-linux-gnueabi/99.9.9/crtbegin.o",
  496. "include/arm-linux-gnueabi/.keep",
  497. "include/c++/99.9.9/vector"};
  498. for (auto &Name : EmptyFiles)
  499. WriteFile(Name, "\n");
  500. std::string Filename = "test.cc";
  501. WriteFile(Filename, "#include <vector>\n");
  502. std::string Clang = "bin/clang";
  503. WriteFile(Clang, "");
  504. const char *Argv[] = {Clang.c_str(), "-target", "arm-linux-gnueabi",
  505. "-stdlib=libstdc++", "--gcc-toolchain="};
  506. EXPECT_EQ(CXError_Success,
  507. clang_parseTranslationUnit2FullArgv(Index, Filename.c_str(), Argv,
  508. sizeof(Argv) / sizeof(Argv[0]),
  509. nullptr, 0, TUFlags, &ClangTU));
  510. EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
  511. DisplayDiagnostics();
  512. }
  513. class LibclangPrintingPolicyTest : public LibclangParseTest {
  514. public:
  515. CXPrintingPolicy Policy = nullptr;
  516. void SetUp() override {
  517. LibclangParseTest::SetUp();
  518. std::string File = "file.cpp";
  519. WriteFile(File, "int i;\n");
  520. ClangTU = clang_parseTranslationUnit(Index, File.c_str(), nullptr, 0,
  521. nullptr, 0, TUFlags);
  522. CXCursor TUCursor = clang_getTranslationUnitCursor(ClangTU);
  523. Policy = clang_getCursorPrintingPolicy(TUCursor);
  524. }
  525. void TearDown() override {
  526. clang_PrintingPolicy_dispose(Policy);
  527. LibclangParseTest::TearDown();
  528. }
  529. };
  530. TEST_F(LibclangPrintingPolicyTest, SetAndGetProperties) {
  531. for (unsigned Value = 0; Value < 2; ++Value) {
  532. for (int I = 0; I < CXPrintingPolicy_LastProperty; ++I) {
  533. auto Property = static_cast<enum CXPrintingPolicyProperty>(I);
  534. clang_PrintingPolicy_setProperty(Policy, Property, Value);
  535. EXPECT_EQ(Value, clang_PrintingPolicy_getProperty(Policy, Property));
  536. }
  537. }
  538. }
  539. TEST_F(LibclangReparseTest, PreprocessorSkippedRanges) {
  540. std::string Header = "header.h", Main = "main.cpp";
  541. WriteFile(Header,
  542. "#ifdef MANGOS\n"
  543. "printf(\"mmm\");\n"
  544. "#endif");
  545. WriteFile(Main,
  546. "#include \"header.h\"\n"
  547. "#ifdef GUAVA\n"
  548. "#endif\n"
  549. "#ifdef KIWIS\n"
  550. "printf(\"mmm!!\");\n"
  551. "#endif");
  552. for (int i = 0; i != 3; ++i) {
  553. unsigned flags = TUFlags | CXTranslationUnit_PrecompiledPreamble;
  554. if (i == 2)
  555. flags |= CXTranslationUnit_CreatePreambleOnFirstParse;
  556. if (i != 0)
  557. clang_disposeTranslationUnit(ClangTU); // dispose from previous iter
  558. // parse once
  559. ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
  560. nullptr, 0, flags);
  561. if (i != 0) {
  562. // reparse
  563. ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
  564. }
  565. // Check all ranges are there
  566. CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
  567. EXPECT_EQ(3U, Ranges->count);
  568. CXSourceLocation cxl;
  569. unsigned line;
  570. cxl = clang_getRangeStart(Ranges->ranges[0]);
  571. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  572. EXPECT_EQ(1U, line);
  573. cxl = clang_getRangeEnd(Ranges->ranges[0]);
  574. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  575. EXPECT_EQ(3U, line);
  576. cxl = clang_getRangeStart(Ranges->ranges[1]);
  577. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  578. EXPECT_EQ(2U, line);
  579. cxl = clang_getRangeEnd(Ranges->ranges[1]);
  580. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  581. EXPECT_EQ(3U, line);
  582. cxl = clang_getRangeStart(Ranges->ranges[2]);
  583. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  584. EXPECT_EQ(4U, line);
  585. cxl = clang_getRangeEnd(Ranges->ranges[2]);
  586. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  587. EXPECT_EQ(6U, line);
  588. clang_disposeSourceRangeList(Ranges);
  589. // Check obtaining ranges by each file works
  590. CXFile cxf = clang_getFile(ClangTU, Header.c_str());
  591. Ranges = clang_getSkippedRanges(ClangTU, cxf);
  592. EXPECT_EQ(1U, Ranges->count);
  593. cxl = clang_getRangeStart(Ranges->ranges[0]);
  594. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  595. EXPECT_EQ(1U, line);
  596. clang_disposeSourceRangeList(Ranges);
  597. cxf = clang_getFile(ClangTU, Main.c_str());
  598. Ranges = clang_getSkippedRanges(ClangTU, cxf);
  599. EXPECT_EQ(2U, Ranges->count);
  600. cxl = clang_getRangeStart(Ranges->ranges[0]);
  601. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  602. EXPECT_EQ(2U, line);
  603. cxl = clang_getRangeStart(Ranges->ranges[1]);
  604. clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
  605. EXPECT_EQ(4U, line);
  606. clang_disposeSourceRangeList(Ranges);
  607. }
  608. }
  609. class LibclangSerializationTest : public LibclangParseTest {
  610. public:
  611. bool SaveAndLoadTU(const std::string &Filename) {
  612. unsigned options = clang_defaultSaveOptions(ClangTU);
  613. if (clang_saveTranslationUnit(ClangTU, Filename.c_str(), options) !=
  614. CXSaveError_None) {
  615. LLVM_DEBUG(llvm::dbgs() << "Saving failed\n");
  616. return false;
  617. }
  618. clang_disposeTranslationUnit(ClangTU);
  619. ClangTU = clang_createTranslationUnit(Index, Filename.c_str());
  620. if (!ClangTU) {
  621. LLVM_DEBUG(llvm::dbgs() << "Loading failed\n");
  622. return false;
  623. }
  624. return true;
  625. }
  626. };
  627. TEST_F(LibclangSerializationTest, TokenKindsAreCorrectAfterLoading) {
  628. // Ensure that "class" is recognized as a keyword token after serializing
  629. // and reloading the AST, as it is not a keyword for the default LangOptions.
  630. std::string HeaderName = "test.h";
  631. WriteFile(HeaderName, "enum class Something {};");
  632. const char *Argv[] = {"-xc++-header", "-std=c++11"};
  633. ClangTU = clang_parseTranslationUnit(Index, HeaderName.c_str(), Argv,
  634. sizeof(Argv) / sizeof(Argv[0]), nullptr,
  635. 0, TUFlags);
  636. auto CheckTokenKinds = [=]() {
  637. CXSourceRange Range =
  638. clang_getCursorExtent(clang_getTranslationUnitCursor(ClangTU));
  639. CXToken *Tokens;
  640. unsigned int NumTokens;
  641. clang_tokenize(ClangTU, Range, &Tokens, &NumTokens);
  642. ASSERT_EQ(6u, NumTokens);
  643. EXPECT_EQ(CXToken_Keyword, clang_getTokenKind(Tokens[0]));
  644. EXPECT_EQ(CXToken_Keyword, clang_getTokenKind(Tokens[1]));
  645. EXPECT_EQ(CXToken_Identifier, clang_getTokenKind(Tokens[2]));
  646. EXPECT_EQ(CXToken_Punctuation, clang_getTokenKind(Tokens[3]));
  647. EXPECT_EQ(CXToken_Punctuation, clang_getTokenKind(Tokens[4]));
  648. EXPECT_EQ(CXToken_Punctuation, clang_getTokenKind(Tokens[5]));
  649. clang_disposeTokens(ClangTU, Tokens, NumTokens);
  650. };
  651. CheckTokenKinds();
  652. std::string ASTName = "test.ast";
  653. WriteFile(ASTName, "");
  654. ASSERT_TRUE(SaveAndLoadTU(ASTName));
  655. CheckTokenKinds();
  656. }