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);
216 std::unique_ptr<ASTConsumer> IncrConsumer =
217 std::make_unique<IncrementalASTConsumer>(Interp,
CI->takeASTConsumer());
218 CI->setASTConsumer(std::move(IncrConsumer));
221 new Parser(
CI->getPreprocessor(),
CI->getSema(),
false));
225 auto PTU = ParseOrWrapTopLevelDecl();
226 if (
auto E = PTU.takeError()) {
227 consumeError(std::move(
E));
233 assert(PTU->TheModule &&
"Failed to create initial PTU");
239 Act->FinalizeAction();
243IncrementalParser::ParseOrWrapTopLevelDecl() {
246 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
254 C.addTranslationUnitDecl();
255 LastPTU.
TUPart =
C.getTranslationUnitDecl();
258 if (
P->getCurToken().is(tok::annot_repl_input_end)) {
259 P->ConsumeAnyToken();
263 S.CurContext =
nullptr;
266 S.ActOnTranslationUnitScope(
P->getCurScope());
271 for (
bool AtEOF =
P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
272 AtEOF =
P->ParseTopLevelDecl(ADecl, ImportState)) {
274 return llvm::make_error<llvm::StringError>(
"Parsing failed. "
275 "The consumer rejected a decl",
280 if (Diags.hasErrorOccurred()) {
281 PartialTranslationUnit MostRecentPTU = {
C.getTranslationUnitDecl(),
286 Diags.getClient()->clear();
287 return llvm::make_error<llvm::StringError>(
"Parsing failed.",
292 for (Decl *
D : S.WeakTopLevelDecls()) {
297 LocalInstantiations.perform();
298 GlobalInstantiations.perform();
310 std::ostringstream SourceName;
314 size_t InputSize = input.size();
316 std::unique_ptr<llvm::MemoryBuffer> MB(
317 llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
319 char *MBStart =
const_cast<char *
>(MB->getBufferStart());
320 memcpy(MBStart, input.data(), InputSize);
321 MBStart[InputSize] =
'\n';
335 return llvm::make_error<llvm::StringError>(
"Parsing failed. "
336 "Cannot enter source file.",
339 auto PTU = ParseOrWrapTopLevelDecl();
341 return PTU.takeError();
351 }
while (Tok.
isNot(tok::annot_repl_input_end));
355 assert(AssertTok.
is(tok::annot_repl_input_end) &&
356 "Lexer must be EOF when starting incremental parse!");
359 if (std::unique_ptr<llvm::Module> M =
GenModule())
360 PTU->TheModule = std::move(M);
366 static unsigned ID = 0;
380 "CodeGen wrote to a readonly module");
381 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
382 CG->StartModule(
"incr_module_" + std::to_string(
ID++), M->getContext());
391 for (
auto &&[Key, List] : *Map) {
393 std::vector<NamedDecl *> NamedDeclsToRemove;
394 bool RemoveAll =
true;
396 if (
D->getTranslationUnitDecl() == MostRecentTU)
397 NamedDeclsToRemove.push_back(
D);
401 if (LLVM_LIKELY(RemoveAll)) {
412 auto *ND = dyn_cast<NamedDecl>(
D);
416 if (ND->getDeclName().getFETokenInfo() && !
D->getLangOpts().ObjC &&
417 !
D->getLangOpts().CPlusPlus)
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...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
StoredDeclsMap * getLookupPtr() const
Retrieve the internal representation of the lookup structure.
Decl - This represents one declaration (or definition), e.g.
Represents a ValueDecl that came out of a declarator.
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.
void RemoveDecl(NamedDecl *D)
RemoveDecl - Unlink the decl from its shadowed decl chain.
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.
void CompleteExternalDeclaration(DeclaratorDecl *D) override final
CompleteExternalDeclaration - Callback invoked at the end of a translation unit to notify the consume...
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 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< llvm::Module > CachedInCodeGenModule
When CodeGen is created the first llvm::Module gets cached in many places and we must keep it alive.
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
@ 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.
IdentifierResolver IdResolver
Encodes a location in the source.
This class handles loading and caching of source files into memory.
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.
The JSON file list parser is used to communicate input to InstallAPI.
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.
The class keeps track of various objects created as part of processing incremental inputs.
TranslationUnitDecl * TUPart