ASTUnit.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // ASTUnit Implementation.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Frontend/ASTUnit.h"
  14. #include "clang/Frontend/PCHReader.h"
  15. #include "clang/AST/ASTContext.h"
  16. #include "clang/AST/ASTConsumer.h"
  17. #include "clang/AST/DeclVisitor.h"
  18. #include "clang/AST/StmtVisitor.h"
  19. #include "clang/Driver/Compilation.h"
  20. #include "clang/Driver/Driver.h"
  21. #include "clang/Driver/Job.h"
  22. #include "clang/Driver/Tool.h"
  23. #include "clang/Frontend/CompilerInstance.h"
  24. #include "clang/Frontend/FrontendActions.h"
  25. #include "clang/Frontend/FrontendDiagnostic.h"
  26. #include "clang/Frontend/FrontendOptions.h"
  27. #include "clang/Lex/HeaderSearch.h"
  28. #include "clang/Lex/Preprocessor.h"
  29. #include "clang/Basic/TargetOptions.h"
  30. #include "clang/Basic/TargetInfo.h"
  31. #include "clang/Basic/Diagnostic.h"
  32. #include "llvm/Support/MemoryBuffer.h"
  33. #include "llvm/System/Host.h"
  34. #include "llvm/System/Path.h"
  35. using namespace clang;
  36. ASTUnit::ASTUnit(bool _MainFileIsAST)
  37. : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { }
  38. ASTUnit::~ASTUnit() {
  39. ConcurrencyCheckValue = CheckLocked;
  40. for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
  41. TemporaryFiles[I].eraseFromDisk();
  42. }
  43. namespace {
  44. /// \brief Gathers information from PCHReader that will be used to initialize
  45. /// a Preprocessor.
  46. class PCHInfoCollector : public PCHReaderListener {
  47. LangOptions &LangOpt;
  48. HeaderSearch &HSI;
  49. std::string &TargetTriple;
  50. std::string &Predefines;
  51. unsigned &Counter;
  52. unsigned NumHeaderInfos;
  53. public:
  54. PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
  55. std::string &TargetTriple, std::string &Predefines,
  56. unsigned &Counter)
  57. : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
  58. Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
  59. virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
  60. LangOpt = LangOpts;
  61. return false;
  62. }
  63. virtual bool ReadTargetTriple(llvm::StringRef Triple) {
  64. TargetTriple = Triple;
  65. return false;
  66. }
  67. virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
  68. FileID PCHBufferID,
  69. llvm::StringRef OriginalFileName,
  70. std::string &SuggestedPredefines) {
  71. Predefines = PCHPredef;
  72. return false;
  73. }
  74. virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
  75. HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
  76. }
  77. virtual void ReadCounter(unsigned Value) {
  78. Counter = Value;
  79. }
  80. };
  81. class StoredDiagnosticClient : public DiagnosticClient {
  82. llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
  83. public:
  84. explicit StoredDiagnosticClient(
  85. llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
  86. : StoredDiags(StoredDiags) { }
  87. virtual void HandleDiagnostic(Diagnostic::Level Level,
  88. const DiagnosticInfo &Info);
  89. };
  90. /// \brief RAII object that optionally captures diagnostics, if
  91. /// there is no diagnostic client to capture them already.
  92. class CaptureDroppedDiagnostics {
  93. Diagnostic &Diags;
  94. StoredDiagnosticClient Client;
  95. DiagnosticClient *PreviousClient;
  96. public:
  97. CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
  98. llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
  99. : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
  100. {
  101. if (RequestCapture || Diags.getClient() == 0)
  102. Diags.setClient(&Client);
  103. }
  104. ~CaptureDroppedDiagnostics() {
  105. Diags.setClient(PreviousClient);
  106. }
  107. };
  108. } // anonymous namespace
  109. void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
  110. const DiagnosticInfo &Info) {
  111. StoredDiags.push_back(StoredDiagnostic(Level, Info));
  112. }
  113. const std::string &ASTUnit::getOriginalSourceFileName() {
  114. return OriginalSourceFile;
  115. }
  116. const std::string &ASTUnit::getPCHFileName() {
  117. assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
  118. return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
  119. }
  120. ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
  121. llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
  122. bool OnlyLocalDecls,
  123. RemappedFile *RemappedFiles,
  124. unsigned NumRemappedFiles,
  125. bool CaptureDiagnostics) {
  126. llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
  127. if (!Diags.getPtr()) {
  128. // No diagnostics engine was provided, so create our own diagnostics object
  129. // with the default options.
  130. DiagnosticOptions DiagOpts;
  131. Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
  132. }
  133. AST->OnlyLocalDecls = OnlyLocalDecls;
  134. AST->Diagnostics = Diags;
  135. AST->FileMgr.reset(new FileManager);
  136. AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
  137. AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
  138. // If requested, capture diagnostics in the ASTUnit.
  139. CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
  140. AST->StoredDiagnostics);
  141. for (unsigned I = 0; I != NumRemappedFiles; ++I) {
  142. // Create the file entry for the file that we're mapping from.
  143. const FileEntry *FromFile
  144. = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
  145. RemappedFiles[I].second->getBufferSize(),
  146. 0);
  147. if (!FromFile) {
  148. AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
  149. << RemappedFiles[I].first;
  150. delete RemappedFiles[I].second;
  151. continue;
  152. }
  153. // Override the contents of the "from" file with the contents of
  154. // the "to" file.
  155. AST->getSourceManager().overrideFileContents(FromFile,
  156. RemappedFiles[I].second);
  157. }
  158. // Gather Info for preprocessor construction later on.
  159. LangOptions LangInfo;
  160. HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
  161. std::string TargetTriple;
  162. std::string Predefines;
  163. unsigned Counter;
  164. llvm::OwningPtr<PCHReader> Reader;
  165. llvm::OwningPtr<ExternalASTSource> Source;
  166. Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
  167. AST->getDiagnostics()));
  168. Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
  169. Predefines, Counter));
  170. switch (Reader->ReadPCH(Filename)) {
  171. case PCHReader::Success:
  172. break;
  173. case PCHReader::Failure:
  174. case PCHReader::IgnorePCH:
  175. AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
  176. return NULL;
  177. }
  178. AST->OriginalSourceFile = Reader->getOriginalSourceFile();
  179. // PCH loaded successfully. Now create the preprocessor.
  180. // Get information about the target being compiled for.
  181. //
  182. // FIXME: This is broken, we should store the TargetOptions in the PCH.
  183. TargetOptions TargetOpts;
  184. TargetOpts.ABI = "";
  185. TargetOpts.CPU = "";
  186. TargetOpts.Features.clear();
  187. TargetOpts.Triple = TargetTriple;
  188. AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
  189. TargetOpts));
  190. AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
  191. *AST->Target.get(),
  192. AST->getSourceManager(), HeaderInfo));
  193. Preprocessor &PP = *AST->PP.get();
  194. PP.setPredefines(Reader->getSuggestedPredefines());
  195. PP.setCounterValue(Counter);
  196. Reader->setPreprocessor(PP);
  197. // Create and initialize the ASTContext.
  198. AST->Ctx.reset(new ASTContext(LangInfo,
  199. AST->getSourceManager(),
  200. *AST->Target.get(),
  201. PP.getIdentifierTable(),
  202. PP.getSelectorTable(),
  203. PP.getBuiltinInfo(),
  204. /* FreeMemory = */ false,
  205. /* size_reserve = */0));
  206. ASTContext &Context = *AST->Ctx.get();
  207. Reader->InitializeContext(Context);
  208. // Attach the PCH reader to the AST context as an external AST
  209. // source, so that declarations will be deserialized from the
  210. // PCH file as needed.
  211. Source.reset(Reader.take());
  212. Context.setExternalSource(Source);
  213. return AST.take();
  214. }
  215. namespace {
  216. class TopLevelDeclTrackerConsumer : public ASTConsumer {
  217. ASTUnit &Unit;
  218. public:
  219. TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
  220. void HandleTopLevelDecl(DeclGroupRef D) {
  221. for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
  222. Decl *D = *it;
  223. // FIXME: Currently ObjC method declarations are incorrectly being
  224. // reported as top-level declarations, even though their DeclContext
  225. // is the containing ObjC @interface/@implementation. This is a
  226. // fundamental problem in the parser right now.
  227. if (isa<ObjCMethodDecl>(D))
  228. continue;
  229. Unit.getTopLevelDecls().push_back(D);
  230. }
  231. }
  232. };
  233. class TopLevelDeclTrackerAction : public ASTFrontendAction {
  234. public:
  235. ASTUnit &Unit;
  236. virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
  237. llvm::StringRef InFile) {
  238. return new TopLevelDeclTrackerConsumer(Unit);
  239. }
  240. public:
  241. TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
  242. virtual bool hasCodeCompletionSupport() const { return false; }
  243. };
  244. }
  245. ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
  246. llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
  247. bool OnlyLocalDecls,
  248. bool CaptureDiagnostics) {
  249. // Create the compiler instance to use for building the AST.
  250. CompilerInstance Clang;
  251. llvm::OwningPtr<ASTUnit> AST;
  252. llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
  253. if (!Diags.getPtr()) {
  254. // No diagnostics engine was provided, so create our own diagnostics object
  255. // with the default options.
  256. DiagnosticOptions DiagOpts;
  257. Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
  258. }
  259. Clang.setInvocation(CI);
  260. Clang.setDiagnostics(Diags.getPtr());
  261. Clang.setDiagnosticClient(Diags->getClient());
  262. // Create the target instance.
  263. Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
  264. Clang.getTargetOpts()));
  265. if (!Clang.hasTarget()) {
  266. Clang.takeDiagnosticClient();
  267. return 0;
  268. }
  269. // Inform the target of the language options.
  270. //
  271. // FIXME: We shouldn't need to do this, the target should be immutable once
  272. // created. This complexity should be lifted elsewhere.
  273. Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
  274. assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
  275. "Invocation must have exactly one source file!");
  276. assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
  277. "FIXME: AST inputs not yet supported here!");
  278. assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
  279. "IR inputs not support here!");
  280. // Create the AST unit.
  281. AST.reset(new ASTUnit(false));
  282. AST->Diagnostics = Diags;
  283. AST->FileMgr.reset(new FileManager);
  284. AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
  285. AST->OnlyLocalDecls = OnlyLocalDecls;
  286. AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
  287. // Capture any diagnostics that would otherwise be dropped.
  288. CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
  289. Clang.getDiagnostics(),
  290. AST->StoredDiagnostics);
  291. // Create a file manager object to provide access to and cache the filesystem.
  292. Clang.setFileManager(&AST->getFileManager());
  293. // Create the source manager.
  294. Clang.setSourceManager(&AST->getSourceManager());
  295. Act.reset(new TopLevelDeclTrackerAction(*AST));
  296. if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
  297. Clang.getFrontendOpts().Inputs[0].first))
  298. goto error;
  299. Act->Execute();
  300. // Steal the created target, context, and preprocessor, and take back the
  301. // source and file managers.
  302. AST->Ctx.reset(Clang.takeASTContext());
  303. AST->PP.reset(Clang.takePreprocessor());
  304. Clang.takeSourceManager();
  305. Clang.takeFileManager();
  306. AST->Target.reset(Clang.takeTarget());
  307. Act->EndSourceFile();
  308. Clang.takeDiagnosticClient();
  309. Clang.takeInvocation();
  310. AST->Invocation.reset(Clang.takeInvocation());
  311. return AST.take();
  312. error:
  313. Clang.takeSourceManager();
  314. Clang.takeFileManager();
  315. Clang.takeDiagnosticClient();
  316. return 0;
  317. }
  318. ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
  319. const char **ArgEnd,
  320. llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
  321. llvm::StringRef ResourceFilesPath,
  322. bool OnlyLocalDecls,
  323. RemappedFile *RemappedFiles,
  324. unsigned NumRemappedFiles,
  325. bool CaptureDiagnostics) {
  326. if (!Diags.getPtr()) {
  327. // No diagnostics engine was provided, so create our own diagnostics object
  328. // with the default options.
  329. DiagnosticOptions DiagOpts;
  330. Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
  331. }
  332. llvm::SmallVector<const char *, 16> Args;
  333. Args.push_back("<clang>"); // FIXME: Remove dummy argument.
  334. Args.insert(Args.end(), ArgBegin, ArgEnd);
  335. // FIXME: Find a cleaner way to force the driver into restricted modes. We
  336. // also want to force it to use clang.
  337. Args.push_back("-fsyntax-only");
  338. // FIXME: We shouldn't have to pass in the path info.
  339. driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(),
  340. "a.out", false, false, *Diags);
  341. // Don't check that inputs exist, they have been remapped.
  342. TheDriver.setCheckInputsExist(false);
  343. llvm::OwningPtr<driver::Compilation> C(
  344. TheDriver.BuildCompilation(Args.size(), Args.data()));
  345. // We expect to get back exactly one command job, if we didn't something
  346. // failed.
  347. const driver::JobList &Jobs = C->getJobs();
  348. if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
  349. llvm::SmallString<256> Msg;
  350. llvm::raw_svector_ostream OS(Msg);
  351. C->PrintJob(OS, C->getJobs(), "; ", true);
  352. Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
  353. return 0;
  354. }
  355. const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
  356. if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
  357. Diags->Report(diag::err_fe_expected_clang_command);
  358. return 0;
  359. }
  360. const driver::ArgStringList &CCArgs = Cmd->getArguments();
  361. llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
  362. CompilerInvocation::CreateFromArgs(*CI,
  363. const_cast<const char **>(CCArgs.data()),
  364. const_cast<const char **>(CCArgs.data()) +
  365. CCArgs.size(),
  366. *Diags);
  367. // Override any files that need remapping
  368. for (unsigned I = 0; I != NumRemappedFiles; ++I)
  369. CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
  370. RemappedFiles[I].second);
  371. // Override the resources path.
  372. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
  373. CI->getFrontendOpts().DisableFree = true;
  374. return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
  375. CaptureDiagnostics);
  376. }