clang  3.7.0
ChainedIncludesSource.cpp
Go to the documentation of this file.
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 
15 #include "clang/Basic/TargetInfo.h"
16 #include "clang/Frontend/ASTUnit.h"
19 #include "clang/Lex/Preprocessor.h"
20 #include "clang/Parse/ParseAST.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 
25 using namespace clang;
26 
27 namespace {
28 class ChainedIncludesSource : public ExternalSemaSource {
29 public:
30  ~ChainedIncludesSource() override;
31 
32  ExternalSemaSource &getFinalReader() const { return *FinalReader; }
33 
34  std::vector<CompilerInstance *> CIs;
36 
37 protected:
38  //===----------------------------------------------------------------------===//
39  // ExternalASTSource interface.
40  //===----------------------------------------------------------------------===//
41 
42  Decl *GetExternalDecl(uint32_t ID) override;
43  Selector GetExternalSelector(uint32_t ID) override;
44  uint32_t GetNumExternalSelectors() override;
45  Stmt *GetExternalDeclStmt(uint64_t Offset) override;
46  CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
47  CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
48  bool FindExternalVisibleDeclsByName(const DeclContext *DC,
49  DeclarationName Name) override;
51  FindExternalLexicalDecls(const DeclContext *DC,
52  bool (*isKindWeWant)(Decl::Kind),
54  void CompleteType(TagDecl *Tag) override;
55  void CompleteType(ObjCInterfaceDecl *Class) override;
56  void StartedDeserializing() override;
57  void FinishedDeserializing() override;
58  void StartTranslationUnit(ASTConsumer *Consumer) override;
59  void PrintStats() override;
60 
61  /// Return the amount of memory used by memory buffers, breaking down
62  /// by heap-backed versus mmap'ed memory.
63  void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
64 
65  //===----------------------------------------------------------------------===//
66  // ExternalSemaSource interface.
67  //===----------------------------------------------------------------------===//
68 
69  void InitializeSema(Sema &S) override;
70  void ForgetSema() override;
71  void ReadMethodPool(Selector Sel) override;
72  bool LookupUnqualified(LookupResult &R, Scope *S) override;
73 };
74 }
75 
76 static ASTReader *
77 createASTReader(CompilerInstance &CI, StringRef pchFile,
78  SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs,
80  ASTDeserializationListener *deserialListener = nullptr) {
81  Preprocessor &PP = CI.getPreprocessor();
82  std::unique_ptr<ASTReader> Reader;
83  Reader.reset(new ASTReader(PP, CI.getASTContext(),
85  /*isysroot=*/"", /*DisableValidation=*/true));
86  for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
87  StringRef sr(bufNames[ti]);
88  Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
89  }
90  Reader->setDeserializationListener(deserialListener);
91  switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
93  case ASTReader::Success:
94  // Set the predefines buffer as suggested by the PCH reader.
95  PP.setPredefines(Reader->getSuggestedPredefines());
96  return Reader.release();
97 
98  case ASTReader::Failure:
99  case ASTReader::Missing:
104  break;
105  }
106  return nullptr;
107 }
108 
109 ChainedIncludesSource::~ChainedIncludesSource() {
110  for (unsigned i = 0, e = CIs.size(); i != e; ++i)
111  delete CIs[i];
112 }
113 
116 
117  std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
118  assert(!includes.empty() && "No '-chain-include' in options!");
119 
120  IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
121  InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
122 
124  SmallVector<std::string, 4> serialBufNames;
125 
126  for (unsigned i = 0, e = includes.size(); i != e; ++i) {
127  bool firstInclude = (i == 0);
128  std::unique_ptr<CompilerInvocation> CInvok;
129  CInvok.reset(new CompilerInvocation(CI.getInvocation()));
130 
131  CInvok->getPreprocessorOpts().ChainedIncludes.clear();
132  CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
133  CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
134  CInvok->getPreprocessorOpts().DisablePCHValidation = true;
135  CInvok->getPreprocessorOpts().Includes.clear();
136  CInvok->getPreprocessorOpts().MacroIncludes.clear();
137  CInvok->getPreprocessorOpts().Macros.clear();
138 
139  CInvok->getFrontendOpts().Inputs.clear();
140  FrontendInputFile InputFile(includes[i], IK);
141  CInvok->getFrontendOpts().Inputs.push_back(InputFile);
142 
143  TextDiagnosticPrinter *DiagClient =
144  new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
147  new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
148 
149  std::unique_ptr<CompilerInstance> Clang(
151  Clang->setInvocation(CInvok.release());
152  Clang->setDiagnostics(Diags.get());
153  Clang->setTarget(TargetInfo::CreateTargetInfo(
154  Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
155  Clang->createFileManager();
156  Clang->createSourceManager(Clang->getFileManager());
157  Clang->createPreprocessor(TU_Prefix);
158  Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
159  &Clang->getPreprocessor());
160  Clang->createASTContext();
161 
162  auto Buffer = std::make_shared<PCHBuffer>();
163  auto consumer = llvm::make_unique<PCHGenerator>(
164  Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer);
165  Clang->getASTContext().setASTMutationListener(
166  consumer->GetASTMutationListener());
167  Clang->setASTConsumer(std::move(consumer));
168  Clang->createSema(TU_Prefix, nullptr);
169 
170  if (firstInclude) {
171  Preprocessor &PP = Clang->getPreprocessor();
173  PP.getLangOpts());
174  } else {
175  assert(!SerialBufs.empty());
177  // TODO: Pass through the existing MemoryBuffer instances instead of
178  // allocating new ones.
179  for (auto &SB : SerialBufs)
180  Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
181  std::string pchName = includes[i-1];
182  llvm::raw_string_ostream os(pchName);
183  os << ".pch" << i-1;
184  serialBufNames.push_back(os.str());
185 
187  Reader = createASTReader(
188  *Clang, pchName, Bufs, serialBufNames,
189  Clang->getASTConsumer().GetASTDeserializationListener());
190  if (!Reader)
191  return nullptr;
192  Clang->setModuleManager(Reader);
193  Clang->getASTContext().setExternalSource(Reader);
194  }
195 
196  if (!Clang->InitializeSourceManager(InputFile))
197  return nullptr;
198 
199  ParseAST(Clang->getSema());
200  Clang->getDiagnosticClient().EndSourceFile();
201  assert(Buffer->IsComplete && "serialization did not complete");
202  auto &serialAST = Buffer->Data;
203  SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
204  StringRef(serialAST.data(), serialAST.size())));
205  serialAST.clear();
206  source->CIs.push_back(Clang.release());
207  }
208 
209  assert(!SerialBufs.empty());
210  std::string pchName = includes.back() + ".pch-final";
211  serialBufNames.push_back(pchName);
212  Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
213  if (!Reader)
214  return nullptr;
215 
216  source->FinalReader = Reader;
217  return source;
218 }
219 
220 //===----------------------------------------------------------------------===//
221 // ExternalASTSource interface.
222 //===----------------------------------------------------------------------===//
223 
224 Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
225  return getFinalReader().GetExternalDecl(ID);
226 }
227 Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
228  return getFinalReader().GetExternalSelector(ID);
229 }
230 uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
231  return getFinalReader().GetNumExternalSelectors();
232 }
233 Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
234  return getFinalReader().GetExternalDeclStmt(Offset);
235 }
237 ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
238  return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
239 }
241 ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
242  return getFinalReader().GetExternalCXXCtorInitializers(Offset);
243 }
244 bool
245 ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
246  DeclarationName Name) {
247  return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
248 }
250 ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC,
251  bool (*isKindWeWant)(Decl::Kind),
252  SmallVectorImpl<Decl*> &Result) {
253  return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result);
254 }
255 void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
256  return getFinalReader().CompleteType(Tag);
257 }
258 void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
259  return getFinalReader().CompleteType(Class);
260 }
261 void ChainedIncludesSource::StartedDeserializing() {
262  return getFinalReader().StartedDeserializing();
263 }
264 void ChainedIncludesSource::FinishedDeserializing() {
265  return getFinalReader().FinishedDeserializing();
266 }
267 void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
268  return getFinalReader().StartTranslationUnit(Consumer);
269 }
270 void ChainedIncludesSource::PrintStats() {
271  return getFinalReader().PrintStats();
272 }
273 void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
274  for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
275  if (const ExternalASTSource *eSrc =
276  CIs[i]->getASTContext().getExternalSource()) {
277  eSrc->getMemoryBufferSizes(sizes);
278  }
279  }
280 
281  getFinalReader().getMemoryBufferSizes(sizes);
282 }
283 
284 void ChainedIncludesSource::InitializeSema(Sema &S) {
285  return getFinalReader().InitializeSema(S);
286 }
287 void ChainedIncludesSource::ForgetSema() {
288  return getFinalReader().ForgetSema();
289 }
290 void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
291  getFinalReader().ReadMethodPool(Sel);
292 }
293 bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
294  return getFinalReader().LookupUnqualified(R, S);
295 }
296 
ASTContext & getASTContext() const
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
Smart pointer class that efficiently represents Objective-C method names.
IntrusiveRefCntPtr< ExternalSemaSource > createChainedIncludesSource(CompilerInstance &CI, IntrusiveRefCntPtr< ExternalSemaSource > &Reader)
DiagnosticOptions & getDiagnosticOpts()
The translation unit is a prefix to a translation unit, and is not complete.
Definition: LangOptions.h:168
static ASTReader * createASTReader(CompilerInstance &CI, StringRef pchFile, SmallVectorImpl< std::unique_ptr< llvm::MemoryBuffer >> &MemBufs, SmallVectorImpl< std::string > &bufNames, ASTDeserializationListener *deserialListener=nullptr)
The AST file has errors.
Definition: ASTReader.h:333
Builtin::Context & getBuiltinInfo()
Definition: Preprocessor.h:688
void setPredefines(const char *P)
Set the predefines for this Preprocessor.
Definition: Preprocessor.h:917
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:679
Represents the results of name lookup.
Definition: Lookup.h:30
FrontendOptions & getFrontendOpts()
uint32_t Offset
Definition: CacheTokens.cpp:43
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:135
Represents an ObjC class declaration.
Definition: DeclObjC.h:851
The AST file itself appears corrupted.
Definition: ASTReader.h:321
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:258
std::vector< std::string > ChainedIncludes
Headers that will be converted to chained PCHs in memory.
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
ExternalLoadResult
Enumeration describing the result of loading information from an external source. ...
Defines the clang::Preprocessor interface.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
Definition: Targets.cpp:7387
An input file for the front end.
The result type of a method or function.
The client can't handle any AST loading failures.
Definition: ASTReader.h:1311
The AST file was missing.
Definition: ASTReader.h:323
An abstract interface that should be implemented by external AST sources that also provide informatio...
Abstract interface for external sources of AST nodes.
The control block was read successfully. Aside from failures, the AST file is safe to read into the c...
Definition: ASTReader.h:319
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
const PCHContainerReader & getPCHContainerReader() const
File is a PCH file treated as such.
Options for controlling the compiler diagnostics engine.
std::vector< FrontendInputFile > Inputs
The input files and their types.
TagDecl - Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:2694
IdentifierTable & getIdentifierTable()
Definition: Preprocessor.h:685
void ParseAST(Preprocessor &pp, ASTConsumer *C, ASTContext &Ctx, bool PrintStats=false, TranslationUnitKind TUKind=TU_Complete, CodeCompleteConsumer *CompletionConsumer=nullptr, bool SkipFunctionBodies=false)
Parse the entire file specified, notifying the ASTConsumer as the file is parsed. ...
Definition: ParseAST.cpp:84
std::shared_ptr< PCHContainerOperations > getPCHContainerOperations() const
The AST file was writtten with a different language/target configuration.
Definition: ASTReader.h:331
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:302
Used for handling and querying diagnostic IDs.
Helper class for holding the data necessary to invoke the compiler.
Represents a C++ base or member initializer.
Definition: DeclCXX.h:1901
Represents a base class of a C++ class.
Definition: DeclCXX.h:157
void InitializeBuiltins(IdentifierTable &Table, const LangOptions &LangOpts)
Mark the identifiers for all the builtins with their appropriate builtin ID # and mark any non-portab...
Definition: Builtins.cpp:69
Defines the clang::TargetInfo interface.
The AST file is out-of-date relative to its input files, and needs to be regenerated.
Definition: ASTReader.h:326
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:76
The AST file was written by a different version of Clang.
Definition: ASTReader.h:328
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:96