clang API Documentation
00001 //===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the ChainedIncludesSource class, which converts headers 00011 // to chained PCHs in memory, mainly used for testing. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/Basic/TargetInfo.h" 00016 #include "clang/Frontend/ASTUnit.h" 00017 #include "clang/Frontend/CompilerInstance.h" 00018 #include "clang/Frontend/TextDiagnosticPrinter.h" 00019 #include "clang/Lex/Preprocessor.h" 00020 #include "clang/Parse/ParseAST.h" 00021 #include "clang/Serialization/ASTReader.h" 00022 #include "clang/Serialization/ASTWriter.h" 00023 #include "llvm/Support/MemoryBuffer.h" 00024 00025 using namespace clang; 00026 00027 namespace { 00028 class ChainedIncludesSource : public ExternalSemaSource { 00029 public: 00030 virtual ~ChainedIncludesSource(); 00031 00032 ExternalSemaSource &getFinalReader() const { return *FinalReader; } 00033 00034 std::vector<CompilerInstance *> CIs; 00035 IntrusiveRefCntPtr<ExternalSemaSource> FinalReader; 00036 00037 protected: 00038 //===----------------------------------------------------------------------===// 00039 // ExternalASTSource interface. 00040 //===----------------------------------------------------------------------===// 00041 00042 Decl *GetExternalDecl(uint32_t ID) override; 00043 Selector GetExternalSelector(uint32_t ID) override; 00044 uint32_t GetNumExternalSelectors() override; 00045 Stmt *GetExternalDeclStmt(uint64_t Offset) override; 00046 CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; 00047 bool FindExternalVisibleDeclsByName(const DeclContext *DC, 00048 DeclarationName Name) override; 00049 ExternalLoadResult 00050 FindExternalLexicalDecls(const DeclContext *DC, 00051 bool (*isKindWeWant)(Decl::Kind), 00052 SmallVectorImpl<Decl *> &Result) override; 00053 void CompleteType(TagDecl *Tag) override; 00054 void CompleteType(ObjCInterfaceDecl *Class) override; 00055 void StartedDeserializing() override; 00056 void FinishedDeserializing() override; 00057 void StartTranslationUnit(ASTConsumer *Consumer) override; 00058 void PrintStats() override; 00059 00060 /// Return the amount of memory used by memory buffers, breaking down 00061 /// by heap-backed versus mmap'ed memory. 00062 void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override; 00063 00064 //===----------------------------------------------------------------------===// 00065 // ExternalSemaSource interface. 00066 //===----------------------------------------------------------------------===// 00067 00068 void InitializeSema(Sema &S) override; 00069 void ForgetSema() override; 00070 void ReadMethodPool(Selector Sel) override; 00071 bool LookupUnqualified(LookupResult &R, Scope *S) override; 00072 }; 00073 } 00074 00075 static ASTReader * 00076 createASTReader(CompilerInstance &CI, StringRef pchFile, 00077 SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs, 00078 SmallVectorImpl<std::string> &bufNames, 00079 ASTDeserializationListener *deserialListener = nullptr) { 00080 Preprocessor &PP = CI.getPreprocessor(); 00081 std::unique_ptr<ASTReader> Reader; 00082 Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"", 00083 /*DisableValidation=*/true)); 00084 for (unsigned ti = 0; ti < bufNames.size(); ++ti) { 00085 StringRef sr(bufNames[ti]); 00086 Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti])); 00087 } 00088 Reader->setDeserializationListener(deserialListener); 00089 switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(), 00090 ASTReader::ARR_None)) { 00091 case ASTReader::Success: 00092 // Set the predefines buffer as suggested by the PCH reader. 00093 PP.setPredefines(Reader->getSuggestedPredefines()); 00094 return Reader.release(); 00095 00096 case ASTReader::Failure: 00097 case ASTReader::Missing: 00098 case ASTReader::OutOfDate: 00099 case ASTReader::VersionMismatch: 00100 case ASTReader::ConfigurationMismatch: 00101 case ASTReader::HadErrors: 00102 break; 00103 } 00104 return nullptr; 00105 } 00106 00107 ChainedIncludesSource::~ChainedIncludesSource() { 00108 for (unsigned i = 0, e = CIs.size(); i != e; ++i) 00109 delete CIs[i]; 00110 } 00111 00112 IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource( 00113 CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> &Reader) { 00114 00115 std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes; 00116 assert(!includes.empty() && "No '-chain-include' in options!"); 00117 00118 IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource()); 00119 InputKind IK = CI.getFrontendOpts().Inputs[0].getKind(); 00120 00121 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> SerialBufs; 00122 SmallVector<std::string, 4> serialBufNames; 00123 00124 for (unsigned i = 0, e = includes.size(); i != e; ++i) { 00125 bool firstInclude = (i == 0); 00126 std::unique_ptr<CompilerInvocation> CInvok; 00127 CInvok.reset(new CompilerInvocation(CI.getInvocation())); 00128 00129 CInvok->getPreprocessorOpts().ChainedIncludes.clear(); 00130 CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear(); 00131 CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear(); 00132 CInvok->getPreprocessorOpts().DisablePCHValidation = true; 00133 CInvok->getPreprocessorOpts().Includes.clear(); 00134 CInvok->getPreprocessorOpts().MacroIncludes.clear(); 00135 CInvok->getPreprocessorOpts().Macros.clear(); 00136 00137 CInvok->getFrontendOpts().Inputs.clear(); 00138 FrontendInputFile InputFile(includes[i], IK); 00139 CInvok->getFrontendOpts().Inputs.push_back(InputFile); 00140 00141 TextDiagnosticPrinter *DiagClient = 00142 new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions()); 00143 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 00144 IntrusiveRefCntPtr<DiagnosticsEngine> Diags( 00145 new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); 00146 00147 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); 00148 Clang->setInvocation(CInvok.release()); 00149 Clang->setDiagnostics(Diags.get()); 00150 Clang->setTarget(TargetInfo::CreateTargetInfo( 00151 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); 00152 Clang->createFileManager(); 00153 Clang->createSourceManager(Clang->getFileManager()); 00154 Clang->createPreprocessor(TU_Prefix); 00155 Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), 00156 &Clang->getPreprocessor()); 00157 Clang->createASTContext(); 00158 00159 SmallVector<char, 256> serialAST; 00160 llvm::raw_svector_ostream OS(serialAST); 00161 auto consumer = 00162 llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr, 00163 /*isysroot=*/"", &OS); 00164 Clang->getASTContext().setASTMutationListener( 00165 consumer->GetASTMutationListener()); 00166 Clang->setASTConsumer(std::move(consumer)); 00167 Clang->createSema(TU_Prefix, nullptr); 00168 00169 if (firstInclude) { 00170 Preprocessor &PP = Clang->getPreprocessor(); 00171 PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 00172 PP.getLangOpts()); 00173 } else { 00174 assert(!SerialBufs.empty()); 00175 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> Bufs; 00176 // TODO: Pass through the existing MemoryBuffer instances instead of 00177 // allocating new ones. 00178 for (auto &SB : SerialBufs) 00179 Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer())); 00180 std::string pchName = includes[i-1]; 00181 llvm::raw_string_ostream os(pchName); 00182 os << ".pch" << i-1; 00183 serialBufNames.push_back(os.str()); 00184 00185 IntrusiveRefCntPtr<ASTReader> Reader; 00186 Reader = createASTReader( 00187 *Clang, pchName, Bufs, serialBufNames, 00188 Clang->getASTConsumer().GetASTDeserializationListener()); 00189 if (!Reader) 00190 return nullptr; 00191 Clang->setModuleManager(Reader); 00192 Clang->getASTContext().setExternalSource(Reader); 00193 } 00194 00195 if (!Clang->InitializeSourceManager(InputFile)) 00196 return nullptr; 00197 00198 ParseAST(Clang->getSema()); 00199 Clang->getDiagnosticClient().EndSourceFile(); 00200 SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str())); 00201 source->CIs.push_back(Clang.release()); 00202 } 00203 00204 assert(!SerialBufs.empty()); 00205 std::string pchName = includes.back() + ".pch-final"; 00206 serialBufNames.push_back(pchName); 00207 Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames); 00208 if (!Reader) 00209 return nullptr; 00210 00211 source->FinalReader = Reader; 00212 return source; 00213 } 00214 00215 //===----------------------------------------------------------------------===// 00216 // ExternalASTSource interface. 00217 //===----------------------------------------------------------------------===// 00218 00219 Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) { 00220 return getFinalReader().GetExternalDecl(ID); 00221 } 00222 Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) { 00223 return getFinalReader().GetExternalSelector(ID); 00224 } 00225 uint32_t ChainedIncludesSource::GetNumExternalSelectors() { 00226 return getFinalReader().GetNumExternalSelectors(); 00227 } 00228 Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) { 00229 return getFinalReader().GetExternalDeclStmt(Offset); 00230 } 00231 CXXBaseSpecifier * 00232 ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { 00233 return getFinalReader().GetExternalCXXBaseSpecifiers(Offset); 00234 } 00235 bool 00236 ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC, 00237 DeclarationName Name) { 00238 return getFinalReader().FindExternalVisibleDeclsByName(DC, Name); 00239 } 00240 ExternalLoadResult 00241 ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC, 00242 bool (*isKindWeWant)(Decl::Kind), 00243 SmallVectorImpl<Decl*> &Result) { 00244 return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result); 00245 } 00246 void ChainedIncludesSource::CompleteType(TagDecl *Tag) { 00247 return getFinalReader().CompleteType(Tag); 00248 } 00249 void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) { 00250 return getFinalReader().CompleteType(Class); 00251 } 00252 void ChainedIncludesSource::StartedDeserializing() { 00253 return getFinalReader().StartedDeserializing(); 00254 } 00255 void ChainedIncludesSource::FinishedDeserializing() { 00256 return getFinalReader().FinishedDeserializing(); 00257 } 00258 void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) { 00259 return getFinalReader().StartTranslationUnit(Consumer); 00260 } 00261 void ChainedIncludesSource::PrintStats() { 00262 return getFinalReader().PrintStats(); 00263 } 00264 void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{ 00265 for (unsigned i = 0, e = CIs.size(); i != e; ++i) { 00266 if (const ExternalASTSource *eSrc = 00267 CIs[i]->getASTContext().getExternalSource()) { 00268 eSrc->getMemoryBufferSizes(sizes); 00269 } 00270 } 00271 00272 getFinalReader().getMemoryBufferSizes(sizes); 00273 } 00274 00275 void ChainedIncludesSource::InitializeSema(Sema &S) { 00276 return getFinalReader().InitializeSema(S); 00277 } 00278 void ChainedIncludesSource::ForgetSema() { 00279 return getFinalReader().ForgetSema(); 00280 } 00281 void ChainedIncludesSource::ReadMethodPool(Selector Sel) { 00282 getFinalReader().ReadMethodPool(Sel); 00283 } 00284 bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) { 00285 return getFinalReader().LookupUnqualified(R, S); 00286 } 00287