mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 03:25:54 -04:00

Summary: Computing lazily leads to crashes. In particular, computing scopes may produce diagnostics (from inside template instantiations) and we currently do it when processing another diagnostic, which leads to crashes. Moreover, we remember and access 'Scope*' when computing scopes. This might lead to invalid memory access if the Scope is deleted by the time we run the delayed computation. We did not actually construct an example when this happens, though. From the VCS and review history, it seems the optimization was introduced in the initial version without a mention of any performance benchmarks justifying the performance gains. This led me to a conclusion that the optimization was premature, so removing it to avoid crashes seems like the right trade-off at that point. Reviewers: sammccall Reviewed By: sammccall Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65796 llvm-svn: 368019
99 lines
3.8 KiB
C++
99 lines
3.8 KiB
C++
//===--- IncludeFixer.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_INCLUDE_FIXER_H
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
|
|
|
|
#include "Diagnostics.h"
|
|
#include "Headers.h"
|
|
#include "index/Index.h"
|
|
#include "index/Symbol.h"
|
|
#include "clang/AST/Type.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include "clang/Sema/ExternalSemaSource.h"
|
|
#include "clang/Sema/Sema.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include <memory>
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
|
|
/// Attempts to recover from error diagnostics by suggesting include insertion
|
|
/// fixes. For example, member access into incomplete type can be fixes by
|
|
/// include headers with the definition.
|
|
class IncludeFixer {
|
|
public:
|
|
IncludeFixer(llvm::StringRef File, std::shared_ptr<IncludeInserter> Inserter,
|
|
const SymbolIndex &Index, unsigned IndexRequestLimit)
|
|
: File(File), Inserter(std::move(Inserter)), Index(Index),
|
|
IndexRequestLimit(IndexRequestLimit) {}
|
|
|
|
/// Returns include insertions that can potentially recover the diagnostic.
|
|
std::vector<Fix> fix(DiagnosticsEngine::Level DiagLevel,
|
|
const clang::Diagnostic &Info) const;
|
|
|
|
/// Returns an ExternalSemaSource that records failed name lookups in Sema.
|
|
/// This allows IncludeFixer to suggest inserting headers that define those
|
|
/// names.
|
|
llvm::IntrusiveRefCntPtr<ExternalSemaSource> unresolvedNameRecorder();
|
|
|
|
private:
|
|
/// Attempts to recover diagnostic caused by an incomplete type \p T.
|
|
std::vector<Fix> fixIncompleteType(const Type &T) const;
|
|
|
|
/// Generates header insertion fixes for all symbols. Fixes are deduplicated.
|
|
std::vector<Fix> fixesForSymbols(const SymbolSlab &Syms) const;
|
|
|
|
struct UnresolvedName {
|
|
std::string Name; // E.g. "X" in foo::X.
|
|
SourceLocation Loc; // Start location of the unresolved name.
|
|
std::vector<std::string> Scopes; // Namespace scopes we should search in.
|
|
};
|
|
|
|
/// Records the last unresolved name seen by Sema.
|
|
class UnresolvedNameRecorder;
|
|
|
|
/// Attempts to fix the unresolved name associated with the current
|
|
/// diagnostic. We assume a diagnostic is caused by a unresolved name when
|
|
/// they have the same source location and the unresolved name is the last
|
|
/// one we've seen during the Sema run.
|
|
std::vector<Fix> fixUnresolvedName() const;
|
|
|
|
std::string File;
|
|
std::shared_ptr<IncludeInserter> Inserter;
|
|
const SymbolIndex &Index;
|
|
const unsigned IndexRequestLimit; // Make at most 5 index requests.
|
|
mutable unsigned IndexRequestCount = 0;
|
|
|
|
// These collect the last unresolved name so that we can associate it with the
|
|
// diagnostic.
|
|
llvm::Optional<UnresolvedName> LastUnresolvedName;
|
|
|
|
// There can be multiple diagnostics that are caused by the same unresolved
|
|
// name or incomplete type in one parse, especially when code is
|
|
// copy-and-pasted without #includes. We cache the index results based on
|
|
// index requests.
|
|
mutable llvm::StringMap<SymbolSlab> FuzzyFindCache;
|
|
mutable llvm::DenseMap<SymbolID, SymbolSlab> LookupCache;
|
|
// Returns None if the number of index requests has reached the limit.
|
|
llvm::Optional<const SymbolSlab *>
|
|
fuzzyFindCached(const FuzzyFindRequest &Req) const;
|
|
llvm::Optional<const SymbolSlab *> lookupCached(const SymbolID &ID) const;
|
|
};
|
|
|
|
} // namespace clangd
|
|
} // namespace clang
|
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INCLUDE_FIXER_H
|