1 //===--- ClangdUnit.cpp ------------------------------------------*- 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 #include "ClangdUnit.h"
11 #include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
12 #include "../clang-tidy/ClangTidyModuleRegistry.h"
13 #include "Compiler.h"
14 #include "Diagnostics.h"
15 #include "Logger.h"
16 #include "SourceCode.h"
17 #include "Trace.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/Basic/LangOptions.h"
20 #include "clang/Frontend/CompilerInstance.h"
21 #include "clang/Frontend/CompilerInvocation.h"
22 #include "clang/Frontend/FrontendActions.h"
23 #include "clang/Frontend/Utils.h"
24 #include "clang/Index/IndexDataConsumer.h"
25 #include "clang/Index/IndexingAction.h"
26 #include "clang/Lex/Lexer.h"
27 #include "clang/Lex/MacroInfo.h"
28 #include "clang/Lex/Preprocessor.h"
29 #include "clang/Lex/PreprocessorOptions.h"
30 #include "clang/Sema/Sema.h"
31 #include "clang/Serialization/ASTWriter.h"
32 #include "clang/Tooling/CompilationDatabase.h"
33 #include "llvm/ADT/ArrayRef.h"
34 #include "llvm/ADT/SmallString.h"
35 #include "llvm/ADT/SmallVector.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include <algorithm>
38
39 namespace clang {
40 namespace clangd {
41 namespace {
42
compileCommandsAreEqual(const tooling::CompileCommand & LHS,const tooling::CompileCommand & RHS)43 bool compileCommandsAreEqual(const tooling::CompileCommand &LHS,
44 const tooling::CompileCommand &RHS) {
45 // We don't check for Output, it should not matter to clangd.
46 return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
47 llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine);
48 }
49
getUsedBytes(const std::vector<T> & Vec)50 template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
51 return Vec.capacity() * sizeof(T);
52 }
53
54 class DeclTrackingASTConsumer : public ASTConsumer {
55 public:
DeclTrackingASTConsumer(std::vector<Decl * > & TopLevelDecls)56 DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
57 : TopLevelDecls(TopLevelDecls) {}
58
HandleTopLevelDecl(DeclGroupRef DG)59 bool HandleTopLevelDecl(DeclGroupRef DG) override {
60 for (Decl *D : DG) {
61 if (D->isFromASTFile())
62 continue;
63
64 // ObjCMethodDecl are not actually top-level decls.
65 if (isa<ObjCMethodDecl>(D))
66 continue;
67
68 TopLevelDecls.push_back(D);
69 }
70 return true;
71 }
72
73 private:
74 std::vector<Decl *> &TopLevelDecls;
75 };
76
77 class ClangdFrontendAction : public SyntaxOnlyAction {
78 public:
takeTopLevelDecls()79 std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
80
81 protected:
82 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,llvm::StringRef InFile)83 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
84 return llvm::make_unique<DeclTrackingASTConsumer>(/*ref*/ TopLevelDecls);
85 }
86
87 private:
88 std::vector<Decl *> TopLevelDecls;
89 };
90
91 class CppFilePreambleCallbacks : public PreambleCallbacks {
92 public:
CppFilePreambleCallbacks(PathRef File,PreambleParsedCallback ParsedCallback)93 CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
94 : File(File), ParsedCallback(ParsedCallback) {}
95
takeIncludes()96 IncludeStructure takeIncludes() { return std::move(Includes); }
97
AfterExecute(CompilerInstance & CI)98 void AfterExecute(CompilerInstance &CI) override {
99 if (!ParsedCallback)
100 return;
101 trace::Span Tracer("Running PreambleCallback");
102 ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr());
103 }
104
BeforeExecute(CompilerInstance & CI)105 void BeforeExecute(CompilerInstance &CI) override {
106 SourceMgr = &CI.getSourceManager();
107 }
108
createPPCallbacks()109 std::unique_ptr<PPCallbacks> createPPCallbacks() override {
110 assert(SourceMgr && "SourceMgr must be set at this point");
111 return collectIncludeStructureCallback(*SourceMgr, &Includes);
112 }
113
114 private:
115 PathRef File;
116 PreambleParsedCallback ParsedCallback;
117 IncludeStructure Includes;
118 SourceManager *SourceMgr = nullptr;
119 };
120
121 // When using a preamble, only preprocessor events outside its bounds are seen.
122 // This is almost what we want: replaying transitive preprocessing wastes time.
123 // However this confuses clang-tidy checks: they don't see any #includes!
124 // So we replay the *non-transitive* #includes that appear in the main-file.
125 // It would be nice to replay other events (macro definitions, ifdefs etc) but
126 // this addresses the most common cases fairly cheaply.
127 class ReplayPreamble : private PPCallbacks {
128 public:
129 // Attach preprocessor hooks such that preamble events will be injected at
130 // the appropriate time.
131 // Events will be delivered to the *currently registered* PP callbacks.
attach(const IncludeStructure & Includes,CompilerInstance & Clang)132 static void attach(const IncludeStructure &Includes,
133 CompilerInstance &Clang) {
134 auto &PP = Clang.getPreprocessor();
135 auto *ExistingCallbacks = PP.getPPCallbacks();
136 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(
137 new ReplayPreamble(Includes, ExistingCallbacks,
138 Clang.getSourceManager(), PP, Clang.getLangOpts())));
139 // We're relying on the fact that addPPCallbacks keeps the old PPCallbacks
140 // around, creating a chaining wrapper. Guard against other implementations.
141 assert(PP.getPPCallbacks() != ExistingCallbacks &&
142 "Expected chaining implementation");
143 }
144
145 private:
ReplayPreamble(const IncludeStructure & Includes,PPCallbacks * Delegate,const SourceManager & SM,Preprocessor & PP,const LangOptions & LangOpts)146 ReplayPreamble(const IncludeStructure &Includes, PPCallbacks *Delegate,
147 const SourceManager &SM, Preprocessor &PP,
148 const LangOptions &LangOpts)
149 : Includes(Includes), Delegate(Delegate), SM(SM), PP(PP),
150 LangOpts(LangOpts) {}
151
152 // In a normal compile, the preamble traverses the following structure:
153 //
154 // mainfile.cpp
155 // <built-in>
156 // ... macro definitions like __cplusplus ...
157 // <command-line>
158 // ... macro definitions for args like -Dfoo=bar ...
159 // "header1.h"
160 // ... header file contents ...
161 // "header2.h"
162 // ... header file contents ...
163 // ... main file contents ...
164 //
165 // When using a preamble, the "header1" and "header2" subtrees get skipped.
166 // We insert them right after the built-in header, which still appears.
FileChanged(SourceLocation Loc,FileChangeReason Reason,SrcMgr::CharacteristicKind Kind,FileID PrevFID)167 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
168 SrcMgr::CharacteristicKind Kind, FileID PrevFID) override {
169 // It'd be nice if there was a better way to identify built-in headers...
170 if (Reason == FileChangeReason::ExitFile &&
171 SM.getBuffer(PrevFID)->getBufferIdentifier() == "<built-in>")
172 replay();
173 }
174
replay()175 void replay() {
176 for (const auto &Inc : Includes.MainFileIncludes) {
177 const FileEntry *File = nullptr;
178 if (Inc.Resolved != "")
179 File = SM.getFileManager().getFile(Inc.Resolved);
180
181 llvm::StringRef WrittenFilename =
182 llvm::StringRef(Inc.Written).drop_front().drop_back();
183 bool Angled = llvm::StringRef(Inc.Written).startswith("<");
184
185 // Re-lex the #include directive to find its interesting parts.
186 llvm::StringRef Src = SM.getBufferData(SM.getMainFileID());
187 Lexer RawLexer(SM.getLocForStartOfFile(SM.getMainFileID()), LangOpts,
188 Src.begin(), Src.begin() + Inc.HashOffset, Src.end());
189 Token HashTok, IncludeTok, FilenameTok;
190 RawLexer.LexFromRawLexer(HashTok);
191 assert(HashTok.getKind() == tok::hash);
192 RawLexer.setParsingPreprocessorDirective(true);
193 RawLexer.LexFromRawLexer(IncludeTok);
194 IdentifierInfo *II = PP.getIdentifierInfo(IncludeTok.getRawIdentifier());
195 IncludeTok.setIdentifierInfo(II);
196 IncludeTok.setKind(II->getTokenID());
197 RawLexer.LexIncludeFilename(FilenameTok);
198
199 Delegate->InclusionDirective(
200 HashTok.getLocation(), IncludeTok, WrittenFilename, Angled,
201 CharSourceRange::getCharRange(FilenameTok.getLocation(),
202 FilenameTok.getEndLoc()),
203 File, "SearchPath", "RelPath", /*Imported=*/nullptr, Inc.FileKind);
204 if (File)
205 Delegate->FileSkipped(*File, FilenameTok, Inc.FileKind);
206 else {
207 llvm::SmallString<1> UnusedRecovery;
208 Delegate->FileNotFound(WrittenFilename, UnusedRecovery);
209 }
210 }
211 }
212
213 const IncludeStructure &Includes;
214 PPCallbacks *Delegate;
215 const SourceManager &SM;
216 Preprocessor &PP;
217 const LangOptions &LangOpts;
218 };
219
220 } // namespace
221
dumpAST(ParsedAST & AST,llvm::raw_ostream & OS)222 void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) {
223 AST.getASTContext().getTranslationUnitDecl()->dump(OS, true);
224 }
225
226 llvm::Optional<ParsedAST>
build(std::unique_ptr<CompilerInvocation> CI,std::shared_ptr<const PreambleData> Preamble,std::unique_ptr<llvm::MemoryBuffer> Buffer,std::shared_ptr<PCHContainerOperations> PCHs,llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)227 ParsedAST::build(std::unique_ptr<CompilerInvocation> CI,
228 std::shared_ptr<const PreambleData> Preamble,
229 std::unique_ptr<llvm::MemoryBuffer> Buffer,
230 std::shared_ptr<PCHContainerOperations> PCHs,
231 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
232 assert(CI);
233 // Command-line parsing sets DisableFree to true by default, but we don't want
234 // to leak memory in clangd.
235 CI->getFrontendOpts().DisableFree = false;
236 const PrecompiledPreamble *PreamblePCH =
237 Preamble ? &Preamble->Preamble : nullptr;
238
239 StoreDiags ASTDiags;
240 auto Clang =
241 prepareCompilerInstance(std::move(CI), PreamblePCH, std::move(Buffer),
242 std::move(PCHs), std::move(VFS), ASTDiags);
243 if (!Clang)
244 return None;
245
246 auto Action = llvm::make_unique<ClangdFrontendAction>();
247 const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
248 if (!Action->BeginSourceFile(*Clang, MainInput)) {
249 log("BeginSourceFile() failed when building AST for {0}",
250 MainInput.getFile());
251 return None;
252 }
253
254 // Set up ClangTidy. Must happen after BeginSourceFile() so ASTContext exists.
255 // Clang-tidy has some limitiations to ensure reasonable performance:
256 // - checks don't see all preprocessor events in the preamble
257 // - matchers run only over the main-file top-level decls (and can't see
258 // ancestors outside this scope).
259 // In practice almost all checks work well without modifications.
260 std::vector<std::unique_ptr<tidy::ClangTidyCheck>> CTChecks;
261 ast_matchers::MatchFinder CTFinder;
262 llvm::Optional<tidy::ClangTidyContext> CTContext;
263 {
264 trace::Span Tracer("ClangTidyInit");
265 tidy::ClangTidyCheckFactories CTFactories;
266 for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
267 E.instantiate()->addCheckFactories(CTFactories);
268 auto CTOpts = tidy::ClangTidyOptions::getDefaults();
269 // FIXME: this needs to be configurable, and we need to support .clang-tidy
270 // files and other options providers.
271 // These checks exercise the matcher- and preprocessor-based hooks.
272 CTOpts.Checks = "bugprone-sizeof-expression,"
273 "bugprone-macro-repeated-side-effects,"
274 "modernize-deprecated-headers";
275 CTContext.emplace(llvm::make_unique<tidy::DefaultOptionsProvider>(
276 tidy::ClangTidyGlobalOptions(), CTOpts));
277 CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
278 CTContext->setASTContext(&Clang->getASTContext());
279 CTContext->setCurrentFile(MainInput.getFile());
280 CTFactories.createChecks(CTContext.getPointer(), CTChecks);
281 for (const auto &Check : CTChecks) {
282 // FIXME: the PP callbacks skip the entire preamble.
283 // Checks that want to see #includes in the main file do not see them.
284 Check->registerPPCallbacks(*Clang);
285 Check->registerMatchers(&CTFinder);
286 }
287 }
288
289 // Copy over the includes from the preamble, then combine with the
290 // non-preamble includes below.
291 auto Includes = Preamble ? Preamble->Includes : IncludeStructure{};
292 // Replay the preamble includes so that clang-tidy checks can see them.
293 if (Preamble)
294 ReplayPreamble::attach(Includes, *Clang);
295 // Important: collectIncludeStructure is registered *after* ReplayPreamble!
296 // Otherwise we would collect the replayed includes again...
297 // (We can't *just* use the replayed includes, they don't have Resolved path).
298 Clang->getPreprocessor().addPPCallbacks(
299 collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
300
301 if (!Action->Execute())
302 log("Execute() failed when building AST for {0}", MainInput.getFile());
303
304 std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
305 // AST traversals should exclude the preamble, to avoid performance cliffs.
306 Clang->getASTContext().setTraversalScope(ParsedDecls);
307 {
308 // Run the AST-dependent part of the clang-tidy checks.
309 // (The preprocessor part ran already, via PPCallbacks).
310 trace::Span Tracer("ClangTidyMatch");
311 CTFinder.matchAST(Clang->getASTContext());
312 }
313
314 // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
315 // has a longer lifetime.
316 Clang->getDiagnostics().setClient(new IgnoreDiagnostics);
317 // CompilerInstance won't run this callback, do it directly.
318 ASTDiags.EndSourceFile();
319 // XXX: This is messy: clang-tidy checks flush some diagnostics at EOF.
320 // However Action->EndSourceFile() would destroy the ASTContext!
321 // So just inform the preprocessor of EOF, while keeping everything alive.
322 Clang->getPreprocessor().EndSourceFile();
323
324 std::vector<Diag> Diags = ASTDiags.take();
325 // Add diagnostics from the preamble, if any.
326 if (Preamble)
327 Diags.insert(Diags.begin(), Preamble->Diags.begin(), Preamble->Diags.end());
328 return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
329 std::move(ParsedDecls), std::move(Diags),
330 std::move(Includes));
331 }
332
333 ParsedAST::ParsedAST(ParsedAST &&Other) = default;
334
335 ParsedAST &ParsedAST::operator=(ParsedAST &&Other) = default;
336
~ParsedAST()337 ParsedAST::~ParsedAST() {
338 if (Action) {
339 // We already notified the PP of end-of-file earlier, so detach it first.
340 // We must keep it alive until after EndSourceFile(), Sema relies on this.
341 auto PP = Clang->getPreprocessorPtr(); // Keep PP alive for now.
342 Clang->setPreprocessor(nullptr); // Detach so we don't send EOF again.
343 Action->EndSourceFile(); // Destroy ASTContext and Sema.
344 // Now Sema is gone, it's safe for PP to go out of scope.
345 }
346 }
347
getASTContext()348 ASTContext &ParsedAST::getASTContext() { return Clang->getASTContext(); }
349
getASTContext() const350 const ASTContext &ParsedAST::getASTContext() const {
351 return Clang->getASTContext();
352 }
353
getPreprocessor()354 Preprocessor &ParsedAST::getPreprocessor() { return Clang->getPreprocessor(); }
355
getPreprocessorPtr()356 std::shared_ptr<Preprocessor> ParsedAST::getPreprocessorPtr() {
357 return Clang->getPreprocessorPtr();
358 }
359
getPreprocessor() const360 const Preprocessor &ParsedAST::getPreprocessor() const {
361 return Clang->getPreprocessor();
362 }
363
getLocalTopLevelDecls()364 llvm::ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
365 return LocalTopLevelDecls;
366 }
367
getDiagnostics() const368 const std::vector<Diag> &ParsedAST::getDiagnostics() const { return Diags; }
369
getUsedBytes() const370 std::size_t ParsedAST::getUsedBytes() const {
371 auto &AST = getASTContext();
372 // FIXME(ibiryukov): we do not account for the dynamically allocated part of
373 // Message and Fixes inside each diagnostic.
374 std::size_t Total =
375 clangd::getUsedBytes(LocalTopLevelDecls) + clangd::getUsedBytes(Diags);
376
377 // FIXME: the rest of the function is almost a direct copy-paste from
378 // libclang's clang_getCXTUResourceUsage. We could share the implementation.
379
380 // Sum up variaous allocators inside the ast context and the preprocessor.
381 Total += AST.getASTAllocatedMemory();
382 Total += AST.getSideTableAllocatedMemory();
383 Total += AST.Idents.getAllocator().getTotalMemory();
384 Total += AST.Selectors.getTotalMemory();
385
386 Total += AST.getSourceManager().getContentCacheSize();
387 Total += AST.getSourceManager().getDataStructureSizes();
388 Total += AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
389
390 if (ExternalASTSource *Ext = AST.getExternalSource())
391 Total += Ext->getMemoryBufferSizes().malloc_bytes;
392
393 const Preprocessor &PP = getPreprocessor();
394 Total += PP.getTotalMemory();
395 if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
396 Total += PRec->getTotalMemory();
397 Total += PP.getHeaderSearchInfo().getTotalMemory();
398
399 return Total;
400 }
401
getIncludeStructure() const402 const IncludeStructure &ParsedAST::getIncludeStructure() const {
403 return Includes;
404 }
405
PreambleData(PrecompiledPreamble Preamble,std::vector<Diag> Diags,IncludeStructure Includes,std::unique_ptr<PreambleFileStatusCache> StatCache)406 PreambleData::PreambleData(PrecompiledPreamble Preamble,
407 std::vector<Diag> Diags, IncludeStructure Includes,
408 std::unique_ptr<PreambleFileStatusCache> StatCache)
409 : Preamble(std::move(Preamble)), Diags(std::move(Diags)),
410 Includes(std::move(Includes)), StatCache(std::move(StatCache)) {}
411
ParsedAST(std::shared_ptr<const PreambleData> Preamble,std::unique_ptr<CompilerInstance> Clang,std::unique_ptr<FrontendAction> Action,std::vector<Decl * > LocalTopLevelDecls,std::vector<Diag> Diags,IncludeStructure Includes)412 ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
413 std::unique_ptr<CompilerInstance> Clang,
414 std::unique_ptr<FrontendAction> Action,
415 std::vector<Decl *> LocalTopLevelDecls,
416 std::vector<Diag> Diags, IncludeStructure Includes)
417 : Preamble(std::move(Preamble)), Clang(std::move(Clang)),
418 Action(std::move(Action)), Diags(std::move(Diags)),
419 LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
420 Includes(std::move(Includes)) {
421 assert(this->Clang);
422 assert(this->Action);
423 }
424
425 std::unique_ptr<CompilerInvocation>
buildCompilerInvocation(const ParseInputs & Inputs)426 buildCompilerInvocation(const ParseInputs &Inputs) {
427 std::vector<const char *> ArgStrs;
428 for (const auto &S : Inputs.CompileCommand.CommandLine)
429 ArgStrs.push_back(S.c_str());
430
431 if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
432 log("Couldn't set working directory when creating compiler invocation.");
433 // We proceed anyway, our lit-tests rely on results for non-existing working
434 // dirs.
435 }
436
437 // FIXME(ibiryukov): store diagnostics from CommandLine when we start
438 // reporting them.
439 IgnoreDiagnostics IgnoreDiagnostics;
440 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
441 CompilerInstance::createDiagnostics(new DiagnosticOptions,
442 &IgnoreDiagnostics, false);
443 std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
444 ArgStrs, CommandLineDiagsEngine, Inputs.FS);
445 if (!CI)
446 return nullptr;
447 // createInvocationFromCommandLine sets DisableFree.
448 CI->getFrontendOpts().DisableFree = false;
449 CI->getLangOpts()->CommentOpts.ParseAllComments = true;
450 return CI;
451 }
452
453 std::shared_ptr<const PreambleData>
buildPreamble(PathRef FileName,CompilerInvocation & CI,std::shared_ptr<const PreambleData> OldPreamble,const tooling::CompileCommand & OldCompileCommand,const ParseInputs & Inputs,std::shared_ptr<PCHContainerOperations> PCHs,bool StoreInMemory,PreambleParsedCallback PreambleCallback)454 buildPreamble(PathRef FileName, CompilerInvocation &CI,
455 std::shared_ptr<const PreambleData> OldPreamble,
456 const tooling::CompileCommand &OldCompileCommand,
457 const ParseInputs &Inputs,
458 std::shared_ptr<PCHContainerOperations> PCHs, bool StoreInMemory,
459 PreambleParsedCallback PreambleCallback) {
460 // Note that we don't need to copy the input contents, preamble can live
461 // without those.
462 auto ContentsBuffer = llvm::MemoryBuffer::getMemBuffer(Inputs.Contents);
463 auto Bounds =
464 ComputePreambleBounds(*CI.getLangOpts(), ContentsBuffer.get(), 0);
465
466 if (OldPreamble &&
467 compileCommandsAreEqual(Inputs.CompileCommand, OldCompileCommand) &&
468 OldPreamble->Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
469 Inputs.FS.get())) {
470 vlog("Reusing preamble for file {0}", llvm::Twine(FileName));
471 return OldPreamble;
472 }
473 vlog("Preamble for file {0} cannot be reused. Attempting to rebuild it.",
474 FileName);
475
476 trace::Span Tracer("BuildPreamble");
477 SPAN_ATTACH(Tracer, "File", FileName);
478 StoreDiags PreambleDiagnostics;
479 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
480 CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
481 &PreambleDiagnostics, false);
482
483 // Skip function bodies when building the preamble to speed up building
484 // the preamble and make it smaller.
485 assert(!CI.getFrontendOpts().SkipFunctionBodies);
486 CI.getFrontendOpts().SkipFunctionBodies = true;
487 // We don't want to write comment locations into PCH. They are racy and slow
488 // to read back. We rely on dynamic index for the comments instead.
489 CI.getPreprocessorOpts().WriteCommentListToPCH = false;
490
491 CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
492 if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
493 log("Couldn't set working directory when building the preamble.");
494 // We proceed anyway, our lit-tests rely on results for non-existing working
495 // dirs.
496 }
497
498 llvm::SmallString<32> AbsFileName(FileName);
499 Inputs.FS->makeAbsolute(AbsFileName);
500 auto StatCache = llvm::make_unique<PreambleFileStatusCache>(AbsFileName);
501 auto BuiltPreamble = PrecompiledPreamble::Build(
502 CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
503 StatCache->getProducingFS(Inputs.FS), PCHs, StoreInMemory,
504 SerializedDeclsCollector);
505
506 // When building the AST for the main file, we do want the function
507 // bodies.
508 CI.getFrontendOpts().SkipFunctionBodies = false;
509
510 if (BuiltPreamble) {
511 vlog("Built preamble of size {0} for file {1}", BuiltPreamble->getSize(),
512 FileName);
513 return std::make_shared<PreambleData>(
514 std::move(*BuiltPreamble), PreambleDiagnostics.take(),
515 SerializedDeclsCollector.takeIncludes(), std::move(StatCache));
516 } else {
517 elog("Could not build a preamble for file {0}", FileName);
518 return nullptr;
519 }
520 }
521
522 llvm::Optional<ParsedAST>
buildAST(PathRef FileName,std::unique_ptr<CompilerInvocation> Invocation,const ParseInputs & Inputs,std::shared_ptr<const PreambleData> Preamble,std::shared_ptr<PCHContainerOperations> PCHs)523 buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
524 const ParseInputs &Inputs,
525 std::shared_ptr<const PreambleData> Preamble,
526 std::shared_ptr<PCHContainerOperations> PCHs) {
527 trace::Span Tracer("BuildAST");
528 SPAN_ATTACH(Tracer, "File", FileName);
529
530 auto VFS = Inputs.FS;
531 if (Preamble && Preamble->StatCache)
532 VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
533 if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
534 log("Couldn't set working directory when building the preamble.");
535 // We proceed anyway, our lit-tests rely on results for non-existing working
536 // dirs.
537 }
538
539 return ParsedAST::build(llvm::make_unique<CompilerInvocation>(*Invocation),
540 Preamble,
541 llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents),
542 PCHs, std::move(VFS));
543 }
544
getBeginningOfIdentifier(ParsedAST & Unit,const Position & Pos,const FileID FID)545 SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
546 const FileID FID) {
547 const ASTContext &AST = Unit.getASTContext();
548 const SourceManager &SourceMgr = AST.getSourceManager();
549 auto Offset = positionToOffset(SourceMgr.getBufferData(FID), Pos);
550 if (!Offset) {
551 log("getBeginningOfIdentifier: {0}", Offset.takeError());
552 return SourceLocation();
553 }
554
555 // GetBeginningOfToken(pos) is almost what we want, but does the wrong thing
556 // if the cursor is at the end of the identifier.
557 // Instead, we lex at GetBeginningOfToken(pos - 1). The cases are:
558 // 1) at the beginning of an identifier, we'll be looking at something
559 // that isn't an identifier.
560 // 2) at the middle or end of an identifier, we get the identifier.
561 // 3) anywhere outside an identifier, we'll get some non-identifier thing.
562 // We can't actually distinguish cases 1 and 3, but returning the original
563 // location is correct for both!
564 SourceLocation InputLoc = SourceMgr.getComposedLoc(FID, *Offset);
565 if (*Offset == 0) // Case 1 or 3.
566 return SourceMgr.getMacroArgExpandedLocation(InputLoc);
567 SourceLocation Before = SourceMgr.getComposedLoc(FID, *Offset - 1);
568
569 Before = Lexer::GetBeginningOfToken(Before, SourceMgr, AST.getLangOpts());
570 Token Tok;
571 if (Before.isValid() &&
572 !Lexer::getRawToken(Before, Tok, SourceMgr, AST.getLangOpts(), false) &&
573 Tok.is(tok::raw_identifier))
574 return SourceMgr.getMacroArgExpandedLocation(Before); // Case 2.
575 return SourceMgr.getMacroArgExpandedLocation(InputLoc); // Case 1 or 3.
576 }
577
578 } // namespace clangd
579 namespace tidy {
580 // Force the linker to link in Clang-tidy modules.
581 #define LINK_TIDY_MODULE(X) \
582 extern volatile int X##ModuleAnchorSource; \
583 static int LLVM_ATTRIBUTE_UNUSED X##ModuleAnchorDestination = \
584 X##ModuleAnchorSource
585 LINK_TIDY_MODULE(CERT);
586 LINK_TIDY_MODULE(Abseil);
587 LINK_TIDY_MODULE(Boost);
588 LINK_TIDY_MODULE(Bugprone);
589 LINK_TIDY_MODULE(LLVM);
590 LINK_TIDY_MODULE(CppCoreGuidelines);
591 LINK_TIDY_MODULE(Fuchsia);
592 LINK_TIDY_MODULE(Google);
593 LINK_TIDY_MODULE(Android);
594 LINK_TIDY_MODULE(Misc);
595 LINK_TIDY_MODULE(Modernize);
596 LINK_TIDY_MODULE(Performance);
597 LINK_TIDY_MODULE(Portability);
598 LINK_TIDY_MODULE(Readability);
599 LINK_TIDY_MODULE(ObjC);
600 LINK_TIDY_MODULE(HICPP);
601 LINK_TIDY_MODULE(Zircon);
602 #undef LINK_TIDY_MODULE
603 } // namespace tidy
604 } // namespace clang
605