ChainedIncludesSource.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. //===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===//
  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. // This file defines the ChainedIncludesSource class, which converts headers
  11. // to chained PCHs in memory, mainly used for testing.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/Basic/TargetInfo.h"
  15. #include "clang/Frontend/ASTUnit.h"
  16. #include "clang/Frontend/CompilerInstance.h"
  17. #include "clang/Frontend/TextDiagnosticPrinter.h"
  18. #include "clang/Lex/Preprocessor.h"
  19. #include "clang/Parse/ParseAST.h"
  20. #include "clang/Serialization/ASTReader.h"
  21. #include "clang/Serialization/ASTWriter.h"
  22. #include "llvm/Support/MemoryBuffer.h"
  23. using namespace clang;
  24. namespace {
  25. class ChainedIncludesSource : public ExternalSemaSource {
  26. public:
  27. ~ChainedIncludesSource() override;
  28. ExternalSemaSource &getFinalReader() const { return *FinalReader; }
  29. std::vector<CompilerInstance *> CIs;
  30. IntrusiveRefCntPtr<ExternalSemaSource> FinalReader;
  31. protected:
  32. //===----------------------------------------------------------------------===//
  33. // ExternalASTSource interface.
  34. //===----------------------------------------------------------------------===//
  35. Decl *GetExternalDecl(uint32_t ID) override;
  36. Selector GetExternalSelector(uint32_t ID) override;
  37. uint32_t GetNumExternalSelectors() override;
  38. Stmt *GetExternalDeclStmt(uint64_t Offset) override;
  39. CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
  40. CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
  41. bool FindExternalVisibleDeclsByName(const DeclContext *DC,
  42. DeclarationName Name) override;
  43. void
  44. FindExternalLexicalDecls(const DeclContext *DC,
  45. llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
  46. SmallVectorImpl<Decl *> &Result) override;
  47. void CompleteType(TagDecl *Tag) override;
  48. void CompleteType(ObjCInterfaceDecl *Class) override;
  49. void StartedDeserializing() override;
  50. void FinishedDeserializing() override;
  51. void StartTranslationUnit(ASTConsumer *Consumer) override;
  52. void PrintStats() override;
  53. /// Return the amount of memory used by memory buffers, breaking down
  54. /// by heap-backed versus mmap'ed memory.
  55. void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
  56. //===----------------------------------------------------------------------===//
  57. // ExternalSemaSource interface.
  58. //===----------------------------------------------------------------------===//
  59. void InitializeSema(Sema &S) override;
  60. void ForgetSema() override;
  61. void ReadMethodPool(Selector Sel) override;
  62. bool LookupUnqualified(LookupResult &R, Scope *S) override;
  63. };
  64. }
  65. static ASTReader *
  66. createASTReader(CompilerInstance &CI, StringRef pchFile,
  67. SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs,
  68. SmallVectorImpl<std::string> &bufNames,
  69. ASTDeserializationListener *deserialListener = nullptr) {
  70. Preprocessor &PP = CI.getPreprocessor();
  71. std::unique_ptr<ASTReader> Reader;
  72. Reader.reset(new ASTReader(PP, CI.getASTContext(),
  73. CI.getPCHContainerReader(),
  74. /*Extensions=*/{ },
  75. /*isysroot=*/"", /*DisableValidation=*/true));
  76. for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
  77. StringRef sr(bufNames[ti]);
  78. Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
  79. }
  80. Reader->setDeserializationListener(deserialListener);
  81. switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
  82. ASTReader::ARR_None)) {
  83. case ASTReader::Success:
  84. // Set the predefines buffer as suggested by the PCH reader.
  85. PP.setPredefines(Reader->getSuggestedPredefines());
  86. return Reader.release();
  87. case ASTReader::Failure:
  88. case ASTReader::Missing:
  89. case ASTReader::OutOfDate:
  90. case ASTReader::VersionMismatch:
  91. case ASTReader::ConfigurationMismatch:
  92. case ASTReader::HadErrors:
  93. break;
  94. }
  95. return nullptr;
  96. }
  97. ChainedIncludesSource::~ChainedIncludesSource() {
  98. for (unsigned i = 0, e = CIs.size(); i != e; ++i)
  99. delete CIs[i];
  100. }
  101. IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
  102. CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> &Reader) {
  103. std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
  104. assert(!includes.empty() && "No '-chain-include' in options!");
  105. IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
  106. InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
  107. SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> SerialBufs;
  108. SmallVector<std::string, 4> serialBufNames;
  109. for (unsigned i = 0, e = includes.size(); i != e; ++i) {
  110. bool firstInclude = (i == 0);
  111. std::unique_ptr<CompilerInvocation> CInvok;
  112. CInvok.reset(new CompilerInvocation(CI.getInvocation()));
  113. CInvok->getPreprocessorOpts().ChainedIncludes.clear();
  114. CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
  115. CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
  116. CInvok->getPreprocessorOpts().DisablePCHValidation = true;
  117. CInvok->getPreprocessorOpts().Includes.clear();
  118. CInvok->getPreprocessorOpts().MacroIncludes.clear();
  119. CInvok->getPreprocessorOpts().Macros.clear();
  120. CInvok->getFrontendOpts().Inputs.clear();
  121. FrontendInputFile InputFile(includes[i], IK);
  122. CInvok->getFrontendOpts().Inputs.push_back(InputFile);
  123. TextDiagnosticPrinter *DiagClient =
  124. new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
  125. IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  126. IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
  127. new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
  128. std::unique_ptr<CompilerInstance> Clang(
  129. new CompilerInstance(CI.getPCHContainerOperations()));
  130. Clang->setInvocation(CInvok.release());
  131. Clang->setDiagnostics(Diags.get());
  132. Clang->setTarget(TargetInfo::CreateTargetInfo(
  133. Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
  134. Clang->createFileManager();
  135. Clang->createSourceManager(Clang->getFileManager());
  136. Clang->createPreprocessor(TU_Prefix);
  137. Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
  138. &Clang->getPreprocessor());
  139. Clang->createASTContext();
  140. auto Buffer = std::make_shared<PCHBuffer>();
  141. ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions;
  142. auto consumer = llvm::make_unique<PCHGenerator>(
  143. Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer,
  144. Extensions);
  145. Clang->getASTContext().setASTMutationListener(
  146. consumer->GetASTMutationListener());
  147. Clang->setASTConsumer(std::move(consumer));
  148. Clang->createSema(TU_Prefix, nullptr);
  149. if (firstInclude) {
  150. Preprocessor &PP = Clang->getPreprocessor();
  151. PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
  152. PP.getLangOpts());
  153. } else {
  154. assert(!SerialBufs.empty());
  155. SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> Bufs;
  156. // TODO: Pass through the existing MemoryBuffer instances instead of
  157. // allocating new ones.
  158. for (auto &SB : SerialBufs)
  159. Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
  160. std::string pchName = includes[i-1];
  161. llvm::raw_string_ostream os(pchName);
  162. os << ".pch" << i-1;
  163. serialBufNames.push_back(os.str());
  164. IntrusiveRefCntPtr<ASTReader> Reader;
  165. Reader = createASTReader(
  166. *Clang, pchName, Bufs, serialBufNames,
  167. Clang->getASTConsumer().GetASTDeserializationListener());
  168. if (!Reader)
  169. return nullptr;
  170. Clang->setModuleManager(Reader);
  171. Clang->getASTContext().setExternalSource(Reader);
  172. }
  173. if (!Clang->InitializeSourceManager(InputFile))
  174. return nullptr;
  175. ParseAST(Clang->getSema());
  176. Clang->getDiagnosticClient().EndSourceFile();
  177. assert(Buffer->IsComplete && "serialization did not complete");
  178. auto &serialAST = Buffer->Data;
  179. SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
  180. StringRef(serialAST.data(), serialAST.size())));
  181. serialAST.clear();
  182. source->CIs.push_back(Clang.release());
  183. }
  184. assert(!SerialBufs.empty());
  185. std::string pchName = includes.back() + ".pch-final";
  186. serialBufNames.push_back(pchName);
  187. Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
  188. if (!Reader)
  189. return nullptr;
  190. source->FinalReader = Reader;
  191. return source;
  192. }
  193. //===----------------------------------------------------------------------===//
  194. // ExternalASTSource interface.
  195. //===----------------------------------------------------------------------===//
  196. Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
  197. return getFinalReader().GetExternalDecl(ID);
  198. }
  199. Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
  200. return getFinalReader().GetExternalSelector(ID);
  201. }
  202. uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
  203. return getFinalReader().GetNumExternalSelectors();
  204. }
  205. Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
  206. return getFinalReader().GetExternalDeclStmt(Offset);
  207. }
  208. CXXBaseSpecifier *
  209. ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
  210. return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
  211. }
  212. CXXCtorInitializer **
  213. ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
  214. return getFinalReader().GetExternalCXXCtorInitializers(Offset);
  215. }
  216. bool
  217. ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
  218. DeclarationName Name) {
  219. return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
  220. }
  221. void ChainedIncludesSource::FindExternalLexicalDecls(
  222. const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
  223. SmallVectorImpl<Decl *> &Result) {
  224. return getFinalReader().FindExternalLexicalDecls(DC, IsKindWeWant, Result);
  225. }
  226. void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
  227. return getFinalReader().CompleteType(Tag);
  228. }
  229. void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
  230. return getFinalReader().CompleteType(Class);
  231. }
  232. void ChainedIncludesSource::StartedDeserializing() {
  233. return getFinalReader().StartedDeserializing();
  234. }
  235. void ChainedIncludesSource::FinishedDeserializing() {
  236. return getFinalReader().FinishedDeserializing();
  237. }
  238. void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
  239. return getFinalReader().StartTranslationUnit(Consumer);
  240. }
  241. void ChainedIncludesSource::PrintStats() {
  242. return getFinalReader().PrintStats();
  243. }
  244. void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
  245. for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
  246. if (const ExternalASTSource *eSrc =
  247. CIs[i]->getASTContext().getExternalSource()) {
  248. eSrc->getMemoryBufferSizes(sizes);
  249. }
  250. }
  251. getFinalReader().getMemoryBufferSizes(sizes);
  252. }
  253. void ChainedIncludesSource::InitializeSema(Sema &S) {
  254. return getFinalReader().InitializeSema(S);
  255. }
  256. void ChainedIncludesSource::ForgetSema() {
  257. return getFinalReader().ForgetSema();
  258. }
  259. void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
  260. getFinalReader().ReadMethodPool(Sel);
  261. }
  262. bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
  263. return getFinalReader().LookupUnqualified(R, S);
  264. }