1234287Sdim//===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===// 2234287Sdim// 3234287Sdim// The LLVM Compiler Infrastructure 4234287Sdim// 5234287Sdim// This file is distributed under the University of Illinois Open Source 6234287Sdim// License. See LICENSE.TXT for details. 7234287Sdim// 8234287Sdim//===----------------------------------------------------------------------===// 9234287Sdim// 10234287Sdim// This file defines the ChainedIncludesSource class, which converts headers 11234287Sdim// to chained PCHs in memory, mainly used for testing. 12234287Sdim// 13234287Sdim//===----------------------------------------------------------------------===// 14234287Sdim 15234287Sdim#include "clang/Frontend/ChainedIncludesSource.h" 16249423Sdim#include "clang/Basic/TargetInfo.h" 17249423Sdim#include "clang/Frontend/ASTUnit.h" 18249423Sdim#include "clang/Frontend/CompilerInstance.h" 19234287Sdim#include "clang/Frontend/TextDiagnosticPrinter.h" 20249423Sdim#include "clang/Lex/Preprocessor.h" 21249423Sdim#include "clang/Parse/ParseAST.h" 22234287Sdim#include "clang/Serialization/ASTReader.h" 23234287Sdim#include "clang/Serialization/ASTWriter.h" 24234287Sdim#include "llvm/Support/MemoryBuffer.h" 25234287Sdim 26234287Sdimusing namespace clang; 27234287Sdim 28234287Sdimstatic ASTReader *createASTReader(CompilerInstance &CI, 29263508Sdim StringRef pchFile, 30263508Sdim SmallVectorImpl<llvm::MemoryBuffer *> &memBufs, 31263508Sdim SmallVectorImpl<std::string> &bufNames, 32234287Sdim ASTDeserializationListener *deserialListener = 0) { 33234287Sdim Preprocessor &PP = CI.getPreprocessor(); 34234287Sdim OwningPtr<ASTReader> Reader; 35234287Sdim Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"", 36234287Sdim /*DisableValidation=*/true)); 37234287Sdim for (unsigned ti = 0; ti < bufNames.size(); ++ti) { 38234287Sdim StringRef sr(bufNames[ti]); 39234287Sdim Reader->addInMemoryBuffer(sr, memBufs[ti]); 40234287Sdim } 41234287Sdim Reader->setDeserializationListener(deserialListener); 42249423Sdim switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(), 43243830Sdim ASTReader::ARR_None)) { 44234287Sdim case ASTReader::Success: 45234287Sdim // Set the predefines buffer as suggested by the PCH reader. 46234287Sdim PP.setPredefines(Reader->getSuggestedPredefines()); 47234287Sdim return Reader.take(); 48234287Sdim 49234287Sdim case ASTReader::Failure: 50249423Sdim case ASTReader::Missing: 51243830Sdim case ASTReader::OutOfDate: 52243830Sdim case ASTReader::VersionMismatch: 53243830Sdim case ASTReader::ConfigurationMismatch: 54243830Sdim case ASTReader::HadErrors: 55234287Sdim break; 56234287Sdim } 57234287Sdim return 0; 58234287Sdim} 59234287Sdim 60234287SdimChainedIncludesSource::~ChainedIncludesSource() { 61234287Sdim for (unsigned i = 0, e = CIs.size(); i != e; ++i) 62234287Sdim delete CIs[i]; 63234287Sdim} 64234287Sdim 65234287SdimChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) { 66234287Sdim 67234287Sdim std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes; 68234287Sdim assert(!includes.empty() && "No '-chain-include' in options!"); 69234287Sdim 70234287Sdim OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource()); 71243830Sdim InputKind IK = CI.getFrontendOpts().Inputs[0].getKind(); 72234287Sdim 73234287Sdim SmallVector<llvm::MemoryBuffer *, 4> serialBufs; 74234287Sdim SmallVector<std::string, 4> serialBufNames; 75234287Sdim 76234287Sdim for (unsigned i = 0, e = includes.size(); i != e; ++i) { 77234287Sdim bool firstInclude = (i == 0); 78234287Sdim OwningPtr<CompilerInvocation> CInvok; 79234287Sdim CInvok.reset(new CompilerInvocation(CI.getInvocation())); 80234287Sdim 81234287Sdim CInvok->getPreprocessorOpts().ChainedIncludes.clear(); 82234287Sdim CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear(); 83234287Sdim CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear(); 84234287Sdim CInvok->getPreprocessorOpts().DisablePCHValidation = true; 85234287Sdim CInvok->getPreprocessorOpts().Includes.clear(); 86234287Sdim CInvok->getPreprocessorOpts().MacroIncludes.clear(); 87234287Sdim CInvok->getPreprocessorOpts().Macros.clear(); 88234287Sdim 89234287Sdim CInvok->getFrontendOpts().Inputs.clear(); 90243830Sdim FrontendInputFile InputFile(includes[i], IK); 91243830Sdim CInvok->getFrontendOpts().Inputs.push_back(InputFile); 92234287Sdim 93234287Sdim TextDiagnosticPrinter *DiagClient = 94243830Sdim new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions()); 95234287Sdim IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 96234287Sdim IntrusiveRefCntPtr<DiagnosticsEngine> Diags( 97243830Sdim new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); 98234287Sdim 99234287Sdim OwningPtr<CompilerInstance> Clang(new CompilerInstance()); 100234287Sdim Clang->setInvocation(CInvok.take()); 101234287Sdim Clang->setDiagnostics(Diags.getPtr()); 102234287Sdim Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), 103249423Sdim &Clang->getTargetOpts())); 104234287Sdim Clang->createFileManager(); 105234287Sdim Clang->createSourceManager(Clang->getFileManager()); 106234287Sdim Clang->createPreprocessor(); 107234287Sdim Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), 108234287Sdim &Clang->getPreprocessor()); 109234287Sdim Clang->createASTContext(); 110234287Sdim 111234287Sdim SmallVector<char, 256> serialAST; 112234287Sdim llvm::raw_svector_ostream OS(serialAST); 113234287Sdim OwningPtr<ASTConsumer> consumer; 114234287Sdim consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0, 115234287Sdim /*isysroot=*/"", &OS)); 116234287Sdim Clang->getASTContext().setASTMutationListener( 117234287Sdim consumer->GetASTMutationListener()); 118234287Sdim Clang->setASTConsumer(consumer.take()); 119234287Sdim Clang->createSema(TU_Prefix, 0); 120234287Sdim 121234287Sdim if (firstInclude) { 122234287Sdim Preprocessor &PP = Clang->getPreprocessor(); 123234287Sdim PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 124234287Sdim PP.getLangOpts()); 125234287Sdim } else { 126234287Sdim assert(!serialBufs.empty()); 127234287Sdim SmallVector<llvm::MemoryBuffer *, 4> bufs; 128234287Sdim for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) { 129234287Sdim bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( 130234287Sdim StringRef(serialBufs[si]->getBufferStart(), 131234287Sdim serialBufs[si]->getBufferSize()))); 132234287Sdim } 133234287Sdim std::string pchName = includes[i-1]; 134234287Sdim llvm::raw_string_ostream os(pchName); 135234287Sdim os << ".pch" << i-1; 136234287Sdim os.flush(); 137234287Sdim 138234287Sdim serialBufNames.push_back(pchName); 139234287Sdim 140234287Sdim OwningPtr<ExternalASTSource> Reader; 141234287Sdim 142234287Sdim Reader.reset(createASTReader(*Clang, pchName, bufs, serialBufNames, 143234287Sdim Clang->getASTConsumer().GetASTDeserializationListener())); 144234287Sdim if (!Reader) 145234287Sdim return 0; 146251662Sdim Clang->setModuleManager(static_cast<ASTReader*>(Reader.get())); 147234287Sdim Clang->getASTContext().setExternalSource(Reader); 148234287Sdim } 149234287Sdim 150243830Sdim if (!Clang->InitializeSourceManager(InputFile)) 151234287Sdim return 0; 152234287Sdim 153234287Sdim ParseAST(Clang->getSema()); 154234287Sdim OS.flush(); 155234287Sdim Clang->getDiagnosticClient().EndSourceFile(); 156234287Sdim serialBufs.push_back( 157234287Sdim llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(), 158234287Sdim serialAST.size()))); 159234287Sdim source->CIs.push_back(Clang.take()); 160234287Sdim } 161234287Sdim 162234287Sdim assert(!serialBufs.empty()); 163234287Sdim std::string pchName = includes.back() + ".pch-final"; 164234287Sdim serialBufNames.push_back(pchName); 165234287Sdim OwningPtr<ASTReader> Reader; 166234287Sdim Reader.reset(createASTReader(CI, pchName, serialBufs, serialBufNames)); 167234287Sdim if (!Reader) 168234287Sdim return 0; 169234287Sdim 170234287Sdim source->FinalReader.reset(Reader.take()); 171234287Sdim return source.take(); 172234287Sdim} 173234287Sdim 174234287Sdim//===----------------------------------------------------------------------===// 175234287Sdim// ExternalASTSource interface. 176234287Sdim//===----------------------------------------------------------------------===// 177234287Sdim 178234287SdimDecl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) { 179234287Sdim return getFinalReader().GetExternalDecl(ID); 180234287Sdim} 181234287SdimSelector ChainedIncludesSource::GetExternalSelector(uint32_t ID) { 182234287Sdim return getFinalReader().GetExternalSelector(ID); 183234287Sdim} 184234287Sdimuint32_t ChainedIncludesSource::GetNumExternalSelectors() { 185234287Sdim return getFinalReader().GetNumExternalSelectors(); 186234287Sdim} 187234287SdimStmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) { 188234287Sdim return getFinalReader().GetExternalDeclStmt(Offset); 189234287Sdim} 190234287SdimCXXBaseSpecifier * 191234287SdimChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { 192234287Sdim return getFinalReader().GetExternalCXXBaseSpecifiers(Offset); 193234287Sdim} 194249423Sdimbool 195234287SdimChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC, 196234287Sdim DeclarationName Name) { 197234287Sdim return getFinalReader().FindExternalVisibleDeclsByName(DC, Name); 198234287Sdim} 199234287SdimExternalLoadResult 200234287SdimChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC, 201234287Sdim bool (*isKindWeWant)(Decl::Kind), 202234287Sdim SmallVectorImpl<Decl*> &Result) { 203234287Sdim return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result); 204234287Sdim} 205234287Sdimvoid ChainedIncludesSource::CompleteType(TagDecl *Tag) { 206234287Sdim return getFinalReader().CompleteType(Tag); 207234287Sdim} 208234287Sdimvoid ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) { 209234287Sdim return getFinalReader().CompleteType(Class); 210234287Sdim} 211234287Sdimvoid ChainedIncludesSource::StartedDeserializing() { 212234287Sdim return getFinalReader().StartedDeserializing(); 213234287Sdim} 214234287Sdimvoid ChainedIncludesSource::FinishedDeserializing() { 215234287Sdim return getFinalReader().FinishedDeserializing(); 216234287Sdim} 217234287Sdimvoid ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) { 218234287Sdim return getFinalReader().StartTranslationUnit(Consumer); 219234287Sdim} 220234287Sdimvoid ChainedIncludesSource::PrintStats() { 221234287Sdim return getFinalReader().PrintStats(); 222234287Sdim} 223234287Sdimvoid ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{ 224234287Sdim for (unsigned i = 0, e = CIs.size(); i != e; ++i) { 225234287Sdim if (const ExternalASTSource *eSrc = 226234287Sdim CIs[i]->getASTContext().getExternalSource()) { 227234287Sdim eSrc->getMemoryBufferSizes(sizes); 228234287Sdim } 229234287Sdim } 230234287Sdim 231234287Sdim getFinalReader().getMemoryBufferSizes(sizes); 232234287Sdim} 233234287Sdim 234234287Sdimvoid ChainedIncludesSource::InitializeSema(Sema &S) { 235234287Sdim return getFinalReader().InitializeSema(S); 236234287Sdim} 237234287Sdimvoid ChainedIncludesSource::ForgetSema() { 238234287Sdim return getFinalReader().ForgetSema(); 239234287Sdim} 240234287Sdimvoid ChainedIncludesSource::ReadMethodPool(Selector Sel) { 241234287Sdim getFinalReader().ReadMethodPool(Sel); 242234287Sdim} 243234287Sdimbool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) { 244234287Sdim return getFinalReader().LookupUnqualified(R, S); 245234287Sdim} 246234287Sdim 247