clang API Documentation

ChainedIncludesSource.cpp
Go to the documentation of this file.
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/Frontend/ChainedIncludesSource.h"
00016 #include "clang/Frontend/TextDiagnosticPrinter.h"
00017 #include "clang/Frontend/CompilerInstance.h"
00018 #include "clang/Frontend/ASTUnit.h"
00019 #include "clang/Serialization/ASTReader.h"
00020 #include "clang/Serialization/ASTWriter.h"
00021 #include "clang/Parse/ParseAST.h"
00022 #include "clang/Lex/Preprocessor.h"
00023 #include "clang/Basic/TargetInfo.h"
00024 #include "llvm/Support/MemoryBuffer.h"
00025 
00026 using namespace clang;
00027 
00028 static ASTReader *createASTReader(CompilerInstance &CI,
00029                                   StringRef pchFile,  
00030                                   SmallVector<llvm::MemoryBuffer *, 4> &memBufs,
00031                                   SmallVector<std::string, 4> &bufNames,
00032                              ASTDeserializationListener *deserialListener = 0) {
00033   Preprocessor &PP = CI.getPreprocessor();
00034   OwningPtr<ASTReader> Reader;
00035   Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"",
00036                              /*DisableValidation=*/true));
00037   for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
00038     StringRef sr(bufNames[ti]);
00039     Reader->addInMemoryBuffer(sr, memBufs[ti]);
00040   }
00041   Reader->setDeserializationListener(deserialListener);
00042   switch (Reader->ReadAST(pchFile, serialization::MK_PCH)) {
00043   case ASTReader::Success:
00044     // Set the predefines buffer as suggested by the PCH reader.
00045     PP.setPredefines(Reader->getSuggestedPredefines());
00046     return Reader.take();
00047 
00048   case ASTReader::Failure:
00049   case ASTReader::IgnorePCH:
00050     break;
00051   }
00052   return 0;
00053 }
00054 
00055 ChainedIncludesSource::~ChainedIncludesSource() {
00056   for (unsigned i = 0, e = CIs.size(); i != e; ++i)
00057     delete CIs[i];
00058 }
00059 
00060 ChainedIncludesSource *ChainedIncludesSource::create(CompilerInstance &CI) {
00061 
00062   std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
00063   assert(!includes.empty() && "No '-chain-include' in options!");
00064 
00065   OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
00066   InputKind IK = CI.getFrontendOpts().Inputs[0].Kind;
00067 
00068   SmallVector<llvm::MemoryBuffer *, 4> serialBufs;
00069   SmallVector<std::string, 4> serialBufNames;
00070 
00071   for (unsigned i = 0, e = includes.size(); i != e; ++i) {
00072     bool firstInclude = (i == 0);
00073     OwningPtr<CompilerInvocation> CInvok;
00074     CInvok.reset(new CompilerInvocation(CI.getInvocation()));
00075     
00076     CInvok->getPreprocessorOpts().ChainedIncludes.clear();
00077     CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
00078     CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
00079     CInvok->getPreprocessorOpts().DisablePCHValidation = true;
00080     CInvok->getPreprocessorOpts().Includes.clear();
00081     CInvok->getPreprocessorOpts().MacroIncludes.clear();
00082     CInvok->getPreprocessorOpts().Macros.clear();
00083     
00084     CInvok->getFrontendOpts().Inputs.clear();
00085     CInvok->getFrontendOpts().Inputs.push_back(FrontendInputFile(includes[i],
00086                                                                  IK));
00087 
00088     TextDiagnosticPrinter *DiagClient =
00089       new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
00090     IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
00091     IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
00092         new DiagnosticsEngine(DiagID, DiagClient));
00093 
00094     OwningPtr<CompilerInstance> Clang(new CompilerInstance());
00095     Clang->setInvocation(CInvok.take());
00096     Clang->setDiagnostics(Diags.getPtr());
00097     Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
00098                                                   Clang->getTargetOpts()));
00099     Clang->createFileManager();
00100     Clang->createSourceManager(Clang->getFileManager());
00101     Clang->createPreprocessor();
00102     Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
00103                                                  &Clang->getPreprocessor());
00104     Clang->createASTContext();
00105 
00106     SmallVector<char, 256> serialAST;
00107     llvm::raw_svector_ostream OS(serialAST);
00108     OwningPtr<ASTConsumer> consumer;
00109     consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", 0,
00110                                     /*isysroot=*/"", &OS));
00111     Clang->getASTContext().setASTMutationListener(
00112                                             consumer->GetASTMutationListener());
00113     Clang->setASTConsumer(consumer.take());
00114     Clang->createSema(TU_Prefix, 0);
00115 
00116     if (firstInclude) {
00117       Preprocessor &PP = Clang->getPreprocessor();
00118       PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
00119                                              PP.getLangOpts());
00120     } else {
00121       assert(!serialBufs.empty());
00122       SmallVector<llvm::MemoryBuffer *, 4> bufs;
00123       for (unsigned si = 0, se = serialBufs.size(); si != se; ++si) {
00124         bufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
00125                              StringRef(serialBufs[si]->getBufferStart(),
00126                                              serialBufs[si]->getBufferSize())));
00127       }
00128       std::string pchName = includes[i-1];
00129       llvm::raw_string_ostream os(pchName);
00130       os << ".pch" << i-1;
00131       os.flush();
00132       
00133       serialBufNames.push_back(pchName);
00134 
00135       OwningPtr<ExternalASTSource> Reader;
00136 
00137       Reader.reset(createASTReader(*Clang, pchName, bufs, serialBufNames, 
00138         Clang->getASTConsumer().GetASTDeserializationListener()));
00139       if (!Reader)
00140         return 0;
00141       Clang->getASTContext().setExternalSource(Reader);
00142     }
00143     
00144     if (!Clang->InitializeSourceManager(includes[i]))
00145       return 0;
00146 
00147     ParseAST(Clang->getSema());
00148     OS.flush();
00149     Clang->getDiagnosticClient().EndSourceFile();
00150     serialBufs.push_back(
00151       llvm::MemoryBuffer::getMemBufferCopy(StringRef(serialAST.data(),
00152                                                            serialAST.size())));
00153     source->CIs.push_back(Clang.take());
00154   }
00155 
00156   assert(!serialBufs.empty());
00157   std::string pchName = includes.back() + ".pch-final";
00158   serialBufNames.push_back(pchName);
00159   OwningPtr<ASTReader> Reader;
00160   Reader.reset(createASTReader(CI, pchName, serialBufs, serialBufNames));
00161   if (!Reader)
00162     return 0;
00163 
00164   source->FinalReader.reset(Reader.take());
00165   return source.take();
00166 }
00167 
00168 //===----------------------------------------------------------------------===//
00169 // ExternalASTSource interface.
00170 //===----------------------------------------------------------------------===//
00171 
00172 Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
00173   return getFinalReader().GetExternalDecl(ID);
00174 }
00175 Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
00176   return getFinalReader().GetExternalSelector(ID);
00177 }
00178 uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
00179   return getFinalReader().GetNumExternalSelectors();
00180 }
00181 Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
00182   return getFinalReader().GetExternalDeclStmt(Offset);
00183 }
00184 CXXBaseSpecifier *
00185 ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
00186   return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
00187 }
00188 DeclContextLookupResult
00189 ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
00190                                                       DeclarationName Name) {
00191   return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
00192 }
00193 ExternalLoadResult 
00194 ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC,
00195                                       bool (*isKindWeWant)(Decl::Kind),
00196                                       SmallVectorImpl<Decl*> &Result) {
00197   return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result);
00198 }
00199 void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
00200   return getFinalReader().CompleteType(Tag);
00201 }
00202 void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
00203   return getFinalReader().CompleteType(Class);
00204 }
00205 void ChainedIncludesSource::StartedDeserializing() {
00206   return getFinalReader().StartedDeserializing();
00207 }
00208 void ChainedIncludesSource::FinishedDeserializing() {
00209   return getFinalReader().FinishedDeserializing();
00210 }
00211 void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
00212   return getFinalReader().StartTranslationUnit(Consumer);
00213 }
00214 void ChainedIncludesSource::PrintStats() {
00215   return getFinalReader().PrintStats();
00216 }
00217 void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
00218   for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
00219     if (const ExternalASTSource *eSrc =
00220         CIs[i]->getASTContext().getExternalSource()) {
00221       eSrc->getMemoryBufferSizes(sizes);
00222     }
00223   }
00224 
00225   getFinalReader().getMemoryBufferSizes(sizes);
00226 }
00227 
00228 void ChainedIncludesSource::InitializeSema(Sema &S) {
00229   return getFinalReader().InitializeSema(S);
00230 }
00231 void ChainedIncludesSource::ForgetSema() {
00232   return getFinalReader().ForgetSema();
00233 }
00234 void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
00235   getFinalReader().ReadMethodPool(Sel);
00236 }
00237 bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
00238   return getFinalReader().LookupUnqualified(R, S);
00239 }
00240