[clang-tools-extra] r370862 - [clangd] Rename ClangdUnit.h -> ParsedAST.h. NFC
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 4 02:46:07 PDT 2019
Author: sammccall
Date: Wed Sep 4 02:46:06 2019
New Revision: 370862
URL: http://llvm.org/viewvc/llvm-project?rev=370862&view=rev
Log:
[clangd] Rename ClangdUnit.h -> ParsedAST.h. NFC
This much better reflects what is (now) in this header.
Maybe a rename to ParsedTU would be an improvement, but that's a much
more invasive change and life is too short.
ClangdUnit is dead, long live ClangdUnitTests!
Added:
clang-tools-extra/trunk/clangd/ParsedAST.cpp
clang-tools-extra/trunk/clangd/ParsedAST.h
clang-tools-extra/trunk/clangd/unittests/ParsedASTTests.cpp
Removed:
clang-tools-extra/trunk/clangd/ClangdUnit.cpp
clang-tools-extra/trunk/clangd/ClangdUnit.h
clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
Modified:
clang-tools-extra/trunk/clangd/CMakeLists.txt
clang-tools-extra/trunk/clangd/ClangdServer.cpp
clang-tools-extra/trunk/clangd/FindSymbols.cpp
clang-tools-extra/trunk/clangd/Preamble.cpp
clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
clang-tools-extra/trunk/clangd/SemanticHighlighting.h
clang-tools-extra/trunk/clangd/TUScheduler.cpp
clang-tools-extra/trunk/clangd/XRefs.cpp
clang-tools-extra/trunk/clangd/XRefs.h
clang-tools-extra/trunk/clangd/index/Background.cpp
clang-tools-extra/trunk/clangd/index/BackgroundRebuild.cpp
clang-tools-extra/trunk/clangd/index/FileIndex.cpp
clang-tools-extra/trunk/clangd/refactor/Rename.cpp
clang-tools-extra/trunk/clangd/refactor/Tweak.h
clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractFunction.cpp
clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
clang-tools-extra/trunk/clangd/refactor/tweaks/RawStringLiteral.cpp
clang-tools-extra/trunk/clangd/refactor/tweaks/SwapIfBranches.cpp
clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt
clang-tools-extra/trunk/clangd/unittests/DiagnosticsTests.cpp
clang-tools-extra/trunk/clangd/unittests/ExpectedTypeTest.cpp
clang-tools-extra/trunk/clangd/unittests/FileIndexTests.cpp
clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp
clang-tools-extra/trunk/clangd/unittests/SymbolInfoTests.cpp
clang-tools-extra/trunk/clangd/unittests/TUSchedulerTests.cpp
clang-tools-extra/trunk/clangd/unittests/TestTU.h
clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp
clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp
Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Wed Sep 4 02:46:06 2019
@@ -39,7 +39,6 @@ add_clang_library(clangDaemon
Cancellation.cpp
ClangdLSPServer.cpp
ClangdServer.cpp
- ClangdUnit.cpp
CodeComplete.cpp
CodeCompletionStrings.cpp
Compiler.cpp
@@ -62,6 +61,7 @@ add_clang_library(clangDaemon
Logger.cpp
Protocol.cpp
Quality.cpp
+ ParsedAST.cpp
Preamble.cpp
RIFF.cpp
Selection.cpp
Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Wed Sep 4 02:46:06 2019
@@ -7,12 +7,12 @@
//===-------------------------------------------------------------------===//
#include "ClangdServer.h"
-#include "ClangdUnit.h"
#include "CodeComplete.h"
#include "FindSymbols.h"
#include "Format.h"
#include "FormattedString.h"
#include "Headers.h"
+#include "ParsedAST.h"
#include "Preamble.h"
#include "Protocol.h"
#include "SemanticHighlighting.h"
Removed: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=370861&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp (removed)
@@ -1,574 +0,0 @@
-//===--- ClangdUnit.cpp ------------------------------------------*- C++-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangdUnit.h"
-#include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
-#include "../clang-tidy/ClangTidyModuleRegistry.h"
-#include "AST.h"
-#include "Compiler.h"
-#include "Diagnostics.h"
-#include "Headers.h"
-#include "IncludeFixer.h"
-#include "Logger.h"
-#include "SourceCode.h"
-#include "Trace.h"
-#include "index/CanonicalIncludes.h"
-#include "index/Index.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TokenKinds.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Index/IndexDataConsumer.h"
-#include "clang/Index/IndexingAction.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/MacroInfo.h"
-#include "clang/Lex/PPCallbacks.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Sema/Sema.h"
-#include "clang/Serialization/ASTWriter.h"
-#include "clang/Serialization/PCHContainerOperations.h"
-#include "clang/Tooling/CompilationDatabase.h"
-#include "clang/Tooling/Syntax/Tokens.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <memory>
-
-namespace clang {
-namespace clangd {
-namespace {
-
-template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
- return Vec.capacity() * sizeof(T);
-}
-
-class DeclTrackingASTConsumer : public ASTConsumer {
-public:
- DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
- : TopLevelDecls(TopLevelDecls) {}
-
- bool HandleTopLevelDecl(DeclGroupRef DG) override {
- for (Decl *D : DG) {
- auto &SM = D->getASTContext().getSourceManager();
- if (!isInsideMainFile(D->getLocation(), SM))
- continue;
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- if (isImplicitTemplateInstantiation(ND))
- continue;
-
- // ObjCMethodDecl are not actually top-level decls.
- if (isa<ObjCMethodDecl>(D))
- continue;
-
- TopLevelDecls.push_back(D);
- }
- return true;
- }
-
-private:
- std::vector<Decl *> &TopLevelDecls;
-};
-
-class ClangdFrontendAction : public SyntaxOnlyAction {
-public:
- std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
-
-protected:
- std::unique_ptr<ASTConsumer>
- CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
- return std::make_unique<DeclTrackingASTConsumer>(/*ref*/ TopLevelDecls);
- }
-
-private:
- std::vector<Decl *> TopLevelDecls;
-};
-
-// This collects macro expansions in the main file.
-// (Contrast with CollectMainFileMacros in Preamble.cpp, which collects macro
-// *definitions* in the preamble region of the main file).
-class CollectMainFileMacroExpansions : public PPCallbacks {
- const SourceManager &SM;
- std::vector<SourceLocation> &MainFileMacroLocs;
-
-public:
- CollectMainFileMacroExpansions(const SourceManager &SM,
- std::vector<SourceLocation> &MainFileMacroLocs)
- : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
-
- virtual void MacroExpands(const Token &MacroNameTok,
- const MacroDefinition &MD, SourceRange Range,
- const MacroArgs *Args) {
- SourceLocation L = MacroNameTok.getLocation();
- if (!L.isMacroID() && isInsideMainFile(L, SM))
- MainFileMacroLocs.push_back(L);
- }
-};
-
-// When using a preamble, only preprocessor events outside its bounds are seen.
-// This is almost what we want: replaying transitive preprocessing wastes time.
-// However this confuses clang-tidy checks: they don't see any #includes!
-// So we replay the *non-transitive* #includes that appear in the main-file.
-// It would be nice to replay other events (macro definitions, ifdefs etc) but
-// this addresses the most common cases fairly cheaply.
-class ReplayPreamble : private PPCallbacks {
-public:
- // Attach preprocessor hooks such that preamble events will be injected at
- // the appropriate time.
- // Events will be delivered to the *currently registered* PP callbacks.
- static void attach(const IncludeStructure &Includes,
- CompilerInstance &Clang) {
- auto &PP = Clang.getPreprocessor();
- auto *ExistingCallbacks = PP.getPPCallbacks();
- // No need to replay events if nobody is listening.
- if (!ExistingCallbacks)
- return;
- PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(
- new ReplayPreamble(Includes, ExistingCallbacks,
- Clang.getSourceManager(), PP, Clang.getLangOpts())));
- // We're relying on the fact that addPPCallbacks keeps the old PPCallbacks
- // around, creating a chaining wrapper. Guard against other implementations.
- assert(PP.getPPCallbacks() != ExistingCallbacks &&
- "Expected chaining implementation");
- }
-
-private:
- ReplayPreamble(const IncludeStructure &Includes, PPCallbacks *Delegate,
- const SourceManager &SM, Preprocessor &PP,
- const LangOptions &LangOpts)
- : Includes(Includes), Delegate(Delegate), SM(SM), PP(PP),
- LangOpts(LangOpts) {}
-
- // In a normal compile, the preamble traverses the following structure:
- //
- // mainfile.cpp
- // <built-in>
- // ... macro definitions like __cplusplus ...
- // <command-line>
- // ... macro definitions for args like -Dfoo=bar ...
- // "header1.h"
- // ... header file contents ...
- // "header2.h"
- // ... header file contents ...
- // ... main file contents ...
- //
- // When using a preamble, the "header1" and "header2" subtrees get skipped.
- // We insert them right after the built-in header, which still appears.
- void FileChanged(SourceLocation Loc, FileChangeReason Reason,
- SrcMgr::CharacteristicKind Kind, FileID PrevFID) override {
- // It'd be nice if there was a better way to identify built-in headers...
- if (Reason == FileChangeReason::ExitFile &&
- SM.getBuffer(PrevFID)->getBufferIdentifier() == "<built-in>")
- replay();
- }
-
- void replay() {
- for (const auto &Inc : Includes.MainFileIncludes) {
- const FileEntry *File = nullptr;
- if (Inc.Resolved != "")
- if (auto FE = SM.getFileManager().getFile(Inc.Resolved))
- File = *FE;
-
- llvm::StringRef WrittenFilename =
- llvm::StringRef(Inc.Written).drop_front().drop_back();
- bool Angled = llvm::StringRef(Inc.Written).startswith("<");
-
- // Re-lex the #include directive to find its interesting parts.
- llvm::StringRef Src = SM.getBufferData(SM.getMainFileID());
- Lexer RawLexer(SM.getLocForStartOfFile(SM.getMainFileID()), LangOpts,
- Src.begin(), Src.begin() + Inc.HashOffset, Src.end());
- Token HashTok, IncludeTok, FilenameTok;
- RawLexer.LexFromRawLexer(HashTok);
- assert(HashTok.getKind() == tok::hash);
- RawLexer.setParsingPreprocessorDirective(true);
- RawLexer.LexFromRawLexer(IncludeTok);
- IdentifierInfo *II = PP.getIdentifierInfo(IncludeTok.getRawIdentifier());
- IncludeTok.setIdentifierInfo(II);
- IncludeTok.setKind(II->getTokenID());
- RawLexer.LexIncludeFilename(FilenameTok);
-
- Delegate->InclusionDirective(
- HashTok.getLocation(), IncludeTok, WrittenFilename, Angled,
- CharSourceRange::getCharRange(FilenameTok.getLocation(),
- FilenameTok.getEndLoc()),
- File, "SearchPath", "RelPath", /*Imported=*/nullptr, Inc.FileKind);
- if (File)
- // FIXME: Use correctly named FileEntryRef.
- Delegate->FileSkipped(FileEntryRef(File->getName(), *File), FilenameTok,
- Inc.FileKind);
- else {
- llvm::SmallString<1> UnusedRecovery;
- Delegate->FileNotFound(WrittenFilename, UnusedRecovery);
- }
- }
- }
-
- const IncludeStructure &Includes;
- PPCallbacks *Delegate;
- const SourceManager &SM;
- Preprocessor &PP;
- const LangOptions &LangOpts;
-};
-
-} // namespace
-
-void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) {
- AST.getASTContext().getTranslationUnitDecl()->dump(OS, true);
-}
-
-llvm::Optional<ParsedAST>
-ParsedAST::build(std::unique_ptr<clang::CompilerInvocation> CI,
- llvm::ArrayRef<Diag> CompilerInvocationDiags,
- std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- const SymbolIndex *Index, const ParseOptions &Opts) {
- assert(CI);
- // Command-line parsing sets DisableFree to true by default, but we don't want
- // to leak memory in clangd.
- CI->getFrontendOpts().DisableFree = false;
- const PrecompiledPreamble *PreamblePCH =
- Preamble ? &Preamble->Preamble : nullptr;
-
- StoreDiags ASTDiags;
- std::string Content = Buffer->getBuffer();
- std::string Filename = Buffer->getBufferIdentifier(); // Absolute.
-
- auto Clang = prepareCompilerInstance(std::move(CI), PreamblePCH,
- std::move(Buffer), VFS, ASTDiags);
- if (!Clang)
- return None;
-
- auto Action = std::make_unique<ClangdFrontendAction>();
- const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
- if (!Action->BeginSourceFile(*Clang, MainInput)) {
- log("BeginSourceFile() failed when building AST for {0}",
- MainInput.getFile());
- return None;
- }
-
- // Set up ClangTidy. Must happen after BeginSourceFile() so ASTContext exists.
- // Clang-tidy has some limitiations to ensure reasonable performance:
- // - checks don't see all preprocessor events in the preamble
- // - matchers run only over the main-file top-level decls (and can't see
- // ancestors outside this scope).
- // In practice almost all checks work well without modifications.
- std::vector<std::unique_ptr<tidy::ClangTidyCheck>> CTChecks;
- ast_matchers::MatchFinder CTFinder;
- llvm::Optional<tidy::ClangTidyContext> CTContext;
- {
- trace::Span Tracer("ClangTidyInit");
- dlog("ClangTidy configuration for file {0}: {1}", Filename,
- tidy::configurationAsText(Opts.ClangTidyOpts));
- tidy::ClangTidyCheckFactories CTFactories;
- for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
- E.instantiate()->addCheckFactories(CTFactories);
- CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>(
- tidy::ClangTidyGlobalOptions(), Opts.ClangTidyOpts));
- CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
- CTContext->setASTContext(&Clang->getASTContext());
- CTContext->setCurrentFile(Filename);
- CTFactories.createChecks(CTContext.getPointer(), CTChecks);
- ASTDiags.setLevelAdjuster([&CTContext](DiagnosticsEngine::Level DiagLevel,
- const clang::Diagnostic &Info) {
- if (CTContext) {
- std::string CheckName = CTContext->getCheckName(Info.getID());
- bool IsClangTidyDiag = !CheckName.empty();
- if (IsClangTidyDiag) {
- // Check for warning-as-error.
- // We deliberately let this take precedence over suppression comments
- // to match clang-tidy's behaviour.
- if (DiagLevel == DiagnosticsEngine::Warning &&
- CTContext->treatAsError(CheckName)) {
- return DiagnosticsEngine::Error;
- }
-
- // Check for suppression comment. Skip the check for diagnostics not
- // in the main file, because we don't want that function to query the
- // source buffer for preamble files. For the same reason, we ask
- // ShouldSuppressDiagnostic not to follow macro expansions, since
- // those might take us into a preamble file as well.
- bool IsInsideMainFile =
- Info.hasSourceManager() &&
- isInsideMainFile(Info.getLocation(), Info.getSourceManager());
- if (IsInsideMainFile && tidy::ShouldSuppressDiagnostic(
- DiagLevel, Info, *CTContext,
- /* CheckMacroExpansion = */ false)) {
- return DiagnosticsEngine::Ignored;
- }
- }
- }
- return DiagLevel;
- });
- Preprocessor *PP = &Clang->getPreprocessor();
- for (const auto &Check : CTChecks) {
- // FIXME: the PP callbacks skip the entire preamble.
- // Checks that want to see #includes in the main file do not see them.
- Check->registerPPCallbacks(Clang->getSourceManager(), PP, PP);
- Check->registerMatchers(&CTFinder);
- }
- }
-
- // Add IncludeFixer which can recover diagnostics caused by missing includes
- // (e.g. incomplete type) and attach include insertion fixes to diagnostics.
- llvm::Optional<IncludeFixer> FixIncludes;
- auto BuildDir = VFS->getCurrentWorkingDirectory();
- if (Opts.SuggestMissingIncludes && Index && !BuildDir.getError()) {
- auto Style = getFormatStyleForFile(Filename, Content, VFS.get());
- auto Inserter = std::make_shared<IncludeInserter>(
- Filename, Content, Style, BuildDir.get(),
- &Clang->getPreprocessor().getHeaderSearchInfo());
- if (Preamble) {
- for (const auto &Inc : Preamble->Includes.MainFileIncludes)
- Inserter->addExisting(Inc);
- }
- FixIncludes.emplace(Filename, Inserter, *Index,
- /*IndexRequestLimit=*/5);
- ASTDiags.contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
- const clang::Diagnostic &Info) {
- return FixIncludes->fix(DiagLevl, Info);
- });
- Clang->setExternalSemaSource(FixIncludes->unresolvedNameRecorder());
- }
-
- // Copy over the includes from the preamble, then combine with the
- // non-preamble includes below.
- auto Includes = Preamble ? Preamble->Includes : IncludeStructure{};
- // Replay the preamble includes so that clang-tidy checks can see them.
- if (Preamble)
- ReplayPreamble::attach(Includes, *Clang);
- // Important: collectIncludeStructure is registered *after* ReplayPreamble!
- // Otherwise we would collect the replayed includes again...
- // (We can't *just* use the replayed includes, they don't have Resolved path).
- Clang->getPreprocessor().addPPCallbacks(
- collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
- // Collect the macro expansions in the main file.
- std::vector<SourceLocation> MainFileMacroExpLocs;
- Clang->getPreprocessor().addPPCallbacks(
- std::make_unique<CollectMainFileMacroExpansions>(
- Clang->getSourceManager(), MainFileMacroExpLocs));
-
- // Copy over the includes from the preamble, then combine with the
- // non-preamble includes below.
- CanonicalIncludes CanonIncludes;
- if (Preamble)
- CanonIncludes = Preamble->CanonIncludes;
- else
- addSystemHeadersMapping(&CanonIncludes, Clang->getLangOpts());
- std::unique_ptr<CommentHandler> IWYUHandler =
- collectIWYUHeaderMaps(&CanonIncludes);
- Clang->getPreprocessor().addCommentHandler(IWYUHandler.get());
-
- // Collect tokens of the main file.
- syntax::TokenCollector CollectTokens(Clang->getPreprocessor());
-
- if (llvm::Error Err = Action->Execute())
- log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
- toString(std::move(Err)));
-
- // We have to consume the tokens before running clang-tidy to avoid collecting
- // tokens from running the preprocessor inside the checks (only
- // modernize-use-trailing-return-type does that today).
- syntax::TokenBuffer Tokens = std::move(CollectTokens).consume();
- std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
- // AST traversals should exclude the preamble, to avoid performance cliffs.
- Clang->getASTContext().setTraversalScope(ParsedDecls);
- {
- // Run the AST-dependent part of the clang-tidy checks.
- // (The preprocessor part ran already, via PPCallbacks).
- trace::Span Tracer("ClangTidyMatch");
- CTFinder.matchAST(Clang->getASTContext());
- }
-
- // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
- // has a longer lifetime.
- Clang->getDiagnostics().setClient(new IgnoreDiagnostics);
- // CompilerInstance won't run this callback, do it directly.
- ASTDiags.EndSourceFile();
- // XXX: This is messy: clang-tidy checks flush some diagnostics at EOF.
- // However Action->EndSourceFile() would destroy the ASTContext!
- // So just inform the preprocessor of EOF, while keeping everything alive.
- Clang->getPreprocessor().EndSourceFile();
-
- std::vector<Diag> Diags = CompilerInvocationDiags;
- // Add diagnostics from the preamble, if any.
- if (Preamble)
- Diags.insert(Diags.end(), Preamble->Diags.begin(), Preamble->Diags.end());
- // Finally, add diagnostics coming from the AST.
- {
- std::vector<Diag> D = ASTDiags.take(CTContext.getPointer());
- Diags.insert(Diags.end(), D.begin(), D.end());
- }
- return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
- std::move(Tokens), std::move(MainFileMacroExpLocs),
- std::move(ParsedDecls), std::move(Diags),
- std::move(Includes), std::move(CanonIncludes));
-}
-
-ParsedAST::ParsedAST(ParsedAST &&Other) = default;
-
-ParsedAST &ParsedAST::operator=(ParsedAST &&Other) = default;
-
-ParsedAST::~ParsedAST() {
- if (Action) {
- // We already notified the PP of end-of-file earlier, so detach it first.
- // We must keep it alive until after EndSourceFile(), Sema relies on this.
- auto PP = Clang->getPreprocessorPtr(); // Keep PP alive for now.
- Clang->setPreprocessor(nullptr); // Detach so we don't send EOF again.
- Action->EndSourceFile(); // Destroy ASTContext and Sema.
- // Now Sema is gone, it's safe for PP to go out of scope.
- }
-}
-
-ASTContext &ParsedAST::getASTContext() { return Clang->getASTContext(); }
-
-const ASTContext &ParsedAST::getASTContext() const {
- return Clang->getASTContext();
-}
-
-Preprocessor &ParsedAST::getPreprocessor() { return Clang->getPreprocessor(); }
-
-std::shared_ptr<Preprocessor> ParsedAST::getPreprocessorPtr() {
- return Clang->getPreprocessorPtr();
-}
-
-const Preprocessor &ParsedAST::getPreprocessor() const {
- return Clang->getPreprocessor();
-}
-
-llvm::ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
- return LocalTopLevelDecls;
-}
-
-llvm::ArrayRef<SourceLocation> ParsedAST::getMainFileExpansions() const {
- return MainFileMacroExpLocs;
-}
-
-const std::vector<Diag> &ParsedAST::getDiagnostics() const { return Diags; }
-
-std::size_t ParsedAST::getUsedBytes() const {
- auto &AST = getASTContext();
- // FIXME(ibiryukov): we do not account for the dynamically allocated part of
- // Message and Fixes inside each diagnostic.
- std::size_t Total =
- clangd::getUsedBytes(LocalTopLevelDecls) + clangd::getUsedBytes(Diags);
-
- // FIXME: the rest of the function is almost a direct copy-paste from
- // libclang's clang_getCXTUResourceUsage. We could share the implementation.
-
- // Sum up variaous allocators inside the ast context and the preprocessor.
- Total += AST.getASTAllocatedMemory();
- Total += AST.getSideTableAllocatedMemory();
- Total += AST.Idents.getAllocator().getTotalMemory();
- Total += AST.Selectors.getTotalMemory();
-
- Total += AST.getSourceManager().getContentCacheSize();
- Total += AST.getSourceManager().getDataStructureSizes();
- Total += AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
-
- if (ExternalASTSource *Ext = AST.getExternalSource())
- Total += Ext->getMemoryBufferSizes().malloc_bytes;
-
- const Preprocessor &PP = getPreprocessor();
- Total += PP.getTotalMemory();
- if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
- Total += PRec->getTotalMemory();
- Total += PP.getHeaderSearchInfo().getTotalMemory();
-
- return Total;
-}
-
-const IncludeStructure &ParsedAST::getIncludeStructure() const {
- return Includes;
-}
-
-const CanonicalIncludes &ParsedAST::getCanonicalIncludes() const {
- return CanonIncludes;
-}
-
-ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<CompilerInstance> Clang,
- std::unique_ptr<FrontendAction> Action,
- syntax::TokenBuffer Tokens,
- std::vector<SourceLocation> MainFileMacroExpLocs,
- std::vector<Decl *> LocalTopLevelDecls,
- std::vector<Diag> Diags, IncludeStructure Includes,
- CanonicalIncludes CanonIncludes)
- : Preamble(std::move(Preamble)), Clang(std::move(Clang)),
- Action(std::move(Action)), Tokens(std::move(Tokens)),
- MainFileMacroExpLocs(std::move(MainFileMacroExpLocs)),
- Diags(std::move(Diags)),
- LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
- Includes(std::move(Includes)), CanonIncludes(std::move(CanonIncludes)) {
- assert(this->Clang);
- assert(this->Action);
-}
-
-llvm::Optional<ParsedAST>
-buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
- llvm::ArrayRef<Diag> CompilerInvocationDiags,
- const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble) {
- trace::Span Tracer("BuildAST");
- SPAN_ATTACH(Tracer, "File", FileName);
-
- auto VFS = Inputs.FS;
- if (Preamble && Preamble->StatCache)
- VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
- if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
- log("Couldn't set working directory when building the preamble.");
- // We proceed anyway, our lit-tests rely on results for non-existing working
- // dirs.
- }
-
- return ParsedAST::build(
- std::make_unique<CompilerInvocation>(*Invocation),
- CompilerInvocationDiags, Preamble,
- llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, FileName),
- std::move(VFS), Inputs.Index, Inputs.Opts);
-}
-
-} // namespace clangd
-namespace tidy {
-// Force the linker to link in Clang-tidy modules.
-#define LINK_TIDY_MODULE(X) \
- extern volatile int X##ModuleAnchorSource; \
- static int LLVM_ATTRIBUTE_UNUSED X##ModuleAnchorDestination = \
- X##ModuleAnchorSource
-LINK_TIDY_MODULE(Abseil);
-LINK_TIDY_MODULE(Android);
-LINK_TIDY_MODULE(Boost);
-LINK_TIDY_MODULE(Bugprone);
-LINK_TIDY_MODULE(CERT);
-LINK_TIDY_MODULE(CppCoreGuidelines);
-LINK_TIDY_MODULE(Fuchsia);
-LINK_TIDY_MODULE(Google);
-LINK_TIDY_MODULE(HICPP);
-LINK_TIDY_MODULE(LinuxKernel);
-LINK_TIDY_MODULE(LLVM);
-LINK_TIDY_MODULE(Misc);
-LINK_TIDY_MODULE(Modernize);
-// LINK_TIDY_MODULE(MPI); // clangd doesn't support static analyzer.
-LINK_TIDY_MODULE(ObjC);
-LINK_TIDY_MODULE(OpenMP);
-LINK_TIDY_MODULE(Performance);
-LINK_TIDY_MODULE(Portability);
-LINK_TIDY_MODULE(Readability);
-LINK_TIDY_MODULE(Zircon);
-#undef LINK_TIDY_MODULE
-} // namespace tidy
-} // namespace clang
Removed: clang-tools-extra/trunk/clangd/ClangdUnit.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=370861&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h (removed)
@@ -1,139 +0,0 @@
-//===--- ClangdUnit.h --------------------------------------------*- C++-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
-
-#include "Compiler.h"
-#include "Diagnostics.h"
-#include "Headers.h"
-#include "Path.h"
-#include "Preamble.h"
-#include "index/CanonicalIncludes.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/Frontend/PrecompiledPreamble.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Tooling/CompilationDatabase.h"
-#include "clang/Tooling/Syntax/Tokens.h"
-#include "llvm/ADT/ArrayRef.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace clang {
-namespace clangd {
-class SymbolIndex;
-
-/// Stores and provides access to parsed AST.
-class ParsedAST {
-public:
- /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null
- /// it is reused during parsing.
- static llvm::Optional<ParsedAST>
- build(std::unique_ptr<clang::CompilerInvocation> CI,
- llvm::ArrayRef<Diag> CompilerInvocationDiags,
- std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- const SymbolIndex *Index, const ParseOptions &Opts);
-
- ParsedAST(ParsedAST &&Other);
- ParsedAST &operator=(ParsedAST &&Other);
-
- ~ParsedAST();
-
- /// Note that the returned ast will not contain decls from the preamble that
- /// were not deserialized during parsing. Clients should expect only decls
- /// from the main file to be in the AST.
- ASTContext &getASTContext();
- const ASTContext &getASTContext() const;
-
- Preprocessor &getPreprocessor();
- std::shared_ptr<Preprocessor> getPreprocessorPtr();
- const Preprocessor &getPreprocessor() const;
-
- SourceManager &getSourceManager() {
- return getASTContext().getSourceManager();
- }
- const SourceManager &getSourceManager() const {
- return getASTContext().getSourceManager();
- }
-
- /// This function returns top-level decls present in the main file of the AST.
- /// The result does not include the decls that come from the preamble.
- /// (These should be const, but RecursiveASTVisitor requires Decl*).
- ArrayRef<Decl *> getLocalTopLevelDecls();
-
- const std::vector<Diag> &getDiagnostics() const;
-
- /// Returns the esitmated size of the AST and the accessory structures, in
- /// bytes. Does not include the size of the preamble.
- std::size_t getUsedBytes() const;
- const IncludeStructure &getIncludeStructure() const;
- const CanonicalIncludes &getCanonicalIncludes() const;
-
- /// The start locations of all macro expansions spelled inside the main file.
- /// Does not include expansions from inside other macro expansions.
- llvm::ArrayRef<SourceLocation> getMainFileExpansions() const;
- /// Tokens recorded while parsing the main file.
- /// (!) does not have tokens from the preamble.
- const syntax::TokenBuffer &getTokens() const { return Tokens; }
-
-private:
- ParsedAST(std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<CompilerInstance> Clang,
- std::unique_ptr<FrontendAction> Action, syntax::TokenBuffer Tokens,
- std::vector<SourceLocation> MainFileMacroExpLocs,
- std::vector<Decl *> LocalTopLevelDecls, std::vector<Diag> Diags,
- IncludeStructure Includes, CanonicalIncludes CanonIncludes);
-
- // In-memory preambles must outlive the AST, it is important that this member
- // goes before Clang and Action.
- std::shared_ptr<const PreambleData> Preamble;
- // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called
- // on it) and CompilerInstance used to run it. That way we don't have to do
- // complex memory management of all Clang structures on our own. (They are
- // stored in CompilerInstance and cleaned up by
- // FrontendAction.EndSourceFile).
- std::unique_ptr<CompilerInstance> Clang;
- std::unique_ptr<FrontendAction> Action;
- /// Tokens recorded after the preamble finished.
- /// - Includes all spelled tokens for the main file.
- /// - Includes expanded tokens produced **after** preabmle.
- /// - Does not have spelled or expanded tokens for files from preamble.
- syntax::TokenBuffer Tokens;
-
- /// The start locations of all macro expansions spelled inside the main file.
- /// Does not include expansions from inside other macro expansions.
- std::vector<SourceLocation> MainFileMacroExpLocs;
- // Data, stored after parsing.
- std::vector<Diag> Diags;
- // Top-level decls inside the current file. Not that this does not include
- // top-level decls from the preamble.
- std::vector<Decl *> LocalTopLevelDecls;
- IncludeStructure Includes;
- CanonicalIncludes CanonIncludes;
-};
-
-/// Build an AST from provided user inputs. This function does not check if
-/// preamble can be reused, as this function expects that \p Preamble is the
-/// result of calling buildPreamble.
-llvm::Optional<ParsedAST>
-buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
- llvm::ArrayRef<Diag> CompilerInvocationDiags,
- const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble);
-
-/// For testing/debugging purposes. Note that this method deserializes all
-/// unserialized Decls, so use with care.
-void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
-
-} // namespace clangd
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
Modified: clang-tools-extra/trunk/clangd/FindSymbols.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/FindSymbols.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/FindSymbols.cpp (original)
+++ clang-tools-extra/trunk/clangd/FindSymbols.cpp Wed Sep 4 02:46:06 2019
@@ -8,9 +8,9 @@
#include "FindSymbols.h"
#include "AST.h"
-#include "ClangdUnit.h"
#include "FuzzyMatch.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Quality.h"
#include "SourceCode.h"
#include "index/Index.h"
Added: clang-tools-extra/trunk/clangd/ParsedAST.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ParsedAST.cpp?rev=370862&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/ParsedAST.cpp (added)
+++ clang-tools-extra/trunk/clangd/ParsedAST.cpp Wed Sep 4 02:46:06 2019
@@ -0,0 +1,574 @@
+//===--- ParsedAST.cpp -------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ParsedAST.h"
+#include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
+#include "../clang-tidy/ClangTidyModuleRegistry.h"
+#include "AST.h"
+#include "Compiler.h"
+#include "Diagnostics.h"
+#include "Headers.h"
+#include "IncludeFixer.h"
+#include "Logger.h"
+#include "SourceCode.h"
+#include "Trace.h"
+#include "index/CanonicalIncludes.h"
+#include "index/Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexDataConsumer.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/PCHContainerOperations.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Syntax/Tokens.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <memory>
+
+namespace clang {
+namespace clangd {
+namespace {
+
+template <class T> std::size_t getUsedBytes(const std::vector<T> &Vec) {
+ return Vec.capacity() * sizeof(T);
+}
+
+class DeclTrackingASTConsumer : public ASTConsumer {
+public:
+ DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
+ : TopLevelDecls(TopLevelDecls) {}
+
+ bool HandleTopLevelDecl(DeclGroupRef DG) override {
+ for (Decl *D : DG) {
+ auto &SM = D->getASTContext().getSourceManager();
+ if (!isInsideMainFile(D->getLocation(), SM))
+ continue;
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (isImplicitTemplateInstantiation(ND))
+ continue;
+
+ // ObjCMethodDecl are not actually top-level decls.
+ if (isa<ObjCMethodDecl>(D))
+ continue;
+
+ TopLevelDecls.push_back(D);
+ }
+ return true;
+ }
+
+private:
+ std::vector<Decl *> &TopLevelDecls;
+};
+
+class ClangdFrontendAction : public SyntaxOnlyAction {
+public:
+ std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
+
+protected:
+ std::unique_ptr<ASTConsumer>
+ CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
+ return std::make_unique<DeclTrackingASTConsumer>(/*ref*/ TopLevelDecls);
+ }
+
+private:
+ std::vector<Decl *> TopLevelDecls;
+};
+
+// This collects macro expansions in the main file.
+// (Contrast with CollectMainFileMacros in Preamble.cpp, which collects macro
+// *definitions* in the preamble region of the main file).
+class CollectMainFileMacroExpansions : public PPCallbacks {
+ const SourceManager &SM;
+ std::vector<SourceLocation> &MainFileMacroLocs;
+
+public:
+ CollectMainFileMacroExpansions(const SourceManager &SM,
+ std::vector<SourceLocation> &MainFileMacroLocs)
+ : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
+
+ virtual void MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &MD, SourceRange Range,
+ const MacroArgs *Args) {
+ SourceLocation L = MacroNameTok.getLocation();
+ if (!L.isMacroID() && isInsideMainFile(L, SM))
+ MainFileMacroLocs.push_back(L);
+ }
+};
+
+// When using a preamble, only preprocessor events outside its bounds are seen.
+// This is almost what we want: replaying transitive preprocessing wastes time.
+// However this confuses clang-tidy checks: they don't see any #includes!
+// So we replay the *non-transitive* #includes that appear in the main-file.
+// It would be nice to replay other events (macro definitions, ifdefs etc) but
+// this addresses the most common cases fairly cheaply.
+class ReplayPreamble : private PPCallbacks {
+public:
+ // Attach preprocessor hooks such that preamble events will be injected at
+ // the appropriate time.
+ // Events will be delivered to the *currently registered* PP callbacks.
+ static void attach(const IncludeStructure &Includes,
+ CompilerInstance &Clang) {
+ auto &PP = Clang.getPreprocessor();
+ auto *ExistingCallbacks = PP.getPPCallbacks();
+ // No need to replay events if nobody is listening.
+ if (!ExistingCallbacks)
+ return;
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(
+ new ReplayPreamble(Includes, ExistingCallbacks,
+ Clang.getSourceManager(), PP, Clang.getLangOpts())));
+ // We're relying on the fact that addPPCallbacks keeps the old PPCallbacks
+ // around, creating a chaining wrapper. Guard against other implementations.
+ assert(PP.getPPCallbacks() != ExistingCallbacks &&
+ "Expected chaining implementation");
+ }
+
+private:
+ ReplayPreamble(const IncludeStructure &Includes, PPCallbacks *Delegate,
+ const SourceManager &SM, Preprocessor &PP,
+ const LangOptions &LangOpts)
+ : Includes(Includes), Delegate(Delegate), SM(SM), PP(PP),
+ LangOpts(LangOpts) {}
+
+ // In a normal compile, the preamble traverses the following structure:
+ //
+ // mainfile.cpp
+ // <built-in>
+ // ... macro definitions like __cplusplus ...
+ // <command-line>
+ // ... macro definitions for args like -Dfoo=bar ...
+ // "header1.h"
+ // ... header file contents ...
+ // "header2.h"
+ // ... header file contents ...
+ // ... main file contents ...
+ //
+ // When using a preamble, the "header1" and "header2" subtrees get skipped.
+ // We insert them right after the built-in header, which still appears.
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind Kind, FileID PrevFID) override {
+ // It'd be nice if there was a better way to identify built-in headers...
+ if (Reason == FileChangeReason::ExitFile &&
+ SM.getBuffer(PrevFID)->getBufferIdentifier() == "<built-in>")
+ replay();
+ }
+
+ void replay() {
+ for (const auto &Inc : Includes.MainFileIncludes) {
+ const FileEntry *File = nullptr;
+ if (Inc.Resolved != "")
+ if (auto FE = SM.getFileManager().getFile(Inc.Resolved))
+ File = *FE;
+
+ llvm::StringRef WrittenFilename =
+ llvm::StringRef(Inc.Written).drop_front().drop_back();
+ bool Angled = llvm::StringRef(Inc.Written).startswith("<");
+
+ // Re-lex the #include directive to find its interesting parts.
+ llvm::StringRef Src = SM.getBufferData(SM.getMainFileID());
+ Lexer RawLexer(SM.getLocForStartOfFile(SM.getMainFileID()), LangOpts,
+ Src.begin(), Src.begin() + Inc.HashOffset, Src.end());
+ Token HashTok, IncludeTok, FilenameTok;
+ RawLexer.LexFromRawLexer(HashTok);
+ assert(HashTok.getKind() == tok::hash);
+ RawLexer.setParsingPreprocessorDirective(true);
+ RawLexer.LexFromRawLexer(IncludeTok);
+ IdentifierInfo *II = PP.getIdentifierInfo(IncludeTok.getRawIdentifier());
+ IncludeTok.setIdentifierInfo(II);
+ IncludeTok.setKind(II->getTokenID());
+ RawLexer.LexIncludeFilename(FilenameTok);
+
+ Delegate->InclusionDirective(
+ HashTok.getLocation(), IncludeTok, WrittenFilename, Angled,
+ CharSourceRange::getCharRange(FilenameTok.getLocation(),
+ FilenameTok.getEndLoc()),
+ File, "SearchPath", "RelPath", /*Imported=*/nullptr, Inc.FileKind);
+ if (File)
+ // FIXME: Use correctly named FileEntryRef.
+ Delegate->FileSkipped(FileEntryRef(File->getName(), *File), FilenameTok,
+ Inc.FileKind);
+ else {
+ llvm::SmallString<1> UnusedRecovery;
+ Delegate->FileNotFound(WrittenFilename, UnusedRecovery);
+ }
+ }
+ }
+
+ const IncludeStructure &Includes;
+ PPCallbacks *Delegate;
+ const SourceManager &SM;
+ Preprocessor &PP;
+ const LangOptions &LangOpts;
+};
+
+} // namespace
+
+void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) {
+ AST.getASTContext().getTranslationUnitDecl()->dump(OS, true);
+}
+
+llvm::Optional<ParsedAST>
+ParsedAST::build(std::unique_ptr<clang::CompilerInvocation> CI,
+ llvm::ArrayRef<Diag> CompilerInvocationDiags,
+ std::shared_ptr<const PreambleData> Preamble,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const SymbolIndex *Index, const ParseOptions &Opts) {
+ assert(CI);
+ // Command-line parsing sets DisableFree to true by default, but we don't want
+ // to leak memory in clangd.
+ CI->getFrontendOpts().DisableFree = false;
+ const PrecompiledPreamble *PreamblePCH =
+ Preamble ? &Preamble->Preamble : nullptr;
+
+ StoreDiags ASTDiags;
+ std::string Content = Buffer->getBuffer();
+ std::string Filename = Buffer->getBufferIdentifier(); // Absolute.
+
+ auto Clang = prepareCompilerInstance(std::move(CI), PreamblePCH,
+ std::move(Buffer), VFS, ASTDiags);
+ if (!Clang)
+ return None;
+
+ auto Action = std::make_unique<ClangdFrontendAction>();
+ const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
+ if (!Action->BeginSourceFile(*Clang, MainInput)) {
+ log("BeginSourceFile() failed when building AST for {0}",
+ MainInput.getFile());
+ return None;
+ }
+
+ // Set up ClangTidy. Must happen after BeginSourceFile() so ASTContext exists.
+ // Clang-tidy has some limitiations to ensure reasonable performance:
+ // - checks don't see all preprocessor events in the preamble
+ // - matchers run only over the main-file top-level decls (and can't see
+ // ancestors outside this scope).
+ // In practice almost all checks work well without modifications.
+ std::vector<std::unique_ptr<tidy::ClangTidyCheck>> CTChecks;
+ ast_matchers::MatchFinder CTFinder;
+ llvm::Optional<tidy::ClangTidyContext> CTContext;
+ {
+ trace::Span Tracer("ClangTidyInit");
+ dlog("ClangTidy configuration for file {0}: {1}", Filename,
+ tidy::configurationAsText(Opts.ClangTidyOpts));
+ tidy::ClangTidyCheckFactories CTFactories;
+ for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
+ E.instantiate()->addCheckFactories(CTFactories);
+ CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>(
+ tidy::ClangTidyGlobalOptions(), Opts.ClangTidyOpts));
+ CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
+ CTContext->setASTContext(&Clang->getASTContext());
+ CTContext->setCurrentFile(Filename);
+ CTFactories.createChecks(CTContext.getPointer(), CTChecks);
+ ASTDiags.setLevelAdjuster([&CTContext](DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &Info) {
+ if (CTContext) {
+ std::string CheckName = CTContext->getCheckName(Info.getID());
+ bool IsClangTidyDiag = !CheckName.empty();
+ if (IsClangTidyDiag) {
+ // Check for warning-as-error.
+ // We deliberately let this take precedence over suppression comments
+ // to match clang-tidy's behaviour.
+ if (DiagLevel == DiagnosticsEngine::Warning &&
+ CTContext->treatAsError(CheckName)) {
+ return DiagnosticsEngine::Error;
+ }
+
+ // Check for suppression comment. Skip the check for diagnostics not
+ // in the main file, because we don't want that function to query the
+ // source buffer for preamble files. For the same reason, we ask
+ // ShouldSuppressDiagnostic not to follow macro expansions, since
+ // those might take us into a preamble file as well.
+ bool IsInsideMainFile =
+ Info.hasSourceManager() &&
+ isInsideMainFile(Info.getLocation(), Info.getSourceManager());
+ if (IsInsideMainFile && tidy::ShouldSuppressDiagnostic(
+ DiagLevel, Info, *CTContext,
+ /* CheckMacroExpansion = */ false)) {
+ return DiagnosticsEngine::Ignored;
+ }
+ }
+ }
+ return DiagLevel;
+ });
+ Preprocessor *PP = &Clang->getPreprocessor();
+ for (const auto &Check : CTChecks) {
+ // FIXME: the PP callbacks skip the entire preamble.
+ // Checks that want to see #includes in the main file do not see them.
+ Check->registerPPCallbacks(Clang->getSourceManager(), PP, PP);
+ Check->registerMatchers(&CTFinder);
+ }
+ }
+
+ // Add IncludeFixer which can recover diagnostics caused by missing includes
+ // (e.g. incomplete type) and attach include insertion fixes to diagnostics.
+ llvm::Optional<IncludeFixer> FixIncludes;
+ auto BuildDir = VFS->getCurrentWorkingDirectory();
+ if (Opts.SuggestMissingIncludes && Index && !BuildDir.getError()) {
+ auto Style = getFormatStyleForFile(Filename, Content, VFS.get());
+ auto Inserter = std::make_shared<IncludeInserter>(
+ Filename, Content, Style, BuildDir.get(),
+ &Clang->getPreprocessor().getHeaderSearchInfo());
+ if (Preamble) {
+ for (const auto &Inc : Preamble->Includes.MainFileIncludes)
+ Inserter->addExisting(Inc);
+ }
+ FixIncludes.emplace(Filename, Inserter, *Index,
+ /*IndexRequestLimit=*/5);
+ ASTDiags.contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
+ const clang::Diagnostic &Info) {
+ return FixIncludes->fix(DiagLevl, Info);
+ });
+ Clang->setExternalSemaSource(FixIncludes->unresolvedNameRecorder());
+ }
+
+ // Copy over the includes from the preamble, then combine with the
+ // non-preamble includes below.
+ auto Includes = Preamble ? Preamble->Includes : IncludeStructure{};
+ // Replay the preamble includes so that clang-tidy checks can see them.
+ if (Preamble)
+ ReplayPreamble::attach(Includes, *Clang);
+ // Important: collectIncludeStructure is registered *after* ReplayPreamble!
+ // Otherwise we would collect the replayed includes again...
+ // (We can't *just* use the replayed includes, they don't have Resolved path).
+ Clang->getPreprocessor().addPPCallbacks(
+ collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
+ // Collect the macro expansions in the main file.
+ std::vector<SourceLocation> MainFileMacroExpLocs;
+ Clang->getPreprocessor().addPPCallbacks(
+ std::make_unique<CollectMainFileMacroExpansions>(
+ Clang->getSourceManager(), MainFileMacroExpLocs));
+
+ // Copy over the includes from the preamble, then combine with the
+ // non-preamble includes below.
+ CanonicalIncludes CanonIncludes;
+ if (Preamble)
+ CanonIncludes = Preamble->CanonIncludes;
+ else
+ addSystemHeadersMapping(&CanonIncludes, Clang->getLangOpts());
+ std::unique_ptr<CommentHandler> IWYUHandler =
+ collectIWYUHeaderMaps(&CanonIncludes);
+ Clang->getPreprocessor().addCommentHandler(IWYUHandler.get());
+
+ // Collect tokens of the main file.
+ syntax::TokenCollector CollectTokens(Clang->getPreprocessor());
+
+ if (llvm::Error Err = Action->Execute())
+ log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
+ toString(std::move(Err)));
+
+ // We have to consume the tokens before running clang-tidy to avoid collecting
+ // tokens from running the preprocessor inside the checks (only
+ // modernize-use-trailing-return-type does that today).
+ syntax::TokenBuffer Tokens = std::move(CollectTokens).consume();
+ std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
+ // AST traversals should exclude the preamble, to avoid performance cliffs.
+ Clang->getASTContext().setTraversalScope(ParsedDecls);
+ {
+ // Run the AST-dependent part of the clang-tidy checks.
+ // (The preprocessor part ran already, via PPCallbacks).
+ trace::Span Tracer("ClangTidyMatch");
+ CTFinder.matchAST(Clang->getASTContext());
+ }
+
+ // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
+ // has a longer lifetime.
+ Clang->getDiagnostics().setClient(new IgnoreDiagnostics);
+ // CompilerInstance won't run this callback, do it directly.
+ ASTDiags.EndSourceFile();
+ // XXX: This is messy: clang-tidy checks flush some diagnostics at EOF.
+ // However Action->EndSourceFile() would destroy the ASTContext!
+ // So just inform the preprocessor of EOF, while keeping everything alive.
+ Clang->getPreprocessor().EndSourceFile();
+
+ std::vector<Diag> Diags = CompilerInvocationDiags;
+ // Add diagnostics from the preamble, if any.
+ if (Preamble)
+ Diags.insert(Diags.end(), Preamble->Diags.begin(), Preamble->Diags.end());
+ // Finally, add diagnostics coming from the AST.
+ {
+ std::vector<Diag> D = ASTDiags.take(CTContext.getPointer());
+ Diags.insert(Diags.end(), D.begin(), D.end());
+ }
+ return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
+ std::move(Tokens), std::move(MainFileMacroExpLocs),
+ std::move(ParsedDecls), std::move(Diags),
+ std::move(Includes), std::move(CanonIncludes));
+}
+
+ParsedAST::ParsedAST(ParsedAST &&Other) = default;
+
+ParsedAST &ParsedAST::operator=(ParsedAST &&Other) = default;
+
+ParsedAST::~ParsedAST() {
+ if (Action) {
+ // We already notified the PP of end-of-file earlier, so detach it first.
+ // We must keep it alive until after EndSourceFile(), Sema relies on this.
+ auto PP = Clang->getPreprocessorPtr(); // Keep PP alive for now.
+ Clang->setPreprocessor(nullptr); // Detach so we don't send EOF again.
+ Action->EndSourceFile(); // Destroy ASTContext and Sema.
+ // Now Sema is gone, it's safe for PP to go out of scope.
+ }
+}
+
+ASTContext &ParsedAST::getASTContext() { return Clang->getASTContext(); }
+
+const ASTContext &ParsedAST::getASTContext() const {
+ return Clang->getASTContext();
+}
+
+Preprocessor &ParsedAST::getPreprocessor() { return Clang->getPreprocessor(); }
+
+std::shared_ptr<Preprocessor> ParsedAST::getPreprocessorPtr() {
+ return Clang->getPreprocessorPtr();
+}
+
+const Preprocessor &ParsedAST::getPreprocessor() const {
+ return Clang->getPreprocessor();
+}
+
+llvm::ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
+ return LocalTopLevelDecls;
+}
+
+llvm::ArrayRef<SourceLocation> ParsedAST::getMainFileExpansions() const {
+ return MainFileMacroExpLocs;
+}
+
+const std::vector<Diag> &ParsedAST::getDiagnostics() const { return Diags; }
+
+std::size_t ParsedAST::getUsedBytes() const {
+ auto &AST = getASTContext();
+ // FIXME(ibiryukov): we do not account for the dynamically allocated part of
+ // Message and Fixes inside each diagnostic.
+ std::size_t Total =
+ clangd::getUsedBytes(LocalTopLevelDecls) + clangd::getUsedBytes(Diags);
+
+ // FIXME: the rest of the function is almost a direct copy-paste from
+ // libclang's clang_getCXTUResourceUsage. We could share the implementation.
+
+ // Sum up variaous allocators inside the ast context and the preprocessor.
+ Total += AST.getASTAllocatedMemory();
+ Total += AST.getSideTableAllocatedMemory();
+ Total += AST.Idents.getAllocator().getTotalMemory();
+ Total += AST.Selectors.getTotalMemory();
+
+ Total += AST.getSourceManager().getContentCacheSize();
+ Total += AST.getSourceManager().getDataStructureSizes();
+ Total += AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
+
+ if (ExternalASTSource *Ext = AST.getExternalSource())
+ Total += Ext->getMemoryBufferSizes().malloc_bytes;
+
+ const Preprocessor &PP = getPreprocessor();
+ Total += PP.getTotalMemory();
+ if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
+ Total += PRec->getTotalMemory();
+ Total += PP.getHeaderSearchInfo().getTotalMemory();
+
+ return Total;
+}
+
+const IncludeStructure &ParsedAST::getIncludeStructure() const {
+ return Includes;
+}
+
+const CanonicalIncludes &ParsedAST::getCanonicalIncludes() const {
+ return CanonIncludes;
+}
+
+ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
+ std::unique_ptr<CompilerInstance> Clang,
+ std::unique_ptr<FrontendAction> Action,
+ syntax::TokenBuffer Tokens,
+ std::vector<SourceLocation> MainFileMacroExpLocs,
+ std::vector<Decl *> LocalTopLevelDecls,
+ std::vector<Diag> Diags, IncludeStructure Includes,
+ CanonicalIncludes CanonIncludes)
+ : Preamble(std::move(Preamble)), Clang(std::move(Clang)),
+ Action(std::move(Action)), Tokens(std::move(Tokens)),
+ MainFileMacroExpLocs(std::move(MainFileMacroExpLocs)),
+ Diags(std::move(Diags)),
+ LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
+ Includes(std::move(Includes)), CanonIncludes(std::move(CanonIncludes)) {
+ assert(this->Clang);
+ assert(this->Action);
+}
+
+llvm::Optional<ParsedAST>
+buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
+ llvm::ArrayRef<Diag> CompilerInvocationDiags,
+ const ParseInputs &Inputs,
+ std::shared_ptr<const PreambleData> Preamble) {
+ trace::Span Tracer("BuildAST");
+ SPAN_ATTACH(Tracer, "File", FileName);
+
+ auto VFS = Inputs.FS;
+ if (Preamble && Preamble->StatCache)
+ VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
+ if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+ log("Couldn't set working directory when building the preamble.");
+ // We proceed anyway, our lit-tests rely on results for non-existing working
+ // dirs.
+ }
+
+ return ParsedAST::build(
+ std::make_unique<CompilerInvocation>(*Invocation),
+ CompilerInvocationDiags, Preamble,
+ llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, FileName),
+ std::move(VFS), Inputs.Index, Inputs.Opts);
+}
+
+} // namespace clangd
+namespace tidy {
+// Force the linker to link in Clang-tidy modules.
+#define LINK_TIDY_MODULE(X) \
+ extern volatile int X##ModuleAnchorSource; \
+ static int LLVM_ATTRIBUTE_UNUSED X##ModuleAnchorDestination = \
+ X##ModuleAnchorSource
+LINK_TIDY_MODULE(Abseil);
+LINK_TIDY_MODULE(Android);
+LINK_TIDY_MODULE(Boost);
+LINK_TIDY_MODULE(Bugprone);
+LINK_TIDY_MODULE(CERT);
+LINK_TIDY_MODULE(CppCoreGuidelines);
+LINK_TIDY_MODULE(Fuchsia);
+LINK_TIDY_MODULE(Google);
+LINK_TIDY_MODULE(HICPP);
+LINK_TIDY_MODULE(LinuxKernel);
+LINK_TIDY_MODULE(LLVM);
+LINK_TIDY_MODULE(Misc);
+LINK_TIDY_MODULE(Modernize);
+// LINK_TIDY_MODULE(MPI); // clangd doesn't support static analyzer.
+LINK_TIDY_MODULE(ObjC);
+LINK_TIDY_MODULE(OpenMP);
+LINK_TIDY_MODULE(Performance);
+LINK_TIDY_MODULE(Portability);
+LINK_TIDY_MODULE(Readability);
+LINK_TIDY_MODULE(Zircon);
+#undef LINK_TIDY_MODULE
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clangd/ParsedAST.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ParsedAST.h?rev=370862&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/ParsedAST.h (added)
+++ clang-tools-extra/trunk/clangd/ParsedAST.h Wed Sep 4 02:46:06 2019
@@ -0,0 +1,151 @@
+//===--- ParsedAST.h - Building translation units ----------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file exposes building a file as if it were open in clangd, and defines
+// the ParsedAST structure that holds the results.
+//
+// This is similar to a clang -fsyntax-only run that produces a clang AST, but
+// we have several customizations:
+// - preamble handling
+// - capturing diagnostics for later access
+// - running clang-tidy checks checks
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H
+
+#include "Compiler.h"
+#include "Diagnostics.h"
+#include "Headers.h"
+#include "Path.h"
+#include "Preamble.h"
+#include "index/CanonicalIncludes.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Syntax/Tokens.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace clangd {
+class SymbolIndex;
+
+/// Stores and provides access to parsed AST.
+class ParsedAST {
+public:
+ /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null
+ /// it is reused during parsing.
+ static llvm::Optional<ParsedAST>
+ build(std::unique_ptr<clang::CompilerInvocation> CI,
+ llvm::ArrayRef<Diag> CompilerInvocationDiags,
+ std::shared_ptr<const PreambleData> Preamble,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const SymbolIndex *Index, const ParseOptions &Opts);
+
+ ParsedAST(ParsedAST &&Other);
+ ParsedAST &operator=(ParsedAST &&Other);
+
+ ~ParsedAST();
+
+ /// Note that the returned ast will not contain decls from the preamble that
+ /// were not deserialized during parsing. Clients should expect only decls
+ /// from the main file to be in the AST.
+ ASTContext &getASTContext();
+ const ASTContext &getASTContext() const;
+
+ Preprocessor &getPreprocessor();
+ std::shared_ptr<Preprocessor> getPreprocessorPtr();
+ const Preprocessor &getPreprocessor() const;
+
+ SourceManager &getSourceManager() {
+ return getASTContext().getSourceManager();
+ }
+ const SourceManager &getSourceManager() const {
+ return getASTContext().getSourceManager();
+ }
+
+ /// This function returns top-level decls present in the main file of the AST.
+ /// The result does not include the decls that come from the preamble.
+ /// (These should be const, but RecursiveASTVisitor requires Decl*).
+ ArrayRef<Decl *> getLocalTopLevelDecls();
+
+ const std::vector<Diag> &getDiagnostics() const;
+
+ /// Returns the esitmated size of the AST and the accessory structures, in
+ /// bytes. Does not include the size of the preamble.
+ std::size_t getUsedBytes() const;
+ const IncludeStructure &getIncludeStructure() const;
+ const CanonicalIncludes &getCanonicalIncludes() const;
+
+ /// The start locations of all macro expansions spelled inside the main file.
+ /// Does not include expansions from inside other macro expansions.
+ llvm::ArrayRef<SourceLocation> getMainFileExpansions() const;
+ /// Tokens recorded while parsing the main file.
+ /// (!) does not have tokens from the preamble.
+ const syntax::TokenBuffer &getTokens() const { return Tokens; }
+
+private:
+ ParsedAST(std::shared_ptr<const PreambleData> Preamble,
+ std::unique_ptr<CompilerInstance> Clang,
+ std::unique_ptr<FrontendAction> Action, syntax::TokenBuffer Tokens,
+ std::vector<SourceLocation> MainFileMacroExpLocs,
+ std::vector<Decl *> LocalTopLevelDecls, std::vector<Diag> Diags,
+ IncludeStructure Includes, CanonicalIncludes CanonIncludes);
+
+ // In-memory preambles must outlive the AST, it is important that this member
+ // goes before Clang and Action.
+ std::shared_ptr<const PreambleData> Preamble;
+ // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called
+ // on it) and CompilerInstance used to run it. That way we don't have to do
+ // complex memory management of all Clang structures on our own. (They are
+ // stored in CompilerInstance and cleaned up by
+ // FrontendAction.EndSourceFile).
+ std::unique_ptr<CompilerInstance> Clang;
+ std::unique_ptr<FrontendAction> Action;
+ /// Tokens recorded after the preamble finished.
+ /// - Includes all spelled tokens for the main file.
+ /// - Includes expanded tokens produced **after** preabmle.
+ /// - Does not have spelled or expanded tokens for files from preamble.
+ syntax::TokenBuffer Tokens;
+
+ /// The start locations of all macro expansions spelled inside the main file.
+ /// Does not include expansions from inside other macro expansions.
+ std::vector<SourceLocation> MainFileMacroExpLocs;
+ // Data, stored after parsing.
+ std::vector<Diag> Diags;
+ // Top-level decls inside the current file. Not that this does not include
+ // top-level decls from the preamble.
+ std::vector<Decl *> LocalTopLevelDecls;
+ IncludeStructure Includes;
+ CanonicalIncludes CanonIncludes;
+};
+
+/// Build an AST from provided user inputs. This function does not check if
+/// preamble can be reused, as this function expects that \p Preamble is the
+/// result of calling buildPreamble.
+llvm::Optional<ParsedAST>
+buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
+ llvm::ArrayRef<Diag> CompilerInvocationDiags,
+ const ParseInputs &Inputs,
+ std::shared_ptr<const PreambleData> Preamble);
+
+/// For testing/debugging purposes. Note that this method deserializes all
+/// unserialized Decls, so use with care.
+void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H
Modified: clang-tools-extra/trunk/clangd/Preamble.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Preamble.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Preamble.cpp (original)
+++ clang-tools-extra/trunk/clangd/Preamble.cpp Wed Sep 4 02:46:06 2019
@@ -25,7 +25,7 @@ bool compileCommandsAreEqual(const tooli
}
// This collects macro definitions in the *preamble region* of the main file.
-// (Contrast with CollectMainFileMacroExpansions in ClangdUnit.cpp, which
+// (Contrast with CollectMainFileMacroExpansions in ParsedAST.cpp, which
// collects macro *expansions* in the rest of the main file.
class CollectMainFileMacros : public PPCallbacks {
public:
Modified: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp (original)
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp Wed Sep 4 02:46:06 2019
@@ -8,6 +8,7 @@
#include "SemanticHighlighting.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "clang/AST/ASTContext.h"
Modified: clang-tools-extra/trunk/clangd/SemanticHighlighting.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/SemanticHighlighting.h?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.h (original)
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.h Wed Sep 4 02:46:06 2019
@@ -17,11 +17,11 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SEMANTICHIGHLIGHTING_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SEMANTICHIGHLIGHTING_H
-#include "ClangdUnit.h"
#include "Protocol.h"
namespace clang {
namespace clangd {
+class ParsedAST;
enum class HighlightingKind {
Variable = 0,
Modified: clang-tools-extra/trunk/clangd/TUScheduler.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/TUScheduler.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/TUScheduler.cpp (original)
+++ clang-tools-extra/trunk/clangd/TUScheduler.cpp Wed Sep 4 02:46:06 2019
@@ -43,11 +43,11 @@
#include "TUScheduler.h"
#include "Cancellation.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
#include "Diagnostics.h"
#include "GlobalCompilationDatabase.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Preamble.h"
#include "Trace.h"
#include "index/CanonicalIncludes.h"
Modified: clang-tools-extra/trunk/clangd/XRefs.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/XRefs.cpp (original)
+++ clang-tools-extra/trunk/clangd/XRefs.cpp Wed Sep 4 02:46:06 2019
@@ -11,6 +11,7 @@
#include "FindSymbols.h"
#include "FormattedString.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "URI.h"
Modified: clang-tools-extra/trunk/clangd/XRefs.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.h?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/XRefs.h (original)
+++ clang-tools-extra/trunk/clangd/XRefs.h Wed Sep 4 02:46:06 2019
@@ -13,11 +13,13 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_XREFS_H
-#include "ClangdUnit.h"
#include "FormattedString.h"
+#include "Path.h"
#include "Protocol.h"
#include "index/Index.h"
+#include "clang/AST/Type.h"
#include "index/SymbolLocation.h"
+#include "clang/Format/Format.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_ostream.h"
@@ -25,6 +27,7 @@
namespace clang {
namespace clangd {
+class ParsedAST;
// Describes where a symbol is declared and defined (as far as clangd knows).
// There are three cases:
Modified: clang-tools-extra/trunk/clangd/index/Background.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Background.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Background.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/Background.cpp Wed Sep 4 02:46:06 2019
@@ -7,12 +7,12 @@
//===----------------------------------------------------------------------===//
#include "index/Background.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
#include "Context.h"
#include "FSProvider.h"
#include "Headers.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Path.h"
#include "SourceCode.h"
#include "Symbol.h"
Modified: clang-tools-extra/trunk/clangd/index/BackgroundRebuild.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/BackgroundRebuild.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/BackgroundRebuild.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/BackgroundRebuild.cpp Wed Sep 4 02:46:06 2019
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
#include "index/BackgroundRebuild.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
#include "Headers.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Path.h"
#include "SourceCode.h"
#include "Symbol.h"
Modified: clang-tools-extra/trunk/clangd/index/FileIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/FileIndex.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/FileIndex.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/FileIndex.cpp Wed Sep 4 02:46:06 2019
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "FileIndex.h"
-#include "ClangdUnit.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "SymbolCollector.h"
#include "index/CanonicalIncludes.h"
#include "index/Index.h"
Modified: clang-tools-extra/trunk/clangd/refactor/Rename.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/Rename.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/Rename.cpp (original)
+++ clang-tools-extra/trunk/clangd/refactor/Rename.cpp Wed Sep 4 02:46:06 2019
@@ -8,8 +8,8 @@
#include "refactor/Rename.h"
#include "AST.h"
-#include "ClangdUnit.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "SourceCode.h"
#include "index/SymbolCollector.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
Modified: clang-tools-extra/trunk/clangd/refactor/Tweak.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/Tweak.h?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/Tweak.h (original)
+++ clang-tools-extra/trunk/clangd/refactor/Tweak.h Wed Sep 4 02:46:06 2019
@@ -19,7 +19,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_TWEAK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_ACTIONS_TWEAK_H
-#include "ClangdUnit.h"
+#include "ParsedAST.h"
#include "Protocol.h"
#include "Selection.h"
#include "clang/Tooling/Core/Replacement.h"
Modified: clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractFunction.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractFunction.cpp (original)
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractFunction.cpp Wed Sep 4 02:46:06 2019
@@ -47,8 +47,8 @@
//===----------------------------------------------------------------------===//
#include "AST.h"
-#include "ClangdUnit.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Selection.h"
#include "SourceCode.h"
#include "refactor/Tweak.h"
Modified: clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp (original)
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp Wed Sep 4 02:46:06 2019
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-#include "ClangdUnit.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "Protocol.h"
#include "Selection.h"
#include "SourceCode.h"
Modified: clang-tools-extra/trunk/clangd/refactor/tweaks/RawStringLiteral.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/tweaks/RawStringLiteral.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/tweaks/RawStringLiteral.cpp (original)
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/RawStringLiteral.cpp Wed Sep 4 02:46:06 2019
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-#include "ClangdUnit.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "SourceCode.h"
#include "refactor/Tweak.h"
#include "clang/AST/ASTContext.h"
Modified: clang-tools-extra/trunk/clangd/refactor/tweaks/SwapIfBranches.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/refactor/tweaks/SwapIfBranches.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/refactor/tweaks/SwapIfBranches.cpp (original)
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/SwapIfBranches.cpp Wed Sep 4 02:46:06 2019
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-#include "ClangdUnit.h"
#include "Logger.h"
+#include "ParsedAST.h"
#include "SourceCode.h"
#include "refactor/Tweak.h"
#include "clang/AST/ASTContext.h"
Modified: clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt Wed Sep 4 02:46:06 2019
@@ -28,7 +28,6 @@ add_unittest(ClangdUnitTests ClangdTests
CancellationTests.cpp
CanonicalIncludesTests.cpp
ClangdTests.cpp
- ClangdUnitTests.cpp
CodeCompleteTests.cpp
CodeCompletionStringsTests.cpp
ContextTests.cpp
@@ -50,6 +49,7 @@ add_unittest(ClangdUnitTests ClangdTests
IndexActionTests.cpp
IndexTests.cpp
JSONTransportTests.cpp
+ ParsedASTTests.cpp
PrintASTTests.cpp
QualityTests.cpp
RenameTests.cpp
Removed: clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp?rev=370861&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp (removed)
@@ -1,278 +0,0 @@
-//===-- ClangdUnitTests.cpp - ClangdUnit tests ------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "AST.h"
-#include "Annotations.h"
-#include "ClangdUnit.h"
-#include "Compiler.h"
-#include "Diagnostics.h"
-#include "SourceCode.h"
-#include "TestFS.h"
-#include "TestTU.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/TokenKinds.h"
-#include "clang/Tooling/Syntax/Tokens.h"
-#include "llvm/Support/ScopedPrinter.h"
-#include "gmock/gmock-matchers.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace clangd {
-namespace {
-
-using ::testing::ElementsAre;
-using ::testing::ElementsAreArray;
-using ::testing::AllOf;
-
-MATCHER_P(DeclNamed, Name, "") {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
- if (ND->getName() == Name)
- return true;
- if (auto *Stream = result_listener->stream()) {
- llvm::raw_os_ostream OS(*Stream);
- arg->dump(OS);
- }
- return false;
-}
-
-// Matches if the Decl has template args equal to ArgName. If the decl is a
-// NamedDecl and ArgName is an empty string it also matches.
-MATCHER_P(WithTemplateArgs, ArgName, "") {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(arg)) {
- if (const auto *Args = FD->getTemplateSpecializationArgs()) {
- std::string SpecializationArgs;
- // Without the PrintingPolicy "bool" will be printed as "_Bool".
- LangOptions LO;
- PrintingPolicy Policy(LO);
- Policy.adjustForCPlusPlus();
- for (const auto Arg : Args->asArray()) {
- if (SpecializationArgs.size() > 0)
- SpecializationArgs += ",";
- SpecializationArgs += Arg.getAsType().getAsString(Policy);
- }
- if (Args->size() == 0)
- return ArgName == SpecializationArgs;
- return ArgName == "<" + SpecializationArgs + ">";
- }
- }
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(arg))
- return printTemplateSpecializationArgs(*ND) == ArgName;
- return false;
-}
-
-TEST(ClangdUnitTest, TopLevelDecls) {
- TestTU TU;
- TU.HeaderCode = R"(
- int header1();
- int header2;
- )";
- TU.Code = "int main();";
- auto AST = TU.build();
- EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
-}
-
-TEST(ClangdUnitTest, DoesNotGetIncludedTopDecls) {
- TestTU TU;
- TU.HeaderCode = R"cpp(
- #define LL void foo(){}
- template<class T>
- struct H {
- H() {}
- LL
- };
- )cpp";
- TU.Code = R"cpp(
- int main() {
- H<int> h;
- h.foo();
- }
- )cpp";
- auto AST = TU.build();
- EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
-}
-
-TEST(ClangdUnitTest, DoesNotGetImplicitTemplateTopDecls) {
- TestTU TU;
- TU.Code = R"cpp(
- template<typename T>
- void f(T) {}
- void s() {
- f(10UL);
- }
- )cpp";
-
- auto AST = TU.build();
- EXPECT_THAT(AST.getLocalTopLevelDecls(),
- ElementsAre(DeclNamed("f"), DeclNamed("s")));
-}
-
-TEST(ClangdUnitTest,
- GetsExplicitInstantiationAndSpecializationTemplateTopDecls) {
- TestTU TU;
- TU.Code = R"cpp(
- template <typename T>
- void f(T) {}
- template<>
- void f(bool);
- template void f(double);
-
- template <class T>
- struct V {};
- template<class T>
- struct V<T*> {};
- template <>
- struct V<bool> {};
-
- template<class T>
- T foo = T(10);
- int i = foo<int>;
- double d = foo<double>;
-
- template <class T>
- int foo<T*> = 0;
- template <>
- int foo<bool> = 0;
- )cpp";
-
- auto AST = TU.build();
- EXPECT_THAT(
- AST.getLocalTopLevelDecls(),
- ElementsAreArray({AllOf(DeclNamed("f"), WithTemplateArgs("")),
- AllOf(DeclNamed("f"), WithTemplateArgs("<bool>")),
- AllOf(DeclNamed("f"), WithTemplateArgs("<double>")),
- AllOf(DeclNamed("V"), WithTemplateArgs("")),
- AllOf(DeclNamed("V"), WithTemplateArgs("<T *>")),
- AllOf(DeclNamed("V"), WithTemplateArgs("<bool>")),
- AllOf(DeclNamed("foo"), WithTemplateArgs("")),
- AllOf(DeclNamed("i"), WithTemplateArgs("")),
- AllOf(DeclNamed("d"), WithTemplateArgs("")),
- AllOf(DeclNamed("foo"), WithTemplateArgs("<T *>")),
- AllOf(DeclNamed("foo"), WithTemplateArgs("<bool>"))}));
-}
-
-TEST(ClangdUnitTest, TokensAfterPreamble) {
- TestTU TU;
- TU.AdditionalFiles["foo.h"] = R"(
- int foo();
- )";
- TU.Code = R"cpp(
- #include "foo.h"
- first_token;
- void test() {
- }
- last_token
-)cpp";
- auto AST = TU.build();
- const syntax::TokenBuffer &T = AST.getTokens();
- const auto &SM = AST.getSourceManager();
-
- ASSERT_GT(T.expandedTokens().size(), 2u);
- // Check first token after the preamble.
- EXPECT_EQ(T.expandedTokens().front().text(SM), "first_token");
- // Last token is always 'eof'.
- EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
- // Check the token before 'eof'.
- EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "last_token");
-
- // The spelled tokens for the main file should have everything.
- auto Spelled = T.spelledTokens(SM.getMainFileID());
- ASSERT_FALSE(Spelled.empty());
- EXPECT_EQ(Spelled.front().kind(), tok::hash);
- EXPECT_EQ(Spelled.back().text(SM), "last_token");
-}
-
-
-TEST(ClangdUnitTest, NoCrashOnTokensWithTidyCheck) {
- TestTU TU;
- // this check runs the preprocessor, we need to make sure it does not break
- // our recording logic.
- TU.ClangTidyChecks = "modernize-use-trailing-return-type";
- TU.Code = "inline int foo() {}";
-
- auto AST = TU.build();
- const syntax::TokenBuffer &T = AST.getTokens();
- const auto &SM = AST.getSourceManager();
-
- ASSERT_GT(T.expandedTokens().size(), 7u);
- // Check first token after the preamble.
- EXPECT_EQ(T.expandedTokens().front().text(SM), "inline");
- // Last token is always 'eof'.
- EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
- // Check the token before 'eof'.
- EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
-}
-
-TEST(ClangdUnitTest, CanBuildInvocationWithUnknownArgs) {
- // Unknown flags should not prevent a build of compiler invocation.
- ParseInputs Inputs;
- Inputs.FS = buildTestFS({{testPath("foo.cpp"), "void test() {}"}});
- Inputs.CompileCommand.CommandLine = {"clang", "-fsome-unknown-flag",
- testPath("foo.cpp")};
- IgnoreDiagnostics IgnoreDiags;
- EXPECT_NE(buildCompilerInvocation(Inputs, IgnoreDiags), nullptr);
-
- // Unknown forwarded to -cc1 should not a failure either.
- Inputs.CompileCommand.CommandLine = {
- "clang", "-Xclang", "-fsome-unknown-flag", testPath("foo.cpp")};
- EXPECT_NE(buildCompilerInvocation(Inputs, IgnoreDiags), nullptr);
-}
-
-TEST(ClangdUnitTest, CollectsMainFileMacroExpansions) {
- Annotations TestCase(R"cpp(
- #define MACRO_ARGS(X, Y) X Y
- ^ID(int A);
- // Macro arguments included.
- ^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2));
-
- // Macro names inside other macros not included.
- #define FOO BAR
- #define BAR 1
- int A = ^FOO;
-
- // Macros from token concatenations not included.
- #define CONCAT(X) X##A()
- #define PREPEND(X) MACRO##X()
- #define MACROA() 123
- int B = ^CONCAT(MACRO);
- int D = ^PREPEND(A)
-
- // Macros included not from preamble not included.
- #include "foo.inc"
-
- #define assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); }
-
- void test() {
- // Includes macro expansions in arguments that are expressions
- ^assert(0 <= ^BAR);
- }
- )cpp");
- auto TU = TestTU::withCode(TestCase.code());
- TU.HeaderCode = R"cpp(
- #define ID(X) X
- #define MACRO_EXP(X) ID(X)
- MACRO_EXP(int B);
- )cpp";
- TU.AdditionalFiles["foo.inc"] = R"cpp(
- int C = ID(1);
- #define DEF 1
- int D = DEF;
- )cpp";
- ParsedAST AST = TU.build();
- const std::vector<SourceLocation> &MacroExpansionLocations =
- AST.getMainFileExpansions();
- std::vector<Position> MacroExpansionPositions;
- for (const auto &L : MacroExpansionLocations)
- MacroExpansionPositions.push_back(
- sourceLocToPosition(AST.getSourceManager(), L));
- EXPECT_EQ(MacroExpansionPositions, TestCase.points());
-}
-
-} // namespace
-} // namespace clangd
-} // namespace clang
Modified: clang-tools-extra/trunk/clangd/unittests/DiagnosticsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/DiagnosticsTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/DiagnosticsTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/DiagnosticsTests.cpp Wed Sep 4 02:46:06 2019
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "Annotations.h"
-#include "ClangdUnit.h"
#include "Diagnostics.h"
+#include "ParsedAST.h"
#include "Path.h"
#include "Protocol.h"
#include "SourceCode.h"
Modified: clang-tools-extra/trunk/clangd/unittests/ExpectedTypeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/ExpectedTypeTest.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/ExpectedTypeTest.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/ExpectedTypeTest.cpp Wed Sep 4 02:46:06 2019
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangdUnit.h"
#include "ExpectedTypes.h"
+#include "ParsedAST.h"
#include "TestTU.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
Modified: clang-tools-extra/trunk/clangd/unittests/FileIndexTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/FileIndexTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/FileIndexTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/FileIndexTests.cpp Wed Sep 4 02:46:06 2019
@@ -8,8 +8,8 @@
#include "AST.h"
#include "Annotations.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
+#include "ParsedAST.h"
#include "SyncAPI.h"
#include "TestFS.h"
#include "TestTU.h"
Added: clang-tools-extra/trunk/clangd/unittests/ParsedASTTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/ParsedASTTests.cpp?rev=370862&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/ParsedASTTests.cpp (added)
+++ clang-tools-extra/trunk/clangd/unittests/ParsedASTTests.cpp Wed Sep 4 02:46:06 2019
@@ -0,0 +1,282 @@
+//===-- ParsedASTTests.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// These tests cover clangd's logic to build a TU, which generally uses the APIs
+// in ParsedAST and Preamble, via the TestTU helper.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AST.h"
+#include "Annotations.h"
+#include "Compiler.h"
+#include "Diagnostics.h"
+#include "ParsedAST.h"
+#include "SourceCode.h"
+#include "TestFS.h"
+#include "TestTU.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Tooling/Syntax/Tokens.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::ElementsAreArray;
+
+MATCHER_P(DeclNamed, Name, "") {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
+ if (ND->getName() == Name)
+ return true;
+ if (auto *Stream = result_listener->stream()) {
+ llvm::raw_os_ostream OS(*Stream);
+ arg->dump(OS);
+ }
+ return false;
+}
+
+// Matches if the Decl has template args equal to ArgName. If the decl is a
+// NamedDecl and ArgName is an empty string it also matches.
+MATCHER_P(WithTemplateArgs, ArgName, "") {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(arg)) {
+ if (const auto *Args = FD->getTemplateSpecializationArgs()) {
+ std::string SpecializationArgs;
+ // Without the PrintingPolicy "bool" will be printed as "_Bool".
+ LangOptions LO;
+ PrintingPolicy Policy(LO);
+ Policy.adjustForCPlusPlus();
+ for (const auto Arg : Args->asArray()) {
+ if (SpecializationArgs.size() > 0)
+ SpecializationArgs += ",";
+ SpecializationArgs += Arg.getAsType().getAsString(Policy);
+ }
+ if (Args->size() == 0)
+ return ArgName == SpecializationArgs;
+ return ArgName == "<" + SpecializationArgs + ">";
+ }
+ }
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(arg))
+ return printTemplateSpecializationArgs(*ND) == ArgName;
+ return false;
+}
+
+TEST(ParsedASTTest, TopLevelDecls) {
+ TestTU TU;
+ TU.HeaderCode = R"(
+ int header1();
+ int header2;
+ )";
+ TU.Code = "int main();";
+ auto AST = TU.build();
+ EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
+}
+
+TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {
+ TestTU TU;
+ TU.HeaderCode = R"cpp(
+ #define LL void foo(){}
+ template<class T>
+ struct H {
+ H() {}
+ LL
+ };
+ )cpp";
+ TU.Code = R"cpp(
+ int main() {
+ H<int> h;
+ h.foo();
+ }
+ )cpp";
+ auto AST = TU.build();
+ EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
+}
+
+TEST(ParsedASTTest, DoesNotGetImplicitTemplateTopDecls) {
+ TestTU TU;
+ TU.Code = R"cpp(
+ template<typename T>
+ void f(T) {}
+ void s() {
+ f(10UL);
+ }
+ )cpp";
+
+ auto AST = TU.build();
+ EXPECT_THAT(AST.getLocalTopLevelDecls(),
+ ElementsAre(DeclNamed("f"), DeclNamed("s")));
+}
+
+TEST(ParsedASTTest,
+ GetsExplicitInstantiationAndSpecializationTemplateTopDecls) {
+ TestTU TU;
+ TU.Code = R"cpp(
+ template <typename T>
+ void f(T) {}
+ template<>
+ void f(bool);
+ template void f(double);
+
+ template <class T>
+ struct V {};
+ template<class T>
+ struct V<T*> {};
+ template <>
+ struct V<bool> {};
+
+ template<class T>
+ T foo = T(10);
+ int i = foo<int>;
+ double d = foo<double>;
+
+ template <class T>
+ int foo<T*> = 0;
+ template <>
+ int foo<bool> = 0;
+ )cpp";
+
+ auto AST = TU.build();
+ EXPECT_THAT(
+ AST.getLocalTopLevelDecls(),
+ ElementsAreArray({AllOf(DeclNamed("f"), WithTemplateArgs("")),
+ AllOf(DeclNamed("f"), WithTemplateArgs("<bool>")),
+ AllOf(DeclNamed("f"), WithTemplateArgs("<double>")),
+ AllOf(DeclNamed("V"), WithTemplateArgs("")),
+ AllOf(DeclNamed("V"), WithTemplateArgs("<T *>")),
+ AllOf(DeclNamed("V"), WithTemplateArgs("<bool>")),
+ AllOf(DeclNamed("foo"), WithTemplateArgs("")),
+ AllOf(DeclNamed("i"), WithTemplateArgs("")),
+ AllOf(DeclNamed("d"), WithTemplateArgs("")),
+ AllOf(DeclNamed("foo"), WithTemplateArgs("<T *>")),
+ AllOf(DeclNamed("foo"), WithTemplateArgs("<bool>"))}));
+}
+
+TEST(ParsedASTTest, TokensAfterPreamble) {
+ TestTU TU;
+ TU.AdditionalFiles["foo.h"] = R"(
+ int foo();
+ )";
+ TU.Code = R"cpp(
+ #include "foo.h"
+ first_token;
+ void test() {
+ }
+ last_token
+)cpp";
+ auto AST = TU.build();
+ const syntax::TokenBuffer &T = AST.getTokens();
+ const auto &SM = AST.getSourceManager();
+
+ ASSERT_GT(T.expandedTokens().size(), 2u);
+ // Check first token after the preamble.
+ EXPECT_EQ(T.expandedTokens().front().text(SM), "first_token");
+ // Last token is always 'eof'.
+ EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
+ // Check the token before 'eof'.
+ EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "last_token");
+
+ // The spelled tokens for the main file should have everything.
+ auto Spelled = T.spelledTokens(SM.getMainFileID());
+ ASSERT_FALSE(Spelled.empty());
+ EXPECT_EQ(Spelled.front().kind(), tok::hash);
+ EXPECT_EQ(Spelled.back().text(SM), "last_token");
+}
+
+TEST(ParsedASTTest, NoCrashOnTokensWithTidyCheck) {
+ TestTU TU;
+ // this check runs the preprocessor, we need to make sure it does not break
+ // our recording logic.
+ TU.ClangTidyChecks = "modernize-use-trailing-return-type";
+ TU.Code = "inline int foo() {}";
+
+ auto AST = TU.build();
+ const syntax::TokenBuffer &T = AST.getTokens();
+ const auto &SM = AST.getSourceManager();
+
+ ASSERT_GT(T.expandedTokens().size(), 7u);
+ // Check first token after the preamble.
+ EXPECT_EQ(T.expandedTokens().front().text(SM), "inline");
+ // Last token is always 'eof'.
+ EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
+ // Check the token before 'eof'.
+ EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
+}
+
+TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) {
+ // Unknown flags should not prevent a build of compiler invocation.
+ ParseInputs Inputs;
+ Inputs.FS = buildTestFS({{testPath("foo.cpp"), "void test() {}"}});
+ Inputs.CompileCommand.CommandLine = {"clang", "-fsome-unknown-flag",
+ testPath("foo.cpp")};
+ IgnoreDiagnostics IgnoreDiags;
+ EXPECT_NE(buildCompilerInvocation(Inputs, IgnoreDiags), nullptr);
+
+ // Unknown forwarded to -cc1 should not a failure either.
+ Inputs.CompileCommand.CommandLine = {
+ "clang", "-Xclang", "-fsome-unknown-flag", testPath("foo.cpp")};
+ EXPECT_NE(buildCompilerInvocation(Inputs, IgnoreDiags), nullptr);
+}
+
+TEST(ParsedASTTest, CollectsMainFileMacroExpansions) {
+ Annotations TestCase(R"cpp(
+ #define MACRO_ARGS(X, Y) X Y
+ ^ID(int A);
+ // Macro arguments included.
+ ^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2));
+
+ // Macro names inside other macros not included.
+ #define FOO BAR
+ #define BAR 1
+ int A = ^FOO;
+
+ // Macros from token concatenations not included.
+ #define CONCAT(X) X##A()
+ #define PREPEND(X) MACRO##X()
+ #define MACROA() 123
+ int B = ^CONCAT(MACRO);
+ int D = ^PREPEND(A)
+
+ // Macros included not from preamble not included.
+ #include "foo.inc"
+
+ #define assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); }
+
+ void test() {
+ // Includes macro expansions in arguments that are expressions
+ ^assert(0 <= ^BAR);
+ }
+ )cpp");
+ auto TU = TestTU::withCode(TestCase.code());
+ TU.HeaderCode = R"cpp(
+ #define ID(X) X
+ #define MACRO_EXP(X) ID(X)
+ MACRO_EXP(int B);
+ )cpp";
+ TU.AdditionalFiles["foo.inc"] = R"cpp(
+ int C = ID(1);
+ #define DEF 1
+ int D = DEF;
+ )cpp";
+ ParsedAST AST = TU.build();
+ const std::vector<SourceLocation> &MacroExpansionLocations =
+ AST.getMainFileExpansions();
+ std::vector<Position> MacroExpansionPositions;
+ for (const auto &L : MacroExpansionLocations)
+ MacroExpansionPositions.push_back(
+ sourceLocToPosition(AST.getSourceManager(), L));
+ EXPECT_EQ(MacroExpansionPositions, TestCase.points());
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Modified: clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp Wed Sep 4 02:46:06 2019
@@ -312,7 +312,7 @@ TEST(SourceCodeTests, SourceLocationInMa
}
}
-TEST(ClangdUnitTest, GetBeginningOfIdentifier) {
+TEST(SourceCodeTests, GetBeginningOfIdentifier) {
std::string Preamble = R"cpp(
struct Bar { int func(); };
#define MACRO(X) void f() { X; }
Modified: clang-tools-extra/trunk/clangd/unittests/SymbolInfoTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/SymbolInfoTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/SymbolInfoTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/SymbolInfoTests.cpp Wed Sep 4 02:46:06 2019
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
#include "Matchers.h"
+#include "ParsedAST.h"
#include "SyncAPI.h"
#include "TestFS.h"
#include "TestTU.h"
Modified: clang-tools-extra/trunk/clangd/unittests/TUSchedulerTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/TUSchedulerTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/TUSchedulerTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/TUSchedulerTests.cpp Wed Sep 4 02:46:06 2019
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
#include "Annotations.h"
-#include "ClangdUnit.h"
#include "Context.h"
#include "Diagnostics.h"
#include "Matchers.h"
+#include "ParsedAST.h"
#include "Path.h"
#include "Preamble.h"
#include "TUScheduler.h"
Modified: clang-tools-extra/trunk/clangd/unittests/TestTU.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/TestTU.h?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/TestTU.h (original)
+++ clang-tools-extra/trunk/clangd/unittests/TestTU.h Wed Sep 4 02:46:06 2019
@@ -17,7 +17,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTTU_H
#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTTU_H
-#include "ClangdUnit.h"
+#include "ParsedAST.h"
#include "Path.h"
#include "index/Index.h"
#include "llvm/ADT/StringMap.h"
Modified: clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp Wed Sep 4 02:46:06 2019
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
#include "Matchers.h"
+#include "ParsedAST.h"
#include "SyncAPI.h"
#include "TestFS.h"
#include "TestTU.h"
Modified: clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp?rev=370862&r1=370861&r2=370862&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp Wed Sep 4 02:46:06 2019
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
#include "Annotations.h"
-#include "ClangdUnit.h"
#include "Compiler.h"
#include "Matchers.h"
+#include "ParsedAST.h"
#include "Protocol.h"
#include "SyncAPI.h"
#include "TestFS.h"
More information about the cfe-commits
mailing list