ChainedIncludesSource.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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/Frontend/ChainedIncludesSource.h"
  15. #include "clang/Basic/TargetInfo.h"
  16. #include "clang/Frontend/ASTUnit.h"
  17. #include "clang/Frontend/CompilerInstance.h"
  18. #include "clang/Frontend/TextDiagnosticPrinter.h"
  19. #include "clang/Lex/Preprocessor.h"
  20. #include "clang/Parse/ParseAST.h"
  21. #include "clang/Serialization/ASTReader.h"
  22. #include "clang/Serialization/ASTWriter.h"
  23. #include "llvm/Support/MemoryBuffer.h"
  24. using namespace clang;
  25. static ASTReader *createASTReader(CompilerInstance &CI,
  26. StringRef pchFile,
  27. SmallVector<llvm::MemoryBuffer *, 4> &memBufs,
  28. SmallVector<std::string, 4> &bufNames,
  29. ASTDeserializationListener *deserialListener = 0) {
  30. Preprocessor &PP = CI.getPreprocessor();
  31. OwningPtr<ASTReader> Reader;
  32. Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"",
  33. /*DisableValidation=*/true));
  34. for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
  35. StringRef sr(bufNames[ti]);
  36. Reader->addInMemoryBuffer(sr, memBufs[ti]);
  37. }
  38. Reader->setDeserializationListener(deserialListener);
  39. switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
  40. ASTReader::ARR_None)) {
  41. case ASTReader::Success:
  42. // Set the predefines buffer as suggested by the PCH reader.
  43. PP.setPredefines(Reader->getSuggestedPredefines());
  44. return Reader.take();
  45. case ASTReader::Failure:
  46. case ASTReader::Missing:
  47. case ASTReader::OutOfDate:
  48. case ASTReader::VersionMismatch:
  49. case ASTReader::ConfigurationMismatch:
  50. case ASTReader::HadErrors:
  51. break;
  52. }
  53. return 0;
  54. }
  55. ChainedIncludesSource::~ChainedIncludesSource() {
  56. for (unsigned i = 0, e = CIs.size(); i != e; ++i)
  57. delete CIs[i];
  58. }
  59. ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
  60. std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
  61. assert(!includes.empty() && "No '-chain-include' in options!");
  62. OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
  63. InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
  64. SmallVector<llvm::MemoryBuffer *, 4> serialBufs;
  65. SmallVector<std::string, 4> serialBufNames;
  66. for (unsigned i = 0, e = includes.size(); i != e; ++i) {
  67. bool firstInclude = (i == 0);
  68. OwningPtr<CompilerInvocation> CInvok;
  69. CInvok.reset(new CompilerInvocation(CI.getInvocation()));
  70. CInvok->getPreprocessorOpts().ChainedIncludes.clear();
  71. CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
  72. CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
  73. CInvok->getPreprocessorOpts().DisablePCHValidation = true;
  74. CInvok->getPreprocessorOpts().Includes.clear();
  75. CInvok->getPreprocessorOpts().MacroIncludes.clear();
  76. CInvok->getPreprocessorOpts().Macros.clear();
  77. CInvok->getFrontendOpts().Inputs.clear();
  78. FrontendInputFile InputFile(includes[i], IK);
  79. CInvok->getFrontendOpts().Inputs.push_back(InputFile);
  80. TextDiagnosticPrinter *DiagClient =
  81. new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
  82. IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  83. IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
  84. new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
  85. OwningPtr<CompilerInstance> Clang(new CompilerInstance());
  86. Clang->setInvocation(CInvok.take());
  87. Clang->setDiagnostics(Diags.getPtr());
  88. Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
  89. &Clang->getTargetOpts()));
  90. Clang->createFileManager();
  91. Clang->createSourceManager(Clang->getFileManager());
  92. Clang->createPreprocessor();
  93. Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
  94. &Clang->getPreprocessor());
  95. Clang->createASTContext();
  96. SmallVector<char, 256> serialAST;
  97. llvm::raw_svector_ostream OS(serialAST);
  98. OwningPtr<ASTConsumer> consumer;
  99. consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0,
  100. /*isysroot=*/"", &OS));
  101. Clang->getASTContext().setASTMutationListener(
  102. consumer->GetASTMutationListener());
  103. Clang->setASTConsumer(consumer.take());
  104. Clang->createSema(TU_Prefix, 0);
  105. if (firstInclude) {
  106. Preprocessor &PP = Clang->getPreprocessor();
  107. PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
  108. PP.getLangOpts());
  109. } else {
  110. assert(!serialBufs.empty());
  111. SmallVector<llvm::MemoryBuffer *, 4> bufs;
  112. for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) {
  113. bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
  114. StringRef(serialBufs[si]->getBufferStart(),
  115. serialBufs[si]->getBufferSize())));
  116. }
  117. std::string pchName = includes[i-1];
  118. llvm::raw_string_ostream os(pchName);
  119. os << ".pch" << i-1;
  120. os.flush();
  121. serialBufNames.push_back(pchName);
  122. OwningPtr<ExternalASTSource> Reader;
  123. Reader.reset(createASTReader(*Clang, pchName, bufs, serialBufNames,
  124. Clang->getASTConsumer().GetASTDeserializationListener()));
  125. if (!Reader)
  126. return 0;
  127. Clang->setModuleManager(static_cast<ASTReader*>(Reader.get()));
  128. Clang->getASTContext().setExternalSource(Reader);
  129. }
  130. if (!Clang->InitializeSourceManager(InputFile))
  131. return 0;
  132. ParseAST(Clang->getSema());
  133. OS.flush();
  134. Clang->getDiagnosticClient().EndSourceFile();
  135. serialBufs.push_back(
  136. llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(),
  137. serialAST.size())));
  138. source->CIs.push_back(Clang.take());
  139. }
  140. assert(!serialBufs.empty());
  141. std::string pchName = includes.back() + ".pch-final";
  142. serialBufNames.push_back(pchName);
  143. OwningPtr<ASTReader> Reader;
  144. Reader.reset(createASTReader(CI, pchName, serialBufs, serialBufNames));
  145. if (!Reader)
  146. return 0;
  147. source->FinalReader.reset(Reader.take());
  148. return source.take();
  149. }
  150. //===----------------------------------------------------------------------===//
  151. // ExternalASTSource interface.
  152. //===----------------------------------------------------------------------===//
  153. Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
  154. return getFinalReader().GetExternalDecl(ID);
  155. }
  156. Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
  157. return getFinalReader().GetExternalSelector(ID);
  158. }
  159. uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
  160. return getFinalReader().GetNumExternalSelectors();
  161. }
  162. Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
  163. return getFinalReader().GetExternalDeclStmt(Offset);
  164. }
  165. CXXBaseSpecifier *
  166. ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
  167. return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
  168. }
  169. bool
  170. ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
  171. DeclarationName Name) {
  172. return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
  173. }
  174. ExternalLoadResult
  175. ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC,
  176. bool (*isKindWeWant)(Decl::Kind),
  177. SmallVectorImpl<Decl*> &Result) {
  178. return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result);
  179. }
  180. void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
  181. return getFinalReader().CompleteType(Tag);
  182. }
  183. void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
  184. return getFinalReader().CompleteType(Class);
  185. }
  186. void ChainedIncludesSource::StartedDeserializing() {
  187. return getFinalReader().StartedDeserializing();
  188. }
  189. void ChainedIncludesSource::FinishedDeserializing() {
  190. return getFinalReader().FinishedDeserializing();
  191. }
  192. void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
  193. return getFinalReader().StartTranslationUnit(Consumer);
  194. }
  195. void ChainedIncludesSource::PrintStats() {
  196. return getFinalReader().PrintStats();
  197. }
  198. void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
  199. for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
  200. if (const ExternalASTSource *eSrc =
  201. CIs[i]->getASTContext().getExternalSource()) {
  202. eSrc->getMemoryBufferSizes(sizes);
  203. }
  204. }
  205. getFinalReader().getMemoryBufferSizes(sizes);
  206. }
  207. void ChainedIncludesSource::InitializeSema(Sema &S) {
  208. return getFinalReader().InitializeSema(S);
  209. }
  210. void ChainedIncludesSource::ForgetSema() {
  211. return getFinalReader().ForgetSema();
  212. }
  213. void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
  214. getFinalReader().ReadMethodPool(Sel);
  215. }
  216. bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
  217. return getFinalReader().LookupUnqualified(R, S);
  218. }