clang: lib/Interpreter/IncrementalParser.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

15

21#include "llvm/IR/Module.h"

22#include "llvm/Support/CrashRecoveryContext.h"

23#include "llvm/Support/Error.h"

24

25#include

26

27#define DEBUG_TYPE "clang-repl"

28

30

31

32

35 std::list &PTUs)

37 llvm::ErrorAsOutParameter EAO(&Err);

39 P.reset(new Parser(S.getPreprocessor(), S, false));

40

43

44 P->Initialize();

45}

46

48

50IncrementalParser::ParseOrWrapTopLevelDecl() {

51

52 llvm::CrashRecoveryContextCleanupRegistrar CleanupSema(&S);

54 true);

56

57

59 C.addTranslationUnitDecl();

60

61

62 if (P->getCurToken().is(tok::annot_repl_input_end)) {

63 P->ConsumeAnyToken();

64

65

66 P->ExitScope();

68

71 }

72

75 for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;

76 AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {

78 return llvm::make_errorllvm::StringError("Parsing failed. "

79 "The consumer rejected a decl",

80 std::error_code());

81 }

82

83 DiagnosticsEngine &Diags = S.getDiagnostics();

84 if (Diags.hasErrorOccurred()) {

86

87 Diags.Reset(true);

88 Diags.getClient()->clear();

89 return llvm::make_errorllvm::StringError("Parsing failed.",

90 std::error_code());

91 }

92

93

94 for (Decl *D : S.WeakTopLevelDecls()) {

95 DeclGroupRef DGR(D);

96 Consumer->HandleTopLevelDecl(DGR);

97 }

98

99 LocalInstantiations.perform();

100 GlobalInstantiations.perform();

101

102 Consumer->HandleTranslationUnit(C);

103

104 return C.getTranslationUnitDecl();

105}

106

111

112 std::ostringstream SourceName;

113 SourceName << "input_line_" << InputCount++;

114

115

116 size_t InputSize = input.size();

117

118 std::unique_ptrllvm::MemoryBuffer MB(

119 llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,

120 SourceName.str()));

121 char *MBStart = const_cast<char *>(MB->getBufferStart());

122 memcpy(MBStart, input.data(), InputSize);

123 MBStart[InputSize] = '\n';

124

126

127

128

130

131

133 0, NewLoc);

134

135

136 if (PP.EnterSourceFile(FID, nullptr, NewLoc))

137 return llvm::make_errorllvm::StringError("Parsing failed. "

138 "Cannot enter source file.",

139 std::error_code());

140

141 auto PTU = ParseOrWrapTopLevelDecl();

142 if (!PTU)

143 return PTU.takeError();

144

145 if (PP.getLangOpts().DelayedTemplateParsing) {

146

147

148

149

151 do {

153 } while (Tok.isNot(tok::annot_repl_input_end));

154 } else {

156 PP.Lex(AssertTok);

157 assert(AssertTok.is(tok::annot_repl_input_end) &&

158 "Lexer must be EOF when starting incremental parse!");

159 }

160

161 return PTU;

162}

163

166 for (auto &&[Key, List] : *Map) {

168 std::vector<NamedDecl *> NamedDeclsToRemove;

169 bool RemoveAll = true;

171 if (D->getTranslationUnitDecl() == MostRecentTU)

172 NamedDeclsToRemove.push_back(D);

173 else

174 RemoveAll = false;

175 }

176 if (LLVM_LIKELY(RemoveAll)) {

177 Map->erase(Key);

178 } else {

179 for (NamedDecl *D : NamedDeclsToRemove)

180 List.remove(D);

181 }

182 }

183 }

184

185

186 for (Decl *D : MostRecentTU->decls()) {

187 auto *ND = dyn_cast(D);

188 if (!ND || ND->getDeclName().isEmpty())

189 continue;

190

191 if (ND->getDeclName().getFETokenInfo() && !D->getLangOpts().ObjC &&

192 !D->getLangOpts().CPlusPlus)

193 S.IdResolver.RemoveDecl(ND);

194 }

195}

196

199 std::unique_ptrllvm::Module M ) {

203

204 if (!M)

205 M = Act->GenModule();

206

207 assert((Act->getCodeGen() || M) && "Must have a llvm::Module at this point");

208

209 LastPTU.TheModule = std::move(M);

210 LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1

211 << ": [TU=" << LastPTU.TUPart);

213 LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " ("

214 << LastPTU.TheModule->getName() << ")");

215 LLVM_DEBUG(llvm::dbgs() << "]\n");

216 return LastPTU;

217}

218}

__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)

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 ...

CompilerInstance - Helper class for managing a single instance of the Clang compiler.

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.

Abstract interface for external sources of AST nodes.

An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...

A custom action enabling the incremental processing functionality.

IncrementalParser(CompilerInstance &Instance, IncrementalAction *Act, llvm::Error &Err, std::list< PartialTranslationUnit > &PTUs)

Definition IncrementalParser.cpp:33

IncrementalAction * Act

The FrontendAction used during incremental parsing.

std::list< PartialTranslationUnit > & PTUs

virtual ~IncrementalParser()

Definition IncrementalParser.cpp:47

unsigned InputCount

Counts the number of direct user input lines that have been parsed.

void CleanUpPTU(TranslationUnitDecl *MostRecentTU)

Definition IncrementalParser.cpp:164

PartialTranslationUnit & RegisterPTU(TranslationUnitDecl *TU, std::unique_ptr< llvm::Module > M={})

Register a PTU produced by Parse.

Definition IncrementalParser.cpp:198

virtual llvm::Expected< TranslationUnitDecl * > Parse(llvm::StringRef Input)

Parses incremental input by creating an in-memory file.

Definition IncrementalParser.cpp:108

std::unique_ptr< Parser > P

Parser.

ASTConsumer * Consumer

Consumer to process the produced top level decls. Owned by Act.

Sema & S

The Sema performing the incremental compilation.

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...

const LangOptions & getLangOpts() const

@ DeclScope

This is a scope that can contain a declaration.

void ActOnTranslationUnitScope(Scope *S)

Scope actions.

ASTContext & getASTContext() const

DeclContext * CurContext

CurContext - This is the current declaration context of parsing.

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.

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)) {....

The top declaration context.

The JSON file list parser is used to communicate input to InstallAPI.

@ External

External linkage, which indicates that the entity can be referred to from other translation units.

The class keeps track of various objects created as part of processing incremental inputs.

TranslationUnitDecl * TUPart

std::unique_ptr< llvm::Module > TheModule

The llvm IR produced for the input.