xref: /aosp_15_r20/external/clang/lib/Frontend/ChainedIncludesSource.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  This file defines the ChainedIncludesSource class, which converts headers
11*67e74705SXin Li //  to chained PCHs in memory, mainly used for testing.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li 
15*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
16*67e74705SXin Li #include "clang/Frontend/ASTUnit.h"
17*67e74705SXin Li #include "clang/Frontend/CompilerInstance.h"
18*67e74705SXin Li #include "clang/Frontend/TextDiagnosticPrinter.h"
19*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
20*67e74705SXin Li #include "clang/Parse/ParseAST.h"
21*67e74705SXin Li #include "clang/Serialization/ASTReader.h"
22*67e74705SXin Li #include "clang/Serialization/ASTWriter.h"
23*67e74705SXin Li #include "llvm/Support/MemoryBuffer.h"
24*67e74705SXin Li 
25*67e74705SXin Li using namespace clang;
26*67e74705SXin Li 
27*67e74705SXin Li namespace {
28*67e74705SXin Li class ChainedIncludesSource : public ExternalSemaSource {
29*67e74705SXin Li public:
30*67e74705SXin Li   ~ChainedIncludesSource() override;
31*67e74705SXin Li 
getFinalReader() const32*67e74705SXin Li   ExternalSemaSource &getFinalReader() const { return *FinalReader; }
33*67e74705SXin Li 
34*67e74705SXin Li   std::vector<CompilerInstance *> CIs;
35*67e74705SXin Li   IntrusiveRefCntPtr<ExternalSemaSource> FinalReader;
36*67e74705SXin Li 
37*67e74705SXin Li protected:
38*67e74705SXin Li   //===----------------------------------------------------------------------===//
39*67e74705SXin Li   // ExternalASTSource interface.
40*67e74705SXin Li   //===----------------------------------------------------------------------===//
41*67e74705SXin Li 
42*67e74705SXin Li   Decl *GetExternalDecl(uint32_t ID) override;
43*67e74705SXin Li   Selector GetExternalSelector(uint32_t ID) override;
44*67e74705SXin Li   uint32_t GetNumExternalSelectors() override;
45*67e74705SXin Li   Stmt *GetExternalDeclStmt(uint64_t Offset) override;
46*67e74705SXin Li   CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
47*67e74705SXin Li   CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
48*67e74705SXin Li   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
49*67e74705SXin Li                                       DeclarationName Name) override;
50*67e74705SXin Li   void
51*67e74705SXin Li   FindExternalLexicalDecls(const DeclContext *DC,
52*67e74705SXin Li                            llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
53*67e74705SXin Li                            SmallVectorImpl<Decl *> &Result) override;
54*67e74705SXin Li   void CompleteType(TagDecl *Tag) override;
55*67e74705SXin Li   void CompleteType(ObjCInterfaceDecl *Class) override;
56*67e74705SXin Li   void StartedDeserializing() override;
57*67e74705SXin Li   void FinishedDeserializing() override;
58*67e74705SXin Li   void StartTranslationUnit(ASTConsumer *Consumer) override;
59*67e74705SXin Li   void PrintStats() override;
60*67e74705SXin Li 
61*67e74705SXin Li   /// Return the amount of memory used by memory buffers, breaking down
62*67e74705SXin Li   /// by heap-backed versus mmap'ed memory.
63*67e74705SXin Li   void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
64*67e74705SXin Li 
65*67e74705SXin Li   //===----------------------------------------------------------------------===//
66*67e74705SXin Li   // ExternalSemaSource interface.
67*67e74705SXin Li   //===----------------------------------------------------------------------===//
68*67e74705SXin Li 
69*67e74705SXin Li   void InitializeSema(Sema &S) override;
70*67e74705SXin Li   void ForgetSema() override;
71*67e74705SXin Li   void ReadMethodPool(Selector Sel) override;
72*67e74705SXin Li   bool LookupUnqualified(LookupResult &R, Scope *S) override;
73*67e74705SXin Li };
74*67e74705SXin Li }
75*67e74705SXin Li 
76*67e74705SXin Li static ASTReader *
createASTReader(CompilerInstance & CI,StringRef pchFile,SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> & MemBufs,SmallVectorImpl<std::string> & bufNames,ASTDeserializationListener * deserialListener=nullptr)77*67e74705SXin Li createASTReader(CompilerInstance &CI, StringRef pchFile,
78*67e74705SXin Li                 SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs,
79*67e74705SXin Li                 SmallVectorImpl<std::string> &bufNames,
80*67e74705SXin Li                 ASTDeserializationListener *deserialListener = nullptr) {
81*67e74705SXin Li   Preprocessor &PP = CI.getPreprocessor();
82*67e74705SXin Li   std::unique_ptr<ASTReader> Reader;
83*67e74705SXin Li   Reader.reset(new ASTReader(PP, CI.getASTContext(),
84*67e74705SXin Li                              CI.getPCHContainerReader(),
85*67e74705SXin Li                              /*Extensions=*/{ },
86*67e74705SXin Li                              /*isysroot=*/"", /*DisableValidation=*/true));
87*67e74705SXin Li   for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
88*67e74705SXin Li     StringRef sr(bufNames[ti]);
89*67e74705SXin Li     Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
90*67e74705SXin Li   }
91*67e74705SXin Li   Reader->setDeserializationListener(deserialListener);
92*67e74705SXin Li   switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
93*67e74705SXin Li                           ASTReader::ARR_None)) {
94*67e74705SXin Li   case ASTReader::Success:
95*67e74705SXin Li     // Set the predefines buffer as suggested by the PCH reader.
96*67e74705SXin Li     PP.setPredefines(Reader->getSuggestedPredefines());
97*67e74705SXin Li     return Reader.release();
98*67e74705SXin Li 
99*67e74705SXin Li   case ASTReader::Failure:
100*67e74705SXin Li   case ASTReader::Missing:
101*67e74705SXin Li   case ASTReader::OutOfDate:
102*67e74705SXin Li   case ASTReader::VersionMismatch:
103*67e74705SXin Li   case ASTReader::ConfigurationMismatch:
104*67e74705SXin Li   case ASTReader::HadErrors:
105*67e74705SXin Li     break;
106*67e74705SXin Li   }
107*67e74705SXin Li   return nullptr;
108*67e74705SXin Li }
109*67e74705SXin Li 
~ChainedIncludesSource()110*67e74705SXin Li ChainedIncludesSource::~ChainedIncludesSource() {
111*67e74705SXin Li   for (unsigned i = 0, e = CIs.size(); i != e; ++i)
112*67e74705SXin Li     delete CIs[i];
113*67e74705SXin Li }
114*67e74705SXin Li 
createChainedIncludesSource(CompilerInstance & CI,IntrusiveRefCntPtr<ExternalSemaSource> & Reader)115*67e74705SXin Li IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
116*67e74705SXin Li     CompilerInstance &CI, IntrusiveRefCntPtr<ExternalSemaSource> &Reader) {
117*67e74705SXin Li 
118*67e74705SXin Li   std::vector<std::string> &includes = CI.getPreprocessorOpts().ChainedIncludes;
119*67e74705SXin Li   assert(!includes.empty() && "No '-chain-include' in options!");
120*67e74705SXin Li 
121*67e74705SXin Li   IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
122*67e74705SXin Li   InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
123*67e74705SXin Li 
124*67e74705SXin Li   SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> SerialBufs;
125*67e74705SXin Li   SmallVector<std::string, 4> serialBufNames;
126*67e74705SXin Li 
127*67e74705SXin Li   for (unsigned i = 0, e = includes.size(); i != e; ++i) {
128*67e74705SXin Li     bool firstInclude = (i == 0);
129*67e74705SXin Li     std::unique_ptr<CompilerInvocation> CInvok;
130*67e74705SXin Li     CInvok.reset(new CompilerInvocation(CI.getInvocation()));
131*67e74705SXin Li 
132*67e74705SXin Li     CInvok->getPreprocessorOpts().ChainedIncludes.clear();
133*67e74705SXin Li     CInvok->getPreprocessorOpts().ImplicitPCHInclude.clear();
134*67e74705SXin Li     CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
135*67e74705SXin Li     CInvok->getPreprocessorOpts().DisablePCHValidation = true;
136*67e74705SXin Li     CInvok->getPreprocessorOpts().Includes.clear();
137*67e74705SXin Li     CInvok->getPreprocessorOpts().MacroIncludes.clear();
138*67e74705SXin Li     CInvok->getPreprocessorOpts().Macros.clear();
139*67e74705SXin Li 
140*67e74705SXin Li     CInvok->getFrontendOpts().Inputs.clear();
141*67e74705SXin Li     FrontendInputFile InputFile(includes[i], IK);
142*67e74705SXin Li     CInvok->getFrontendOpts().Inputs.push_back(InputFile);
143*67e74705SXin Li 
144*67e74705SXin Li     TextDiagnosticPrinter *DiagClient =
145*67e74705SXin Li       new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
146*67e74705SXin Li     IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
147*67e74705SXin Li     IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
148*67e74705SXin Li         new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
149*67e74705SXin Li 
150*67e74705SXin Li     std::unique_ptr<CompilerInstance> Clang(
151*67e74705SXin Li         new CompilerInstance(CI.getPCHContainerOperations()));
152*67e74705SXin Li     Clang->setInvocation(CInvok.release());
153*67e74705SXin Li     Clang->setDiagnostics(Diags.get());
154*67e74705SXin Li     Clang->setTarget(TargetInfo::CreateTargetInfo(
155*67e74705SXin Li         Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
156*67e74705SXin Li     Clang->createFileManager();
157*67e74705SXin Li     Clang->createSourceManager(Clang->getFileManager());
158*67e74705SXin Li     Clang->createPreprocessor(TU_Prefix);
159*67e74705SXin Li     Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),
160*67e74705SXin Li                                                  &Clang->getPreprocessor());
161*67e74705SXin Li     Clang->createASTContext();
162*67e74705SXin Li 
163*67e74705SXin Li     auto Buffer = std::make_shared<PCHBuffer>();
164*67e74705SXin Li     ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions;
165*67e74705SXin Li     auto consumer = llvm::make_unique<PCHGenerator>(
166*67e74705SXin Li         Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer,
167*67e74705SXin Li         Extensions, /*AllowASTWithErrors=*/true);
168*67e74705SXin Li     Clang->getASTContext().setASTMutationListener(
169*67e74705SXin Li                                             consumer->GetASTMutationListener());
170*67e74705SXin Li     Clang->setASTConsumer(std::move(consumer));
171*67e74705SXin Li     Clang->createSema(TU_Prefix, nullptr);
172*67e74705SXin Li 
173*67e74705SXin Li     if (firstInclude) {
174*67e74705SXin Li       Preprocessor &PP = Clang->getPreprocessor();
175*67e74705SXin Li       PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
176*67e74705SXin Li                                              PP.getLangOpts());
177*67e74705SXin Li     } else {
178*67e74705SXin Li       assert(!SerialBufs.empty());
179*67e74705SXin Li       SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> Bufs;
180*67e74705SXin Li       // TODO: Pass through the existing MemoryBuffer instances instead of
181*67e74705SXin Li       // allocating new ones.
182*67e74705SXin Li       for (auto &SB : SerialBufs)
183*67e74705SXin Li         Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
184*67e74705SXin Li       std::string pchName = includes[i-1];
185*67e74705SXin Li       llvm::raw_string_ostream os(pchName);
186*67e74705SXin Li       os << ".pch" << i-1;
187*67e74705SXin Li       serialBufNames.push_back(os.str());
188*67e74705SXin Li 
189*67e74705SXin Li       IntrusiveRefCntPtr<ASTReader> Reader;
190*67e74705SXin Li       Reader = createASTReader(
191*67e74705SXin Li           *Clang, pchName, Bufs, serialBufNames,
192*67e74705SXin Li           Clang->getASTConsumer().GetASTDeserializationListener());
193*67e74705SXin Li       if (!Reader)
194*67e74705SXin Li         return nullptr;
195*67e74705SXin Li       Clang->setModuleManager(Reader);
196*67e74705SXin Li       Clang->getASTContext().setExternalSource(Reader);
197*67e74705SXin Li     }
198*67e74705SXin Li 
199*67e74705SXin Li     if (!Clang->InitializeSourceManager(InputFile))
200*67e74705SXin Li       return nullptr;
201*67e74705SXin Li 
202*67e74705SXin Li     ParseAST(Clang->getSema());
203*67e74705SXin Li     Clang->getDiagnosticClient().EndSourceFile();
204*67e74705SXin Li     assert(Buffer->IsComplete && "serialization did not complete");
205*67e74705SXin Li     auto &serialAST = Buffer->Data;
206*67e74705SXin Li     SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
207*67e74705SXin Li         StringRef(serialAST.data(), serialAST.size())));
208*67e74705SXin Li     serialAST.clear();
209*67e74705SXin Li     source->CIs.push_back(Clang.release());
210*67e74705SXin Li   }
211*67e74705SXin Li 
212*67e74705SXin Li   assert(!SerialBufs.empty());
213*67e74705SXin Li   std::string pchName = includes.back() + ".pch-final";
214*67e74705SXin Li   serialBufNames.push_back(pchName);
215*67e74705SXin Li   Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
216*67e74705SXin Li   if (!Reader)
217*67e74705SXin Li     return nullptr;
218*67e74705SXin Li 
219*67e74705SXin Li   source->FinalReader = Reader;
220*67e74705SXin Li   return source;
221*67e74705SXin Li }
222*67e74705SXin Li 
223*67e74705SXin Li //===----------------------------------------------------------------------===//
224*67e74705SXin Li // ExternalASTSource interface.
225*67e74705SXin Li //===----------------------------------------------------------------------===//
226*67e74705SXin Li 
GetExternalDecl(uint32_t ID)227*67e74705SXin Li Decl *ChainedIncludesSource::GetExternalDecl(uint32_t ID) {
228*67e74705SXin Li   return getFinalReader().GetExternalDecl(ID);
229*67e74705SXin Li }
GetExternalSelector(uint32_t ID)230*67e74705SXin Li Selector ChainedIncludesSource::GetExternalSelector(uint32_t ID) {
231*67e74705SXin Li   return getFinalReader().GetExternalSelector(ID);
232*67e74705SXin Li }
GetNumExternalSelectors()233*67e74705SXin Li uint32_t ChainedIncludesSource::GetNumExternalSelectors() {
234*67e74705SXin Li   return getFinalReader().GetNumExternalSelectors();
235*67e74705SXin Li }
GetExternalDeclStmt(uint64_t Offset)236*67e74705SXin Li Stmt *ChainedIncludesSource::GetExternalDeclStmt(uint64_t Offset) {
237*67e74705SXin Li   return getFinalReader().GetExternalDeclStmt(Offset);
238*67e74705SXin Li }
239*67e74705SXin Li CXXBaseSpecifier *
GetExternalCXXBaseSpecifiers(uint64_t Offset)240*67e74705SXin Li ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
241*67e74705SXin Li   return getFinalReader().GetExternalCXXBaseSpecifiers(Offset);
242*67e74705SXin Li }
243*67e74705SXin Li CXXCtorInitializer **
GetExternalCXXCtorInitializers(uint64_t Offset)244*67e74705SXin Li ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
245*67e74705SXin Li   return getFinalReader().GetExternalCXXCtorInitializers(Offset);
246*67e74705SXin Li }
247*67e74705SXin Li bool
FindExternalVisibleDeclsByName(const DeclContext * DC,DeclarationName Name)248*67e74705SXin Li ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
249*67e74705SXin Li                                                       DeclarationName Name) {
250*67e74705SXin Li   return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
251*67e74705SXin Li }
FindExternalLexicalDecls(const DeclContext * DC,llvm::function_ref<bool (Decl::Kind)> IsKindWeWant,SmallVectorImpl<Decl * > & Result)252*67e74705SXin Li void ChainedIncludesSource::FindExternalLexicalDecls(
253*67e74705SXin Li     const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
254*67e74705SXin Li     SmallVectorImpl<Decl *> &Result) {
255*67e74705SXin Li   return getFinalReader().FindExternalLexicalDecls(DC, IsKindWeWant, Result);
256*67e74705SXin Li }
CompleteType(TagDecl * Tag)257*67e74705SXin Li void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
258*67e74705SXin Li   return getFinalReader().CompleteType(Tag);
259*67e74705SXin Li }
CompleteType(ObjCInterfaceDecl * Class)260*67e74705SXin Li void ChainedIncludesSource::CompleteType(ObjCInterfaceDecl *Class) {
261*67e74705SXin Li   return getFinalReader().CompleteType(Class);
262*67e74705SXin Li }
StartedDeserializing()263*67e74705SXin Li void ChainedIncludesSource::StartedDeserializing() {
264*67e74705SXin Li   return getFinalReader().StartedDeserializing();
265*67e74705SXin Li }
FinishedDeserializing()266*67e74705SXin Li void ChainedIncludesSource::FinishedDeserializing() {
267*67e74705SXin Li   return getFinalReader().FinishedDeserializing();
268*67e74705SXin Li }
StartTranslationUnit(ASTConsumer * Consumer)269*67e74705SXin Li void ChainedIncludesSource::StartTranslationUnit(ASTConsumer *Consumer) {
270*67e74705SXin Li   return getFinalReader().StartTranslationUnit(Consumer);
271*67e74705SXin Li }
PrintStats()272*67e74705SXin Li void ChainedIncludesSource::PrintStats() {
273*67e74705SXin Li   return getFinalReader().PrintStats();
274*67e74705SXin Li }
getMemoryBufferSizes(MemoryBufferSizes & sizes) const275*67e74705SXin Li void ChainedIncludesSource::getMemoryBufferSizes(MemoryBufferSizes &sizes)const{
276*67e74705SXin Li   for (unsigned i = 0, e = CIs.size(); i != e; ++i) {
277*67e74705SXin Li     if (const ExternalASTSource *eSrc =
278*67e74705SXin Li         CIs[i]->getASTContext().getExternalSource()) {
279*67e74705SXin Li       eSrc->getMemoryBufferSizes(sizes);
280*67e74705SXin Li     }
281*67e74705SXin Li   }
282*67e74705SXin Li 
283*67e74705SXin Li   getFinalReader().getMemoryBufferSizes(sizes);
284*67e74705SXin Li }
285*67e74705SXin Li 
InitializeSema(Sema & S)286*67e74705SXin Li void ChainedIncludesSource::InitializeSema(Sema &S) {
287*67e74705SXin Li   return getFinalReader().InitializeSema(S);
288*67e74705SXin Li }
ForgetSema()289*67e74705SXin Li void ChainedIncludesSource::ForgetSema() {
290*67e74705SXin Li   return getFinalReader().ForgetSema();
291*67e74705SXin Li }
ReadMethodPool(Selector Sel)292*67e74705SXin Li void ChainedIncludesSource::ReadMethodPool(Selector Sel) {
293*67e74705SXin Li   getFinalReader().ReadMethodPool(Sel);
294*67e74705SXin Li }
LookupUnqualified(LookupResult & R,Scope * S)295*67e74705SXin Li bool ChainedIncludesSource::LookupUnqualified(LookupResult &R, Scope *S) {
296*67e74705SXin Li   return getFinalReader().LookupUnqualified(R, S);
297*67e74705SXin Li }
298*67e74705SXin Li 
299