25#include "llvm/Option/ArgList.h"
26#include "llvm/Support/CrashRecoveryContext.h"
27#include "llvm/Support/Error.h"
28#include "llvm/Support/Timer.h"
36 std::unique_ptr<ASTConsumer> Consumer;
40 : Interp(InterpRef), Consumer(
std::move(
C)) {}
49 if (
auto *TSD = llvm::dyn_cast<TopLevelStmtDecl>(D);
50 TSD && TSD->isSemiMissing())
51 TSD->setStmt(Interp.SynthesizeExpr(cast<Expr>(TSD->getStmt())));
53 return Consumer->HandleTopLevelDecl(DGR);
56 Consumer->HandleTranslationUnit(Ctx);
59 Consumer->HandleInlineFunctionDefinition(D);
62 Consumer->HandleInterestingDecl(D);
65 Consumer->HandleTagDeclDefinition(D);
68 Consumer->HandleTagDeclRequiredDefinition(D);
71 Consumer->HandleCXXImplicitFunctionInstantiation(D);
74 Consumer->HandleTopLevelDeclInObjCContainer(D);
77 Consumer->HandleImplicitImportDecl(D);
80 Consumer->CompleteTentativeDefinition(D);
83 Consumer->CompleteExternalDeclaration(D);
86 Consumer->AssignInheritanceModel(RD);
89 Consumer->HandleCXXStaticMemberVarInstantiation(D);
92 Consumer->HandleVTable(RD);
95 return Consumer->GetASTMutationListener();
98 return Consumer->GetASTDeserializationListener();
102 return Consumer->shouldSkipFunctionBody(D);
118 bool IsTerminating =
false;
124 llvm::ErrorAsOutParameter EAO(&Err);
125 std::unique_ptr<FrontendAction> Act;
128 Err = llvm::createStringError(
129 std::errc::state_not_recoverable,
130 "Driver initialization failed. "
131 "Incremental mode for action %d is not supported",
187 assert(!IsTerminating &&
"Already finalized!");
188 IsTerminating =
true;
197 return static_cast<CodeGenAction *
>(WrappedAct)->getCodeGenerator();
203 std::unique_ptr<CompilerInstance> Instance,
204 llvm::LLVMContext &LLVMCtx,
206 : CI(
std::move(Instance)) {
207 llvm::ErrorAsOutParameter EAO(&Err);
208 Act = std::make_unique<IncrementalAction>(*
CI, LLVMCtx, Err);
211 CI->ExecuteAction(*
Act);
212 std::unique_ptr<ASTConsumer> IncrConsumer =
213 std::make_unique<IncrementalASTConsumer>(Interp,
CI->takeASTConsumer());
214 CI->setASTConsumer(std::move(IncrConsumer));
217 new Parser(
CI->getPreprocessor(),
CI->getSema(),
false));
221 auto PTU = ParseOrWrapTopLevelDecl();
222 if (
auto E = PTU.takeError()) {
223 consumeError(std::move(E));
228 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
229 CG->StartModule(
"incr_module_" + std::to_string(
PTUs.size()),
231 PTU->TheModule = std::move(M);
232 assert(PTU->TheModule &&
"Failed to create initial PTU");
238 Act->FinalizeAction();
242IncrementalParser::ParseOrWrapTopLevelDecl() {
245 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
253 C.addTranslationUnitDecl();
254 LastPTU.
TUPart =
C.getTranslationUnitDecl();
257 if (
P->getCurToken().is(tok::annot_repl_input_end)) {
258 P->ConsumeAnyToken();
262 S.CurContext =
nullptr;
265 S.ActOnTranslationUnitScope(
P->getCurScope());
270 for (
bool AtEOF =
P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
271 AtEOF =
P->ParseTopLevelDecl(ADecl, ImportState)) {
273 return llvm::make_error<llvm::StringError>(
"Parsing failed. "
274 "The consumer rejected a decl",
279 if (Diags.hasErrorOccurred()) {
280 PartialTranslationUnit MostRecentPTU = {
C.getTranslationUnitDecl(),
285 Diags.getClient()->clear();
286 return llvm::make_error<llvm::StringError>(
"Parsing failed.",
291 for (Decl *D : S.WeakTopLevelDecls()) {
296 LocalInstantiations.perform();
297 GlobalInstantiations.perform();
309 std::ostringstream SourceName;
313 size_t InputSize = input.size();
315 std::unique_ptr<llvm::MemoryBuffer> MB(
316 llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
318 char *MBStart =
const_cast<char *
>(MB->getBufferStart());
319 memcpy(MBStart, input.data(), InputSize);
320 MBStart[InputSize] =
'\n';
334 return llvm::make_error<llvm::StringError>(
"Parsing failed. "
335 "Cannot enter source file.",
338 auto PTU = ParseOrWrapTopLevelDecl();
340 return PTU.takeError();
350 }
while (Tok.
isNot(tok::annot_repl_input_end));
354 assert(AssertTok.
is(tok::annot_repl_input_end) &&
355 "Lexer must be EOF when starting incremental parse!");
358 if (std::unique_ptr<llvm::Module> M =
GenModule())
359 PTU->TheModule = std::move(M);
365 static unsigned ID = 0;
367 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
368 CG->StartModule(
"incr_module_" + std::to_string(
ID++), M->getContext());
378 for (
auto I = Map->begin(); I != Map->end(); ++I) {
382 if (D->getTranslationUnitDecl() == MostRecentTU) {
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
virtual void HandleTranslationUnit(ASTContext &Ctx)
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
Represents a C++ struct/union/class.
Abstract interface for a consumer of code-completion information.
The primary public interface to the Clang code generator.
llvm::StringRef GetMangledName(GlobalDecl GD)
Given a global declaration, return a mangled name for this declaration which has been added to this c...
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
FrontendOptions & getFrontendOpts()
bool hasCodeCompletionConsumer() const
CodeCompleteConsumer & getCodeCompletionConsumer() const
bool hasPreprocessor() const
void createSema(TranslationUnitKind TUKind, CodeCompleteConsumer *CompletionConsumer)
Create the Sema object to be used for parsing.
The results of name lookup within a DeclContext.
DeclContext * getPrimaryContext()
getPrimaryContext - There may be many different declarations of the same entity (including forward de...
StoredDeclsMap * getLookupPtr() const
Retrieve the internal representation of the lookup structure.
Decl - This represents one declaration (or definition), e.g.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Abstract base class for actions which can be performed by the frontend.
virtual bool hasIRSupport() const
Does this action support use with IR files?
CompilerInstance & getCompilerInstance() const
frontend::ActionKind ProgramAction
The frontend action to perform.
Represents a function declaration or definition.
GlobalDecl - represents a global declaration.
Describes a module import declaration, which makes the contents of the named module visible in the cu...
bool shouldSkipFunctionBody(Decl *D) override final
This callback is called for each function if the Parser was initialized with SkipFunctionBodies set t...
void HandleCXXStaticMemberVarInstantiation(VarDecl *D) override final
HandleCXXStaticMemberVarInstantiation - Tell the consumer that this.
void AssignInheritanceModel(CXXRecordDecl *RD) override final
Callback invoked when an MSInheritanceAttr has been attached to a CXXRecordDecl.
ASTDeserializationListener * GetASTDeserializationListener() override final
If the consumer is interested in entities being deserialized from AST files, it should return a point...
IncrementalASTConsumer(Interpreter &InterpRef, std::unique_ptr< ASTConsumer > C)
void HandleVTable(CXXRecordDecl *RD) override final
Callback involved at the end of a translation unit to notify the consumer that a vtable for the given...
void CompleteExternalDeclaration(VarDecl *D) override final
CompleteExternalDeclaration - Callback invoked at the end of a translation unit to notify the consume...
void HandleTagDeclDefinition(TagDecl *D) override final
HandleTagDeclDefinition - This callback is invoked each time a TagDecl (e.g.
void HandleInterestingDecl(DeclGroupRef D) override final
HandleInterestingDecl - Handle the specified interesting declaration.
void HandleImplicitImportDecl(ImportDecl *D) override final
Handle an ImportDecl that was implicitly created due to an inclusion directive.
ASTMutationListener * GetASTMutationListener() override final
If the consumer is interested in entities getting modified after their initial creation,...
bool HandleTopLevelDecl(DeclGroupRef DGR) override final
HandleTopLevelDecl - Handle the specified top-level declaration.
void PrintStats() override final
PrintStats - If desired, print any statistics.
static bool classof(const clang::ASTConsumer *)
void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override final
Invoked when a function is implicitly instantiated.
void HandleInlineFunctionDefinition(FunctionDecl *D) override final
This callback is invoked each time an inline (method or friend) function definition in a class is com...
void HandleTagDeclRequiredDefinition(const TagDecl *D) override final
This callback is invoked the first time each TagDecl is required to be complete.
void CompleteTentativeDefinition(VarDecl *D) override final
CompleteTentativeDefinition - Callback invoked at the end of a translation unit to notify the consume...
void HandleTranslationUnit(ASTContext &Ctx) override final
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override final
Handle the specified top-level declaration that occurred inside and ObjC container.
A custom action enabling the incremental processing functionality.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
TranslationUnitKind getTranslationUnitKind() override
For AST-based actions, the kind of translation unit we're handling.
IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx, llvm::Error &Err)
FrontendAction * getWrapped() const
void EndSourceFile() override
Perform any per-file post processing, deallocate per-file objects, and run statistics and output file...
std::list< PartialTranslationUnit > PTUs
List containing every information about every incrementally parsed piece of code.
llvm::StringRef GetMangledName(GlobalDecl GD) const
Uses the CodeGenModule mangled name cache and avoids recomputing.
std::unique_ptr< IncrementalAction > Act
Long-lived, incremental parsing action.
virtual llvm::Expected< PartialTranslationUnit & > Parse(llvm::StringRef Input)
Parses incremental input by creating an in-memory file.
CompilerInstance * getCI()
std::unique_ptr< CompilerInstance > CI
Compiler instance performing the incremental compilation.
virtual ~IncrementalParser()
void CleanUpPTU(PartialTranslationUnit &PTU)
unsigned InputCount
Counts the number of direct user input lines that have been parsed.
std::unique_ptr< llvm::Module > GenModule()
std::unique_ptr< Parser > P
Parser.
ASTConsumer * Consumer
Consumer to process the produced top level decls. Owned by Act.
CodeGenerator * getCodeGen() const
Provides top-level interfaces for incremental compilation and execution.
This represents a decl that may have a name.
Parser - This implements a parser for the C family of languages.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool isIncrementalProcessingEnabled() const
Returns true if incremental processing is enabled.
void Lex(Token &Result)
Lex the next token for this preprocessor.
bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir, SourceLocation Loc, bool IsFirstIncludeOfFile=true)
Add a source file to the top of the include stack and start lexing tokens from it instead of the curr...
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc.
const LangOptions & getLangOpts() const
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
@ DeclScope
This is a scope that can contain a declaration.
Sema - This implements semantic analysis and AST building for C.
ModuleImportState
An enumeration to represent the transition of states in parsing module fragments and imports.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
An array of decls optimized for the common case of only containing one entry.
Represents the declaration of a struct/union/class/enum.
Token - This structure provides full information about a lexed token.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
bool isNot(tok::TokenKind K) const
The top declaration context.
Represents a variable declaration or definition.
A frontend action which simply wraps some other runtime-specified frontend action.
std::unique_ptr< FrontendAction > WrappedAction
void EndSourceFile() override
Perform any per-file post processing, deallocate per-file objects, and run statistics and output file...
@ PrintPreprocessedInput
-E mode.
@ ParseSyntaxOnly
Parse and perform semantic analysis.
@ PluginAction
Run a plugin action,.
@ ASTPrint
Parse ASTs and print them.
@ ASTDump
Parse ASTs and dump them.
@ EmitAssembly
Emit a .s file.
@ EmitLLVMOnly
Generate LLVM IR, but do not emit anything.
std::unique_ptr< FrontendAction > CreateFrontendAction(CompilerInstance &CI)
Construct the FrontendAction of a compiler invocation based on the options specified for the compiler...
TranslationUnitKind
Describes the kind of translation unit being processed.
@ TU_Incremental
The translation unit is a is a complete translation unit that we might incrementally extend later.
@ List
New-expression has a C++11 list-initializer.
The class keeps track of various objects created as part of processing incremental inputs.
TranslationUnitDecl * TUPart