Skip to content

Commit

Permalink
Bump to Clang 15
Browse files Browse the repository at this point in the history
  • Loading branch information
davidrohr committed Feb 28, 2023
1 parent 9b46b24 commit a22935e
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 65 deletions.
11 changes: 10 additions & 1 deletion ClangTidy.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyOptions.h"
#include "llvm/ADT/StringSet.h"
#include <memory>
#include <vector>

Expand Down Expand Up @@ -38,7 +39,7 @@ class ClangTidyASTConsumerFactory {

/// Returns an ASTConsumer that runs the specified clang-tidy checks.
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File);
createASTConsumer(clang::CompilerInstance &Compiler, StringRef File);

/// Get the list of enabled checks.
std::vector<std::string> getCheckNames();
Expand All @@ -57,6 +58,14 @@ class ClangTidyASTConsumerFactory {
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options,
bool AllowEnablingAnalyzerAlphaCheckers);

struct NamesAndOptions {
llvm::StringSet<> Names;
llvm::StringSet<> Options;
};

NamesAndOptions
getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers = true);

/// Returns the effective check-specific options.
///
/// The method configures ClangTidy with the specified \p Options and collects
Expand Down
28 changes: 16 additions & 12 deletions ClangTidyCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

namespace clang {

class CompilerInstance;
class SourceManager;

namespace tidy {
Expand Down Expand Up @@ -123,7 +122,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
/// Adds a diagnostic to report errors in the check's configuration.
DiagnosticBuilder
configurationDiag(StringRef Description,
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
DiagnosticIDs::Level Level = DiagnosticIDs::Warning) const;

/// Should store all options supported by this check with their
/// current values or default values for options that haven't been overridden.
Expand Down Expand Up @@ -156,30 +155,30 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
/// Reads the option with the check-local name \p LocalName from the
/// ``CheckOptions``. If the corresponding key is not present, return
/// ``None``.
llvm::Optional<std::string> get(StringRef LocalName) const;
llvm::Optional<StringRef> get(StringRef LocalName) const;

/// Read a named option from the ``Context``.
///
/// Reads the option with the check-local name \p LocalName from the
/// ``CheckOptions``. If the corresponding key is not present, returns
/// \p Default.
std::string get(StringRef LocalName, StringRef Default) const;
StringRef get(StringRef LocalName, StringRef Default) const;

/// Read a named option from the ``Context``.
///
/// Reads the option with the check-local name \p LocalName from local or
/// global ``CheckOptions``. Gets local option first. If local is not
/// present, falls back to get global option. If global option is not
/// present either, return ``None``.
llvm::Optional<std::string> getLocalOrGlobal(StringRef LocalName) const;
llvm::Optional<StringRef> getLocalOrGlobal(StringRef LocalName) const;

/// Read a named option from the ``Context``.
///
/// Reads the option with the check-local name \p LocalName from local or
/// global ``CheckOptions``. Gets local option first. If local is not
/// present, falls back to get global option. If global option is not
/// present either, returns \p Default.
std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const;
StringRef getLocalOrGlobal(StringRef LocalName, StringRef Default) const;

/// Read a named option from the ``Context`` and parse it as an
/// integral type ``T``.
Expand All @@ -193,7 +192,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
template <typename T>
std::enable_if_t<std::is_integral<T>::value, llvm::Optional<T>>
get(StringRef LocalName) const {
if (llvm::Optional<std::string> Value = get(LocalName)) {
if (llvm::Optional<StringRef> Value = get(LocalName)) {
T Result{};
if (!StringRef(*Value).getAsInteger(10, Result))
return Result;
Expand All @@ -214,7 +213,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
template <typename T>
std::enable_if_t<std::is_integral<T>::value, T> get(StringRef LocalName,
T Default) const {
return get<T>(LocalName).getValueOr(Default);
return get<T>(LocalName).value_or(Default);
}

/// Read a named option from the ``Context`` and parse it as an
Expand All @@ -230,7 +229,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
template <typename T>
std::enable_if_t<std::is_integral<T>::value, llvm::Optional<T>>
getLocalOrGlobal(StringRef LocalName) const {
llvm::Optional<std::string> ValueOr = get(LocalName);
llvm::Optional<StringRef> ValueOr = get(LocalName);
bool IsGlobal = false;
if (!ValueOr) {
IsGlobal = true;
Expand Down Expand Up @@ -259,7 +258,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
template <typename T>
std::enable_if_t<std::is_integral<T>::value, T>
getLocalOrGlobal(StringRef LocalName, T Default) const {
return getLocalOrGlobal<T>(LocalName).getValueOr(Default);
return getLocalOrGlobal<T>(LocalName).value_or(Default);
}

/// Read a named option from the ``Context`` and parse it as an
Expand Down Expand Up @@ -298,7 +297,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
template <typename T>
std::enable_if_t<std::is_enum<T>::value, T>
get(StringRef LocalName, T Default, bool IgnoreCase = false) const {
return get<T>(LocalName, IgnoreCase).getValueOr(Default);
return get<T>(LocalName, IgnoreCase).value_or(Default);
}

/// Read a named option from the ``Context`` and parse it as an
Expand Down Expand Up @@ -340,7 +339,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
std::enable_if_t<std::is_enum<T>::value, T>
getLocalOrGlobal(StringRef LocalName, T Default,
bool IgnoreCase = false) const {
return getLocalOrGlobal<T>(LocalName, IgnoreCase).getValueOr(Default);
return getLocalOrGlobal<T>(LocalName, IgnoreCase).value_or(Default);
}

/// Stores an option with the check-local name \p LocalName with
Expand Down Expand Up @@ -418,6 +417,11 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
StringRef getCurrentMainFile() const { return Context->getCurrentFile(); }
/// Returns the language options from the context.
const LangOptions &getLangOpts() const { return Context->getLangOpts(); }
/// Returns true when the check is run in a use case when only 1 fix will be
/// applied at a time.
bool areDiagsSelfContained() const {
return Context->areDiagsSelfContained();
}
};

/// Read a named option from the ``Context`` and parse it as a bool.
Expand Down
88 changes: 52 additions & 36 deletions ClangTidyDiagnosticConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,20 @@

#include "ClangTidyOptions.h"
#include "ClangTidyProfiling.h"
#include "NoLintDirectiveHandler.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Tooling/Core/Diagnostic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Regex.h"

namespace clang {

class ASTContext;
class CompilerInstance;
class SourceManager;
namespace ast_matchers {
class MatchFinder;
}
namespace tooling {
class CompilationDatabase;
}

namespace tidy {
class CachedGlobList;

/// A detected error complete with information to display diagnostic and
/// automatic fix.
Expand All @@ -45,18 +41,13 @@ struct ClangTidyError : tooling::Diagnostic {
std::vector<std::string> EnabledDiagnosticAliases;
};

/// Contains displayed and ignored diagnostic counters for a ClangTidy
/// run.
/// Contains displayed and ignored diagnostic counters for a ClangTidy run.
struct ClangTidyStats {
ClangTidyStats()
: ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
ErrorsIgnoredNonUserCode(0), ErrorsIgnoredLineFilter(0) {}

unsigned ErrorsDisplayed;
unsigned ErrorsIgnoredCheckFilter;
unsigned ErrorsIgnoredNOLINT;
unsigned ErrorsIgnoredNonUserCode;
unsigned ErrorsIgnoredLineFilter;
unsigned ErrorsDisplayed = 0;
unsigned ErrorsIgnoredCheckFilter = 0;
unsigned ErrorsIgnoredNOLINT = 0;
unsigned ErrorsIgnoredNonUserCode = 0;
unsigned ErrorsIgnoredLineFilter = 0;

unsigned errorsIgnored() const {
return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter +
Expand Down Expand Up @@ -99,11 +90,33 @@ class ClangTidyContext {
DiagnosticBuilder diag(StringRef CheckName, StringRef Message,
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);

DiagnosticBuilder diag(const tooling::Diagnostic &Error);

/// Report any errors to do with reading the configuration using this method.
DiagnosticBuilder
configurationDiag(StringRef Message,
DiagnosticIDs::Level Level = DiagnosticIDs::Warning);

/// Check whether a given diagnostic should be suppressed due to the presence
/// of a "NOLINT" suppression comment.
/// This is exposed so that other tools that present clang-tidy diagnostics
/// (such as clangd) can respect the same suppression rules as clang-tidy.
/// This does not handle suppression of notes following a suppressed
/// diagnostic; that is left to the caller as it requires maintaining state in
/// between calls to this function.
/// If any NOLINT is malformed, e.g. a BEGIN without a subsequent END, output
/// \param NoLintErrors will return an error about it.
/// If \param AllowIO is false, the function does not attempt to read source
/// files from disk which are not already mapped into memory; such files are
/// treated as not containing a suppression comment.
/// \param EnableNoLintBlocks controls whether to honor NOLINTBEGIN/NOLINTEND
/// blocks; if false, only considers line-level disabling.
bool
shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info,
SmallVectorImpl<tooling::Diagnostic> &NoLintErrors,
bool AllowIO = true, bool EnableNoLintBlocks = true);

/// Sets the \c SourceManager of the used \c DiagnosticsEngine.
///
/// This is called from the \c ClangTidyCheck base class.
Expand Down Expand Up @@ -165,7 +178,7 @@ class ClangTidyContext {
}

/// Returns build directory of the current translation unit.
const std::string &getCurrentBuildDirectory() {
const std::string &getCurrentBuildDirectory() const {
return CurrentBuildDirectory;
}

Expand All @@ -175,6 +188,10 @@ class ClangTidyContext {
return AllowEnablingAnalyzerAlphaCheckers;
}

void setSelfContainedDiags(bool Value) { SelfContainedDiags = Value; }

bool areDiagsSelfContained() const { return SelfContainedDiags; }

using DiagLevelAndFormatString = std::pair<DiagnosticIDs::Level, std::string>;
DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID,
SourceLocation Loc) {
Expand All @@ -185,6 +202,11 @@ class ClangTidyContext {
DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID)));
}

void setOptionsCollector(llvm::StringSet<> *Collector) {
OptionsCollector = Collector;
}
llvm::StringSet<> *getOptionsCollector() const { return OptionsCollector; }

private:
// Writes to Stats.
friend class ClangTidyDiagnosticConsumer;
Expand All @@ -194,7 +216,7 @@ class ClangTidyContext {

std::string CurrentFile;
ClangTidyOptions CurrentOptions;
class CachedGlobList;

std::unique_ptr<CachedGlobList> CheckFilter;
std::unique_ptr<CachedGlobList> WarningAsErrorFilter;

Expand All @@ -210,21 +232,12 @@ class ClangTidyContext {
std::string ProfilePrefix;

bool AllowEnablingAnalyzerAlphaCheckers;
};

/// Check whether a given diagnostic should be suppressed due to the presence
/// of a "NOLINT" suppression comment.
/// This is exposed so that other tools that present clang-tidy diagnostics
/// (such as clangd) can respect the same suppression rules as clang-tidy.
/// This does not handle suppression of notes following a suppressed diagnostic;
/// that is left to the caller is it requires maintaining state in between calls
/// to this function.
/// If `AllowIO` is false, the function does not attempt to read source files
/// from disk which are not already mapped into memory; such files are treated
/// as not containing a suppression comment.
bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info, ClangTidyContext &Context,
bool AllowIO = true);
bool SelfContainedDiags;

NoLintDirectiveHandler NoLintHandler;
llvm::StringSet<> *OptionsCollector = nullptr;
};

/// Gets the Fix attached to \p Diagnostic.
/// If there isn't a Fix attached to the diagnostic and \p AnyFix is true, Check
Expand All @@ -235,15 +248,17 @@ getFixIt(const tooling::Diagnostic &Diagnostic, bool AnyFix);

/// A diagnostic consumer that turns each \c Diagnostic into a
/// \c SourceManager-independent \c ClangTidyError.
//
// FIXME: If we move away from unit-tests, this can be moved to a private
// implementation file.
class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
public:
/// \param EnableNolintBlocks Enables diagnostic-disabling inside blocks of
/// code, delimited by NOLINTBEGIN and NOLINTEND.
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx,
DiagnosticsEngine *ExternalDiagEngine = nullptr,
bool RemoveIncompatibleErrors = true,
bool GetFixesFromNotes = false);
bool GetFixesFromNotes = false,
bool EnableNolintBlocks = true);

// FIXME: The concept of converting between FixItHints and Replacements is
// more generic and should be pulled out into a more useful Diagnostics
Expand Down Expand Up @@ -274,6 +289,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
DiagnosticsEngine *ExternalDiagEngine;
bool RemoveIncompatibleErrors;
bool GetFixesFromNotes;
bool EnableNolintBlocks;
std::vector<ClangTidyError> Errors;
std::unique_ptr<llvm::Regex> HeaderFilter;
bool LastErrorRelatesToUserCode;
Expand Down
4 changes: 4 additions & 0 deletions ClangTidyModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class ClangTidyCheckFactories {
std::vector<std::unique_ptr<ClangTidyCheck>>
createChecks(ClangTidyContext *Context);

/// Create instances of checks that are enabled for the current Language.
std::vector<std::unique_ptr<ClangTidyCheck>>
createChecksForLanguage(ClangTidyContext *Context);

typedef llvm::StringMap<CheckFactory> FactoryMap;
FactoryMap::const_iterator begin() const { return Factories.begin(); }
FactoryMap::const_iterator end() const { return Factories.end(); }
Expand Down
6 changes: 3 additions & 3 deletions ClangTidyOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ struct ClangTidyOptions {

std::string Value;
/// Priority stores relative precedence of the value loaded from config
/// files to disambigute local vs global value from different levels.
/// files to disambiguate local vs global value from different levels.
unsigned Priority;
};
typedef std::pair<std::string, std::string> StringPair;
Expand All @@ -129,8 +129,8 @@ struct ClangTidyOptions {
/// and using a FileOptionsProvider, it will take a configuration file in the
/// parent directory (if any exists) and apply this config file on top of the
/// parent one. IF true and using a ConfigOptionsProvider, it will apply this
/// config on top of any configuation file it finds in the directory using the
/// same logic as FileOptionsProvider. If false or missing, only this
/// config on top of any configuration file it finds in the directory using
/// the same logic as FileOptionsProvider. If false or missing, only this
/// configuration file will be used.
llvm::Optional<bool> InheritParentConfig;

Expand Down
Loading

0 comments on commit a22935e

Please sign in to comment.