clang  3.8.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;
50  void
51  FindExternalLexicalDecls(const DeclContext *DC,
52  llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
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  /*Extensions=*/{ },
86  /*isysroot=*/"", /*DisableValidation=*/true));
87  for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
88  StringRef sr(bufNames[ti]);
89  Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
90  }
91  Reader->setDeserializationListener(deserialListener);
92  switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
94  case ASTReader::Success:
95  // Set the predefines buffer as suggested by the PCH reader.
96  PP.setPredefines(Reader->getSuggestedPredefines());
97  return Reader.release();
98 
99  case ASTReader::Failure:
100  case ASTReader::Missing:
105  break;
106  }
107  return nullptr;
108 }
109 
110 ChainedIncludesSource::~ChainedIncludesSource() {
111  for (unsigned i = 0, e = CIs.size(); i != e; ++i)
112  delete CIs[i];
113 }
114 
117 
118  std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
119  assert(!includes.empty() && "No '-chain-include' in options!");
120 
121  IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
122  InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
123 
125  SmallVector<std::string, 4> serialBufNames;
126 
127  for (unsigned i = 0, e = includes.size(); i != e; ++i) {
128  bool firstInclude = (i == 0);
129  std::unique_ptr<CompilerInvocation> CInvok;
130  CInvok.reset(new CompilerInvocation(CI.getInvocation()));
131 
132  CInvok->getPreprocessorOpts().ChainedIncludes.clear();
133  CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
134  CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
135  CInvok->getPreprocessorOpts().DisablePCHValidation = true;
136  CInvok->getPreprocessorOpts().Includes.clear();
137  CInvok->getPreprocessorOpts().MacroIncludes.clear();
138  CInvok->getPreprocessorOpts().Macros.clear();
139 
140  CInvok->getFrontendOpts().Inputs.clear();
141  FrontendInputFile InputFile(includes[i], IK);
142  CInvok->getFrontendOpts().Inputs.push_back(InputFile);
143 
144  TextDiagnosticPrinter *DiagClient =
145  new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
148  new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
149 
150  std::unique_ptr<CompilerInstance> Clang(
152  Clang->setInvocation(CInvok.release());
153  Clang->setDiagnostics(Diags.get());
154  Clang->setTarget(TargetInfo::CreateTargetInfo(
155  Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
156  Clang->createFileManager();
157  Clang->createSourceManager(Clang->getFileManager());
158  Clang->createPreprocessor(TU_Prefix);
159  Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
160  &Clang->getPreprocessor());
161  Clang->createASTContext();
162 
163  auto Buffer = std::make_shared<PCHBuffer>();
165  auto consumer = llvm::make_unique<PCHGenerator>(
166  Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer,
167  Extensions);
168  Clang->getASTContext().setASTMutationListener(
169  consumer->GetASTMutationListener());
170  Clang->setASTConsumer(std::move(consumer));
171  Clang->createSema(TU_Prefix, nullptr);
172 
173  if (firstInclude) {
174  Preprocessor &PP = Clang->getPreprocessor();
176  PP.getLangOpts());
177  } else {
178  assert(!SerialBufs.empty());
180  // TODO: Pass through the existing MemoryBuffer instances instead of
181  // allocating new ones.
182  for (auto &SB : SerialBufs)
183  Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
184  std::string pchName = includes[i-1];
185  llvm::raw_string_ostream os(pchName);
186  os << ".pch" << i-1;
187  serialBufNames.push_back(os.str());
188 
190  Reader = createASTReader(
191  *Clang, pchName, Bufs, serialBufNames,
192  Clang->getASTConsumer().GetASTDeserializationListener());
193  if (!Reader)
194  return nullptr;
195  Clang->setModuleManager(Reader);
196  Clang->getASTContext().setExternalSource(Reader);
197  }
198 
199  if (!Clang->InitializeSourceManager(InputFile))
200  return nullptr;
201 
202  ParseAST(Clang->getSema());
203  Clang->getDiagnosticClient().EndSourceFile();
204  assert(Buffer->IsComplete && "serialization did not complete");
205  auto &serialAST = Buffer->Data;
206  SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
207  StringRef(serialAST.data(), serialAST.size())));
208  serialAST.clear();
209  source->CIs.push_back(Clang.release());
210  }
211 
212  assert(!SerialBufs.empty());
213  std::string pchName = includes.back() + ".pch-final";
214  serialBufNames.push_back(pchName);
215  Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
216  if (!Reader)
217  return nullptr;
218 
219  source->FinalReader = Reader;
220  return source;
221 }
222 
223 //===----------------------------------------------------------------------===//
224 // ExternalASTSource interface.
225 //===----------------------------------------------------------------------===//
226 
227 Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
228  return getFinalReader().GetExternalDecl(ID);
229 }
230 Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
231  return getFinalReader().GetExternalSelector(ID);
232 }
233 uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
234  return getFinalReader().GetNumExternalSelectors();
235 }
236 Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
237  return getFinalReader().GetExternalDeclStmt(Offset);
238 }
240 ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
241  return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
242 }
244 ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
245  return getFinalReader().GetExternalCXXCtorInitializers(Offset);
246 }
247 bool
248 ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
250  return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
251 }
252 void ChainedIncludesSource::FindExternalLexicalDecls(
253  const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
254  SmallVectorImpl<Decl *> &Result) {
255  return getFinalReader().FindExternalLexicalDecls(DC, IsKindWeWant, Result);
256 }
257 void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
258  return getFinalReader().CompleteType(Tag);
259 }
260 void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
261  return getFinalReader().CompleteType(Class);
262 }
263 void ChainedIncludesSource::StartedDeserializing() {
264  return getFinalReader().StartedDeserializing();
265 }
266 void ChainedIncludesSource::FinishedDeserializing() {
267  return getFinalReader().FinishedDeserializing();
268 }
269 void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
270  return getFinalReader().StartTranslationUnit(Consumer);
271 }
272 void ChainedIncludesSource::PrintStats() {
273  return getFinalReader().PrintStats();
274 }
275 void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
276  for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
277  if (const ExternalASTSource *eSrc =
278  CIs[i]->getASTContext().getExternalSource()) {
279  eSrc->getMemoryBufferSizes(sizes);
280  }
281  }
282 
283  getFinalReader().getMemoryBufferSizes(sizes);
284 }
285 
286 void ChainedIncludesSource::InitializeSema(Sema &S) {
287  return getFinalReader().InitializeSema(S);
288 }
289 void ChainedIncludesSource::ForgetSema() {
290  return getFinalReader().ForgetSema();
291 }
292 void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
293  getFinalReader().ReadMethodPool(Sel);
294 }
295 bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
296  return getFinalReader().LookupUnqualified(R, S);
297 }
298 
ASTContext & getASTContext() const
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
Smart pointer class that efficiently represents Objective-C method names.
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Definition: ASTConsumer.h:36
IntrusiveRefCntPtr< ExternalSemaSource > createChainedIncludesSource(CompilerInstance &CI, IntrusiveRefCntPtr< ExternalSemaSource > &Reader)
The ChainedIncludesSource class converts headers to chained PCHs in memory, mainly for testing...
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:77
DiagnosticOptions & getDiagnosticOpts()
The translation unit is a prefix to a translation unit, and is not complete.
Definition: LangOptions.h:183
std::unique_ptr< llvm::MemoryBuffer > Buffer
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:342
Builtin::Context & getBuiltinInfo()
Definition: Preprocessor.h:693
void setPredefines(const char *P)
Set the predefines for this Preprocessor.
Definition: Preprocessor.h:922
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Definition: Type.h:4381
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:683
Represents the results of name lookup.
Definition: Sema/Lookup.h:30
FrontendOptions & getFrontendOpts()
uint32_t Offset
Definition: CacheTokens.cpp:44
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:135
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:38
Represents an ObjC class declaration.
Definition: DeclObjC.h:853
The AST file itself appears corrupted.
Definition: ASTReader.h:330
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:259
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
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:7940
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:1338
The AST file was missing.
Definition: ASTReader.h:332
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.
Definition: ASTReader.h:328
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
const PCHContainerReader & getPCHContainerReader() const
Return the appropriate PCHContainerReader depending on the current CodeGenOptions.
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:2644
IdentifierTable & getIdentifierTable()
Definition: Preprocessor.h:690
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:99
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:79
std::shared_ptr< PCHContainerOperations > getPCHContainerOperations() const
The AST file was writtten with a different language/target configuration.
Definition: ASTReader.h:340
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1121
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:311
DeclarationName - The name of a declaration.
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:1885
Represents a base class of a C++ class.
Definition: DeclCXX.h:157
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:335
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:83
The AST file was written by a different version of Clang.
Definition: ASTReader.h:337
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:96