From 7bd8706d96405f6b21a52f995bfafac3876fc6da Mon Sep 17 00:00:00 2001 From: Dario Berzano Date: Thu, 18 Apr 2019 14:08:16 +0200 Subject: [PATCH 01/20] Make it Python 3-compatible (#29) --- tool/run_O2CodeChecker.py | 16 ++++++++++------ utility/ThinCompilationsDatabase.py | 18 +++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/tool/run_O2CodeChecker.py b/tool/run_O2CodeChecker.py index 3ca2a42..2c57d5d 100755 --- a/tool/run_O2CodeChecker.py +++ b/tool/run_O2CodeChecker.py @@ -34,11 +34,15 @@ http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html """ +from __future__ import print_function import argparse import json import multiprocessing import os -import Queue +try: + import Queue +except ImportError: + import queue as Queue import re import shutil import subprocess @@ -52,7 +56,7 @@ def find_compilation_database(path): result = './' while not os.path.isfile(os.path.join(result, path)): if os.path.realpath(result) == '/': - print 'Error: could not find compilation database.' + print('Error: could not find compilation database.') sys.exit(1) result += '../' return os.path.realpath(result) @@ -158,9 +162,9 @@ def main(): if args.checks: invocation.append('-checks=' + args.checks) invocation.append('-') - print subprocess.check_output(invocation) + print(subprocess.check_output(invocation)) except: - print >>sys.stderr, "Unable to run clang-tidy." + print("Unable to run clang-tidy.") sys.exit(1) # Load the database and extract all files. @@ -198,13 +202,13 @@ def main(): except KeyboardInterrupt: # This is a sad hack. Unfortunately subprocess goes # bonkers with ctrl-c and we start forking merrily. - print '\nCtrl-C detected, goodbye.' + print('\nCtrl-C detected, goodbye.') if args.fix: shutil.rmtree(tmpdir) os.kill(0, 9) if args.fix: - print 'Applying fixes ...' + print('Applying fixes ...') apply_fixes(args, tmpdir) if __name__ == '__main__': diff --git a/utility/ThinCompilationsDatabase.py b/utility/ThinCompilationsDatabase.py index 8fccb52..60cb6df 100755 --- a/utility/ThinCompilationsDatabase.py +++ b/utility/ThinCompilationsDatabase.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # A python script with the goal # to transform a (large) compilations database @@ -9,13 +9,17 @@ # # First version: Sandro Wenzel (June 2017) +from __future__ import print_function import argparse import json import os import subprocess import re # these are for queue syncronized multi-threading -import Queue +try: + import Queue +except ImportError: + import queue as Queue import threading import multiprocessing import time @@ -45,7 +49,7 @@ def parseArgs(): def verboseLog(string, level=0): global verbosity if verbosity > 0: - print string + print(string) def getListOfChangedFiles(colonseparatedfilepaths): """ processes the argument '-use-files' and returns a python list of filenames """ @@ -128,8 +132,8 @@ def processItem(keepalive, changedheaderlist, queue, outqueue): def reportProgress(keepalive, queue, q2): while len(keepalive)>0: - print "input queue has size " + str(queue.qsize()) - print "output queue has size " + str(q2.qsize()) + print("input queue has size " + str(queue.qsize())) + print("output queue has size " + str(q2.qsize())) time.sleep(1) #custom function to remove duplicates and return a new list @@ -173,11 +177,11 @@ def main(): #setup the isInvalid (closure) function isInvalid=makeInvalidClosure(args) - #open the compilations database + #open the compilations database try: file=open('compile_commands.json').read() except IOError: - print "Problem opening the compilation database (file not found)" + print("Problem opening the compilation database (file not found)") sys.exit(1) #convert json to dict From aa20be5fee592c54ae7f9ead4e714b34731f0392 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse Date: Mon, 29 Apr 2019 13:39:30 +0200 Subject: [PATCH 02/20] Make code checker python3 compatible --- utility/ThinCompilationsDatabase.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utility/ThinCompilationsDatabase.py b/utility/ThinCompilationsDatabase.py index 60cb6df..7da9657 100755 --- a/utility/ThinCompilationsDatabase.py +++ b/utility/ThinCompilationsDatabase.py @@ -98,7 +98,11 @@ def modifyCompileCommand(command): def matchesHeader(line, header): expression=".*\.h" # make this more efficient by compiling the expression - return re.match(expression, line) is not None + try: + return re.match(expression, line.decode("utf-8")) is not None + except: + return re.match(expression, line) is not None + def queryListOfHeaders(command): proc=subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) From 35a35e029a80d86d96f5cf66dcf5d1075ece1b9d Mon Sep 17 00:00:00 2001 From: Dario Berzano Date: Mon, 6 May 2019 10:51:33 +0200 Subject: [PATCH 03/20] More Python 3 fixes (O2-636) (#32) --- utility/ThinCompilationsDatabase.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utility/ThinCompilationsDatabase.py b/utility/ThinCompilationsDatabase.py index 7da9657..e83b21a 100755 --- a/utility/ThinCompilationsDatabase.py +++ b/utility/ThinCompilationsDatabase.py @@ -108,8 +108,11 @@ def queryListOfHeaders(command): proc=subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) headerlist=[] for line in proc.stdout: - if matchesHeader(line.strip(), headerlist): - headerlist.append(line.strip()) + line = line.strip() + if matchesHeader(line, headerlist): + if isinstance(line, bytes): + line = line.decode('utf-8') + headerlist.append(line) return headerlist # service that processes one item in the queue From 98c0ca0449fd203124668130dc971971b972b3bc Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 26 Apr 2019 10:45:18 +0200 Subject: [PATCH 04/20] Adapt to clang 8 --- ClangTidy.h | 18 ++++++++++-------- ClangTidyDiagnosticConsumer.h | 35 ++++++++++++----------------------- ClangTidyOptions.h | 15 ++++++++------- aliceO2/SizeofCheck.cpp | 4 ++-- reporting/VirtFuncLister.cpp | 6 +++--- tool/ClangTidyMain.cpp | 8 ++++---- 6 files changed, 39 insertions(+), 47 deletions(-) diff --git a/ClangTidy.h b/ClangTidy.h index 0ea9a70..dc11200 100644 --- a/ClangTidy.h +++ b/ClangTidy.h @@ -230,12 +230,13 @@ getCheckOptions(const ClangTidyOptions &Options, /// \param StoreCheckProfile If provided, and EnableCheckProfile is true, /// the profile will not be output to stderr, but will instead be stored /// as a JSON file in the specified directory. -void runClangTidy(clang::tidy::ClangTidyContext &Context, - const tooling::CompilationDatabase &Compilations, - ArrayRef InputFiles, - llvm::IntrusiveRefCntPtr BaseFS, - bool EnableCheckProfile = false, - llvm::StringRef StoreCheckProfile = StringRef()); +std::vector +runClangTidy(clang::tidy::ClangTidyContext &Context, + const tooling::CompilationDatabase &Compilations, + ArrayRef InputFiles, + llvm::IntrusiveRefCntPtr BaseFS, + bool EnableCheckProfile = false, + llvm::StringRef StoreCheckProfile = StringRef()); // FIXME: This interface will need to be significantly extended to be useful. // FIXME: Implement confidence levels for displaying/fixing errors. @@ -243,9 +244,10 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context, /// \brief Displays the found \p Errors to the users. If \p Fix is true, \p /// Errors containing fixes are automatically applied and reformatted. If no /// clang-format configuration file is found, the given \P FormatStyle is used. -void handleErrors(ClangTidyContext &Context, bool Fix, +void handleErrors(llvm::ArrayRef Errors, + ClangTidyContext &Context, bool Fix, unsigned &WarningsAsErrorsCount, - llvm::IntrusiveRefCntPtr BaseFS); + llvm::IntrusiveRefCntPtr BaseFS); /// \brief Serializes replacements into YAML and writes them to the specified /// output stream. diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index ae25013..a868203 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -102,6 +102,12 @@ class ClangTidyContext { /// \brief Initializes \c ClangTidyContext instance. ClangTidyContext(std::unique_ptr OptionsProvider, bool AllowEnablingAnalyzerAlphaCheckers = false); + /// Sets the DiagnosticsEngine that diag() will emit diagnostics to. + // FIXME: this is required initialization, and should be a constructor param. + // Fix the context -> diag engine -> consumer -> context initialization cycle. + void setDiagnosticsEngine(DiagnosticsEngine *DiagEngine) { + this->DiagEngine = DiagEngine; + } ~ClangTidyContext(); @@ -160,12 +166,6 @@ class ClangTidyContext { /// counters. const ClangTidyStats &getStats() const { return Stats; } - /// \brief Returns all collected errors. - ArrayRef getErrors() const { return Errors; } - - /// \brief Clears collected errors. - void clearErrors() { Errors.clear(); } - /// \brief Control profile collection in clang-tidy. void setEnableProfiling(bool Profile); bool getEnableProfiling() const { return Profile; } @@ -192,18 +192,9 @@ class ClangTidyContext { } private: - // Calls setDiagnosticsEngine() and storeError(). + // Writes to Stats. friend class ClangTidyDiagnosticConsumer; - friend class ClangTidyPluginAction; - - /// \brief Sets the \c DiagnosticsEngine so that Diagnostics can be generated - /// correctly. - void setDiagnosticsEngine(DiagnosticsEngine *Engine); - /// \brief Store an \p Error. - void storeError(const ClangTidyError &Error); - - std::vector Errors; DiagnosticsEngine *DiagEngine; std::unique_ptr OptionsProvider; @@ -243,13 +234,12 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override; - /// \brief Flushes the internal diagnostics buffer to the ClangTidyContext. - void finish() override; + // Retrieve the diagnostics that were captured. + std::vector take(); private: void finalizeLastError(); - - void removeIncompatibleErrors(SmallVectorImpl &Errors) const; + void removeIncompatibleErrors(); /// \brief Returns the \c HeaderFilter constructed for the options set in the /// context. @@ -257,13 +247,12 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter /// according to the diagnostic \p Location. - void checkFilters(SourceLocation Location); + void checkFilters(SourceLocation Location, const SourceManager& Sources); bool passesLineFilter(StringRef FileName, unsigned LineNumber) const; ClangTidyContext &Context; bool RemoveIncompatibleErrors; - std::unique_ptr Diags; - SmallVector Errors; + std::vector Errors; std::unique_ptr HeaderFilter; bool LastErrorRelatesToUserCode; bool LastErrorPassesLineFilter; diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index b2a4ce4..1a75354 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -10,12 +10,12 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/ErrorOr.h" -#include "clang/Basic/VirtualFileSystem.h" +#include "llvm/Support/VirtualFileSystem.h" #include #include #include @@ -218,10 +218,11 @@ class FileOptionsProvider : public DefaultOptionsProvider { /// /// If any of the \param OverrideOptions fields are set, they will override /// whatever options are read from the configuration file. - FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - llvm::IntrusiveRefCntPtr FS = nullptr); + FileOptionsProvider( + const ClangTidyGlobalOptions &GlobalOptions, + const ClangTidyOptions &DefaultOptions, + const ClangTidyOptions &OverrideOptions, + llvm::IntrusiveRefCntPtr FS = nullptr); /// \brief Initializes the \c FileOptionsProvider instance with a custom set /// of configuration file handlers. @@ -255,7 +256,7 @@ class FileOptionsProvider : public DefaultOptionsProvider { llvm::StringMap CachedOptions; ClangTidyOptions OverrideOptions; ConfigFileHandlers ConfigHandlers; - llvm::IntrusiveRefCntPtr FS; + llvm::IntrusiveRefCntPtr FS; }; /// \brief Parses LineFilter from JSON and stores it to the \p Options. diff --git a/aliceO2/SizeofCheck.cpp b/aliceO2/SizeofCheck.cpp index bd2c24e..da8d2e0 100644 --- a/aliceO2/SizeofCheck.cpp +++ b/aliceO2/SizeofCheck.cpp @@ -31,7 +31,7 @@ void SizeofCheck::check(const MatchFinder::MatchResult &Result) { // is argument of sizeof a Type? if (Expr->isArgumentType()) { - diag(Expr->getLocStart(), "consider using sizeof() on instance instead on direct type"); + diag(Expr->getBeginLoc(), "consider using sizeof() on instance instead on direct type"); return; } @@ -41,7 +41,7 @@ void SizeofCheck::check(const MatchFinder::MatchResult &Result) { } // no parens -> issue warning - diag(Expr->getLocStart(), "consider using parens () for arguments to sizeof"); + diag(Expr->getBeginLoc(), "consider using parens () for arguments to sizeof"); } } // namespace aliceO2 diff --git a/reporting/VirtFuncLister.cpp b/reporting/VirtFuncLister.cpp index deeee11..9fdb102 100644 --- a/reporting/VirtFuncLister.cpp +++ b/reporting/VirtFuncLister.cpp @@ -47,7 +47,7 @@ void VirtFuncLister::check(const MatchFinder::MatchResult &Result) { auto enditer = MatchedDecl->end_overridden_methods(); if (iter == enditer) { - SourceLocation loc = MatchedDecl->getLocStart();//getLocation(); + SourceLocation loc = MatchedDecl->getBeginLoc();//getLocation(); loc.dump(SM); llvm::errs() << "VIRTUAL-START-DECLARATION \n"; } else { @@ -69,10 +69,10 @@ void VirtFuncLister::check(const MatchFinder::MatchResult &Result) { enditer = (*iter)->end_overridden_methods(); iter = (*iter)->begin_overridden_methods(); } - SourceLocation loc = (*lastiter)->getLocStart();//getLocation(); + SourceLocation loc = (*lastiter)->getBeginLoc();//getLocation(); loc.dump(SM); llvm::errs() << " OVERRIDEN-AT "; - loc = MatchedDecl->getLocStart();//getLocation(); + loc = MatchedDecl->getBeginLoc();//getLocation(); loc.dump(SM); llvm::errs() << "\n"; } diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index 11a04f7..562aef5 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -421,9 +421,9 @@ static int clangTidyMain(int argc, const char **argv) { ClangTidyContext Context(std::move(OwningOptionsProvider), AllowEnablingAnalyzerAlphaCheckers); - runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS, - EnableCheckProfile, ProfilePrefix); - ArrayRef Errors = Context.getErrors(); + std::vector Errors = + runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS, + EnableCheckProfile, ProfilePrefix); bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) { return E.DiagLevel == ClangTidyError::Error; }) != Errors.end(); @@ -433,7 +433,7 @@ static int clangTidyMain(int argc, const char **argv) { unsigned WErrorCount = 0; // -fix-errors implies -fix. - handleErrors(Context, (FixErrors || Fix) && !DisableFixes, WErrorCount, + handleErrors(Errors, Context, (FixErrors || Fix) && !DisableFixes, WErrorCount, BaseFS); if (!ExportFixes.empty() && !Errors.empty()) { From c994ce7defde62189fa098425d55a85f1fb26f98 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 3 Dec 2019 22:43:16 +0100 Subject: [PATCH 05/20] Adapt to clang 9 --- ClangTidy.h | 177 ++----------------------------- ClangTidyCheck.h | 194 ++++++++++++++++++++++++++++++++++ ClangTidyDiagnosticConsumer.h | 41 +++++-- ClangTidyModule.h | 7 +- ClangTidyModuleRegistry.h | 7 +- ClangTidyOptions.h | 7 +- ClangTidyProfiling.h | 7 +- tool/ClangTidyMain.cpp | 35 +++++- 8 files changed, 282 insertions(+), 193 deletions(-) create mode 100644 ClangTidyCheck.h diff --git a/ClangTidy.h b/ClangTidy.h index dc11200..a9433f6 100644 --- a/ClangTidy.h +++ b/ClangTidy.h @@ -1,25 +1,19 @@ //===--- ClangTidy.h - clang-tidy -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_CLANG_TIDY_CLANGTIDY_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H +#include "ClangTidyCheck.h" #include "ClangTidyDiagnosticConsumer.h" #include "ClangTidyOptions.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Tooling/Refactoring.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" #include -#include #include namespace clang { @@ -31,167 +25,13 @@ class CompilationDatabase; namespace tidy { -/// \brief Provides access to the ``ClangTidyCheck`` options via check-local -/// names. -/// -/// Methods of this class prepend ``CheckName + "."`` to translate check-local -/// option names to global option names. -class OptionsView { -public: - /// \brief Initializes the instance using \p CheckName + "." as a prefix. - OptionsView(StringRef CheckName, - const ClangTidyOptions::OptionMap &CheckOptions); - - /// \brief 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; - - /// \brief 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 Default. - std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const; - - /// \brief Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, returns - /// \p Default. - template - typename std::enable_if::value, T>::type - get(StringRef LocalName, T Default) const { - std::string Value = get(LocalName, ""); - T Result = Default; - if (!Value.empty()) - StringRef(Value).getAsInteger(10, Result); - return Result; - } - - /// \brief Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// 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 Default. - template - typename std::enable_if::value, T>::type - getLocalOrGlobal(StringRef LocalName, T Default) const { - std::string Value = getLocalOrGlobal(LocalName, ""); - T Result = Default; - if (!Value.empty()) - StringRef(Value).getAsInteger(10, Result); - return Result; - } - - /// \brief Stores an option with the check-local name \p LocalName with string - /// value \p Value to \p Options. - void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - StringRef Value) const; - - /// \brief Stores an option with the check-local name \p LocalName with - /// ``int64_t`` value \p Value to \p Options. - void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - int64_t Value) const; - -private: - std::string NamePrefix; - const ClangTidyOptions::OptionMap &CheckOptions; -}; - -/// \brief Base class for all clang-tidy checks. -/// -/// To implement a ``ClangTidyCheck``, write a subclass and override some of the -/// base class's methods. E.g. to implement a check that validates namespace -/// declarations, override ``registerMatchers``: -/// -/// ~~~{.cpp} -/// void registerMatchers(ast_matchers::MatchFinder *Finder) override { -/// Finder->addMatcher(namespaceDecl().bind("namespace"), this); -/// } -/// ~~~ -/// -/// and then override ``check(const MatchResult &Result)`` to do the actual -/// check for each match. -/// -/// A new ``ClangTidyCheck`` instance is created per translation unit. -/// -/// FIXME: Figure out whether carrying information from one TU to another is -/// useful/necessary. -class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { -public: - /// \brief Initializes the check with \p CheckName and \p Context. - /// - /// Derived classes must implement the constructor with this signature or - /// delegate it. If a check needs to read options, it can do this in the - /// constructor using the Options.get() methods below. - ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context) - : CheckName(CheckName), Context(Context), - Options(CheckName, Context->getOptions().CheckOptions) { - assert(Context != nullptr); - assert(!CheckName.empty()); - } - - /// \brief Override this to register ``PPCallbacks`` with ``Compiler``. - /// - /// This should be used for clang-tidy checks that analyze preprocessor- - /// dependent properties, e.g. the order of include directives. - virtual void registerPPCallbacks(CompilerInstance &Compiler) {} - - /// \brief Override this to register AST matchers with \p Finder. - /// - /// This should be used by clang-tidy checks that analyze code properties that - /// dependent on AST knowledge. - /// - /// You can register as many matchers as necessary with \p Finder. Usually, - /// "this" will be used as callback, but you can also specify other callback - /// classes. Thereby, different matchers can trigger different callbacks. - /// - /// If you need to merge information between the different matchers, you can - /// store these as members of the derived class. However, note that all - /// matches occur in the order of the AST traversal. - virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {} - - /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual - /// work in here. - virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} - - /// \brief Add a diagnostic with the check's name. - DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, - DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - - /// \brief Should store all options supported by this check with their - /// current values or default values for options that haven't been overridden. - /// - /// The check should use ``Options.store()`` to store each option it supports - /// whether it has the default value or it has been overridden. - virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {} - -private: - void run(const ast_matchers::MatchFinder::MatchResult &Result) override; - StringRef getID() const override { return CheckName; } - std::string CheckName; - ClangTidyContext *Context; - -protected: - OptionsView Options; - /// \brief Returns the main file name of the current translation unit. - StringRef getCurrentMainFile() const { return Context->getCurrentFile(); } - /// \brief Returns the language options from the context. - LangOptions getLangOpts() const { return Context->getLangOpts(); } -}; - class ClangTidyCheckFactories; class ClangTidyASTConsumerFactory { public: - ClangTidyASTConsumerFactory(ClangTidyContext &Context); + ClangTidyASTConsumerFactory( + ClangTidyContext &Context, + IntrusiveRefCntPtr OverlayFS = nullptr); /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks. std::unique_ptr @@ -205,6 +45,7 @@ class ClangTidyASTConsumerFactory { private: ClangTidyContext &Context; + IntrusiveRefCntPtr OverlayFS; std::unique_ptr CheckFactories; }; @@ -234,7 +75,7 @@ std::vector runClangTidy(clang::tidy::ClangTidyContext &Context, const tooling::CompilationDatabase &Compilations, ArrayRef InputFiles, - llvm::IntrusiveRefCntPtr BaseFS, + llvm::IntrusiveRefCntPtr BaseFS, bool EnableCheckProfile = false, llvm::StringRef StoreCheckProfile = StringRef()); diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h new file mode 100644 index 0000000..3064a41 --- /dev/null +++ b/ClangTidyCheck.h @@ -0,0 +1,194 @@ +//===--- ClangTidyCheck.h - clang-tidy --------------------------*- 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_CLANG_TIDY_CLANGTIDYCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H + +#include "ClangTidyDiagnosticConsumer.h" +#include "ClangTidyOptions.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +#include + +namespace clang { + +class CompilerInstance; + +namespace tidy { + +/// \brief Base class for all clang-tidy checks. +/// +/// To implement a ``ClangTidyCheck``, write a subclass and override some of the +/// base class's methods. E.g. to implement a check that validates namespace +/// declarations, override ``registerMatchers``: +/// +/// ~~~{.cpp} +/// void registerMatchers(ast_matchers::MatchFinder *Finder) override { +/// Finder->addMatcher(namespaceDecl().bind("namespace"), this); +/// } +/// ~~~ +/// +/// and then override ``check(const MatchResult &Result)`` to do the actual +/// check for each match. +/// +/// A new ``ClangTidyCheck`` instance is created per translation unit. +/// +/// FIXME: Figure out whether carrying information from one TU to another is +/// useful/necessary. +class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { +public: + /// \brief Initializes the check with \p CheckName and \p Context. + /// + /// Derived classes must implement the constructor with this signature or + /// delegate it. If a check needs to read options, it can do this in the + /// constructor using the Options.get() methods below. + ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context); + + /// \brief Override this to register ``PPCallbacks`` in the preprocessor. + /// + /// This should be used for clang-tidy checks that analyze preprocessor- + /// dependent properties, e.g. include directives and macro definitions. + /// + /// There are two Preprocessors to choose from that differ in how they handle + /// modular #includes: + /// - PP is the real Preprocessor. It doesn't walk into modular #includes and + /// thus doesn't generate PPCallbacks for their contents. + /// - ModuleExpanderPP preprocesses the whole translation unit in the + /// non-modular mode, which allows it to generate PPCallbacks not only for + /// the main file and textual headers, but also for all transitively + /// included modular headers when the analysis runs with modules enabled. + /// When modules are not enabled ModuleExpanderPP just points to the real + /// preprocessor. + virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) {} + + /// \brief Override this to register AST matchers with \p Finder. + /// + /// This should be used by clang-tidy checks that analyze code properties that + /// dependent on AST knowledge. + /// + /// You can register as many matchers as necessary with \p Finder. Usually, + /// "this" will be used as callback, but you can also specify other callback + /// classes. Thereby, different matchers can trigger different callbacks. + /// + /// If you need to merge information between the different matchers, you can + /// store these as members of the derived class. However, note that all + /// matches occur in the order of the AST traversal. + virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {} + + /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual + /// work in here. + virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} + + /// \brief Add a diagnostic with the check's name. + DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + + /// \brief Should store all options supported by this check with their + /// current values or default values for options that haven't been overridden. + /// + /// The check should use ``Options.store()`` to store each option it supports + /// whether it has the default value or it has been overridden. + virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {} + + /// \brief Provides access to the ``ClangTidyCheck`` options via check-local + /// names. + /// + /// Methods of this class prepend ``CheckName + "."`` to translate check-local + /// option names to global option names. + class OptionsView { + public: + /// \brief Initializes the instance using \p CheckName + "." as a prefix. + OptionsView(StringRef CheckName, + const ClangTidyOptions::OptionMap &CheckOptions); + + /// \brief 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; + + /// \brief 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 Default. + std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const; + + /// \brief Read a named option from the ``Context`` and parse it as an + /// integral type ``T``. + /// + /// Reads the option with the check-local name \p LocalName from the + /// ``CheckOptions``. If the corresponding key is not present, returns + /// \p Default. + template + typename std::enable_if::value, T>::type + get(StringRef LocalName, T Default) const { + std::string Value = get(LocalName, ""); + T Result = Default; + if (!Value.empty()) + StringRef(Value).getAsInteger(10, Result); + return Result; + } + + /// \brief Read a named option from the ``Context`` and parse it as an + /// integral type ``T``. + /// + /// 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 Default. + template + typename std::enable_if::value, T>::type + getLocalOrGlobal(StringRef LocalName, T Default) const { + std::string Value = getLocalOrGlobal(LocalName, ""); + T Result = Default; + if (!Value.empty()) + StringRef(Value).getAsInteger(10, Result); + return Result; + } + + /// \brief Stores an option with the check-local name \p LocalName with + /// string value \p Value to \p Options. + void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + StringRef Value) const; + + /// \brief Stores an option with the check-local name \p LocalName with + /// ``int64_t`` value \p Value to \p Options. + void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + int64_t Value) const; + + private: + std::string NamePrefix; + const ClangTidyOptions::OptionMap &CheckOptions; + }; + +private: + void run(const ast_matchers::MatchFinder::MatchResult &Result) override; + StringRef getID() const override { return CheckName; } + std::string CheckName; + ClangTidyContext *Context; + +protected: + OptionsView Options; + /// \brief Returns the main file name of the current translation unit. + StringRef getCurrentMainFile() const { return Context->getCurrentFile(); } + /// \brief Returns the language options from the context. + const LangOptions &getLangOpts() const { return Context->getLangOpts(); } +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index a868203..01a3526 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -1,9 +1,8 @@ //===--- ClangTidyDiagnosticConsumer.h - clang-tidy -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -139,7 +138,7 @@ class ClangTidyContext { /// \brief Returns the name of the clang-tidy check which produced this /// diagnostic ID. - StringRef getCheckName(unsigned DiagnosticID) const; + std::string getCheckName(unsigned DiagnosticID) const; /// \brief Returns \c true if the check is enabled for the \c CurrentFile. /// @@ -191,6 +190,15 @@ class ClangTidyContext { return AllowEnablingAnalyzerAlphaCheckers; } + using DiagLevelAndFormatString = std::pair; + DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, + SourceLocation Loc) { + return DiagLevelAndFormatString( + static_cast( + DiagEngine->getDiagnosticLevel(DiagnosticID, Loc)), + DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID)); + } + private: // Writes to Stats. friend class ClangTidyDiagnosticConsumer; @@ -218,6 +226,23 @@ class ClangTidyContext { 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. +/// The `CheckMacroExpansion` parameter determines whether the function should +/// handle the case where the diagnostic is inside a macro expansion. A degree +/// of control over this is needed because handling this case can require +/// examining source files other than the one in which the diagnostic is +/// located, and in some use cases we cannot rely on such other files being +/// mapped in the SourceMapper. +bool ShouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info, ClangTidyContext &Context, + bool CheckMacroExpansion = true); + /// \brief A diagnostic consumer that turns each \c Diagnostic into a /// \c SourceManager-independent \c ClangTidyError. // @@ -226,6 +251,7 @@ class ClangTidyContext { class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { public: ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx, + DiagnosticsEngine *ExternalDiagEngine = nullptr, bool RemoveIncompatibleErrors = true); // FIXME: The concept of converting between FixItHints and Replacements is @@ -247,10 +273,13 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter /// according to the diagnostic \p Location. - void checkFilters(SourceLocation Location, const SourceManager& Sources); + void checkFilters(SourceLocation Location, const SourceManager &Sources); bool passesLineFilter(StringRef FileName, unsigned LineNumber) const; + void forwardDiagnostic(const Diagnostic &Info); + ClangTidyContext &Context; + DiagnosticsEngine *ExternalDiagEngine; bool RemoveIncompatibleErrors; std::vector Errors; std::unique_ptr HeaderFilter; diff --git a/ClangTidyModule.h b/ClangTidyModule.h index 4721636..378f109 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -1,9 +1,8 @@ //===--- ClangTidyModule.h - clang-tidy -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/ClangTidyModuleRegistry.h b/ClangTidyModuleRegistry.h index dc44d14..891671a 100644 --- a/ClangTidyModuleRegistry.h +++ b/ClangTidyModuleRegistry.h @@ -1,9 +1,8 @@ //===--- ClangTidyModuleRegistry.h - clang-tidy -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index 1a75354..87c7cf5 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -1,9 +1,8 @@ //===--- ClangTidyOptions.h - clang-tidy ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/ClangTidyProfiling.h b/ClangTidyProfiling.h index 9d86b8e..a266e38 100644 --- a/ClangTidyProfiling.h +++ b/ClangTidyProfiling.h @@ -1,9 +1,8 @@ //===--- ClangTidyProfiling.h - clang-tidy ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index 562aef5..329a1e9 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -326,12 +326,41 @@ getVfsOverlayFromFile(const std::string &OverlayFile) { return OverlayFS; } +llvm::IntrusiveRefCntPtr +getVfsFromFile(const std::string &OverlayFile, + llvm::IntrusiveRefCntPtr BaseFS) { + llvm::ErrorOr> Buffer = + BaseFS->getBufferForFile(OverlayFile); + if (!Buffer) { + llvm::errs() << "Can't load virtual filesystem overlay file '" + << OverlayFile << "': " << Buffer.getError().message() + << ".\n"; + return nullptr; + } + + IntrusiveRefCntPtr FS = vfs::getVFSFromYAML( + std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile); + if (!FS) { + llvm::errs() << "Error: invalid virtual filesystem overlay file '" + << OverlayFile << "'.\n"; + return nullptr; + } + return FS; +} + static int clangTidyMain(int argc, const char **argv) { CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory, cl::ZeroOrMore); - llvm::IntrusiveRefCntPtr BaseFS( - VfsOverlay.empty() ? vfs::getRealFileSystem() - : getVfsOverlayFromFile(VfsOverlay)); + llvm::IntrusiveRefCntPtr BaseFS( + new vfs::OverlayFileSystem(vfs::getRealFileSystem())); + + if (!VfsOverlay.empty()) { + IntrusiveRefCntPtr VfsFromFile = + getVfsFromFile(VfsOverlay, BaseFS); + if (!VfsFromFile) + return 1; + BaseFS->pushOverlay(VfsFromFile); + } if (!BaseFS) return 1; From 9478379c4e945715d07b533e16d55ccfb485c309 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin Date: Fri, 13 Dec 2019 19:19:11 +0300 Subject: [PATCH 06/20] Print fully-qualified names --- aliceO2/NamespaceNamingCheck.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aliceO2/NamespaceNamingCheck.cpp b/aliceO2/NamespaceNamingCheck.cpp index 3f020dd..8ca391a 100644 --- a/aliceO2/NamespaceNamingCheck.cpp +++ b/aliceO2/NamespaceNamingCheck.cpp @@ -69,7 +69,7 @@ void NamespaceNamingCheck::check(const MatchFinder::MatchResult &Result) { if(fixNamespaceName(newName)) { - diag(MatchedNamespaceDecl->getLocation(), "namespace %0 does not follow the underscore convention") + diag(MatchedNamespaceDecl->getLocation(), "namespace %q0 does not follow the underscore convention") << MatchedNamespaceDecl << FixItHint::CreateReplacement(MatchedNamespaceDecl->getLocation(), newName); } @@ -92,7 +92,7 @@ void NamespaceNamingCheck::check(const MatchFinder::MatchResult &Result) { if(fixNamespaceName(newName)) { - diag(MatchedNamespaceLoc->getLocalBeginLoc(), "namespace %0 does not follow the underscore convention") + diag(MatchedNamespaceLoc->getLocalBeginLoc(), "namespace %q0 does not follow the underscore convention") << AsNamespace << FixItHint::CreateReplacement(MatchedNamespaceLoc->getLocalBeginLoc(), newName); } @@ -119,7 +119,7 @@ void NamespaceNamingCheck::check(const MatchFinder::MatchResult &Result) { if(fixNamespaceName(newName)) { - diag(MatchedUsingNamespace->getLocation(), "namespace %0 does not follow the underscore convention") + diag(MatchedUsingNamespace->getLocation(), "namespace %q0 does not follow the underscore convention") << MatchedUsingNamespace->getNominatedNamespace() << FixItHint::CreateReplacement(MatchedUsingNamespace->getLocation(), newName); } From acafa2477b7cb814de4889844caa2464668e74bd Mon Sep 17 00:00:00 2001 From: Andrey Erokhin Date: Fri, 13 Dec 2019 19:37:19 +0300 Subject: [PATCH 07/20] Check only ::o2 subnamespaces --- aliceO2/NamespaceNamingCheck.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/aliceO2/NamespaceNamingCheck.cpp b/aliceO2/NamespaceNamingCheck.cpp index 8ca391a..edd94d2 100644 --- a/aliceO2/NamespaceNamingCheck.cpp +++ b/aliceO2/NamespaceNamingCheck.cpp @@ -9,6 +9,7 @@ #include "NamespaceNamingCheck.h" #include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include #include @@ -17,6 +18,13 @@ using namespace clang::ast_matchers; namespace clang { +namespace ast_matchers { +AST_MATCHER_P(UsingDirectiveDecl, nominatedNamespace, + internal::Matcher, InnerMatcher) +{ + return InnerMatcher.matches(*Node.getNominatedNamespace(), Finder, Builder); +} +} // namespace ast_matchers namespace tidy { namespace aliceO2 { @@ -42,18 +50,26 @@ bool isOutsideOfTargetScope(std::string filename) void NamespaceNamingCheck::registerMatchers(MatchFinder *Finder) { const auto validNameMatch = matchesName( std::string("::") + VALID_NAME_REGEX + "$" ); + const auto inO2NSMatch = matchesName("^::o2::"); // matches namespace declarations that have invalid name Finder->addMatcher(namespaceDecl(allOf( + inO2NSMatch, unless(validNameMatch), unless(isAnonymous()) )).bind("namespace-decl"), this); // matches usage of namespace - Finder->addMatcher(nestedNameSpecifierLoc(loc(nestedNameSpecifier(specifiesNamespace(unless(validNameMatch) - )))).bind("namespace-usage"), this ); + Finder->addMatcher(nestedNameSpecifierLoc(loc(nestedNameSpecifier(specifiesNamespace(allOf( + inO2NSMatch, + unless(validNameMatch) + ))))).bind("namespace-usage"), this); // matches "using namespace" declarations - Finder->addMatcher(usingDirectiveDecl(unless(isImplicit() - )).bind("using-namespace"), this); + Finder->addMatcher(usingDirectiveDecl(allOf( + unless(isImplicit()), + nominatedNamespace(allOf( + inO2NSMatch, + unless(validNameMatch) + )))).bind("using-namespace"), this); } void NamespaceNamingCheck::check(const MatchFinder::MatchResult &Result) { @@ -112,11 +128,6 @@ void NamespaceNamingCheck::check(const MatchFinder::MatchResult &Result) { std::string newName(MatchedUsingNamespace->getNominatedNamespace()->getDeclName().getAsString()); std::string oldName=newName; - if( std::regex_match(newName, std::regex(VALID_NAME_REGEX)) ) - { - return; - } - if(fixNamespaceName(newName)) { diag(MatchedUsingNamespace->getLocation(), "namespace %q0 does not follow the underscore convention") From b9e9684f34260dd88fc314ed734000d9ba11b236 Mon Sep 17 00:00:00 2001 From: Andrey Erokhin Date: Mon, 24 Aug 2020 17:22:15 +0300 Subject: [PATCH 08/20] Bump to llvm 10.0 --- ClangTidyDiagnosticConsumer.h | 74 ++++++----------- ClangTidyForceLinker.h | 129 +++++++++++++++++++++++++++++ ClangTidyModule.h | 29 +++---- GlobList.h | 50 ++++++++++++ tool/CMakeLists.txt | 3 + tool/ClangTidyMain.cpp | 150 ++++------------------------------ 6 files changed, 235 insertions(+), 200 deletions(-) create mode 100644 ClangTidyForceLinker.h create mode 100644 GlobList.h diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index 01a3526..0d39296 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -17,7 +17,6 @@ #include "clang/Tooling/Refactoring.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" -#include "llvm/Support/Regex.h" #include "llvm/Support/Timer.h" namespace clang { @@ -33,7 +32,7 @@ class CompilationDatabase; namespace tidy { -/// \brief A detected error complete with information to display diagnostic and +/// A detected error complete with information to display diagnostic and /// automatic fix. /// /// This is used as an intermediate format to transport Diagnostics without a @@ -47,28 +46,7 @@ struct ClangTidyError : tooling::Diagnostic { bool IsWarningAsError; }; -/// \brief Read-only set of strings represented as a list of positive and -/// negative globs. Positive globs add all matched strings to the set, negative -/// globs remove them in the order of appearance in the list. -class GlobList { -public: - /// \brief \p GlobList is a comma-separated list of globs (only '*' - /// metacharacter is supported) with optional '-' prefix to denote exclusion. - GlobList(StringRef Globs); - - /// \brief Returns \c true if the pattern matches \p S. The result is the last - /// matching glob's Positive flag. - bool contains(StringRef S) { return contains(S, false); } - -private: - bool contains(StringRef S, bool Contains); - - bool Positive; - llvm::Regex Regex; - std::unique_ptr NextGlob; -}; - -/// \brief Contains displayed and ignored diagnostic counters for a ClangTidy +/// Contains displayed and ignored diagnostic counters for a ClangTidy /// run. struct ClangTidyStats { ClangTidyStats() @@ -87,7 +65,7 @@ struct ClangTidyStats { } }; -/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine +/// Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine /// provided by this context. /// /// A \c ClangTidyCheck always has access to the active context to report @@ -98,7 +76,7 @@ struct ClangTidyStats { /// \endcode class ClangTidyContext { public: - /// \brief Initializes \c ClangTidyContext instance. + /// Initializes \c ClangTidyContext instance. ClangTidyContext(std::unique_ptr OptionsProvider, bool AllowEnablingAnalyzerAlphaCheckers = false); /// Sets the DiagnosticsEngine that diag() will emit diagnostics to. @@ -110,7 +88,7 @@ class ClangTidyContext { ~ClangTidyContext(); - /// \brief Report any errors detected using this method. + /// Report any errors detected using this method. /// /// This is still under heavy development and will likely change towards using /// tablegen'd diagnostic IDs. @@ -119,72 +97,72 @@ class ClangTidyContext { StringRef Message, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - /// \brief Sets the \c SourceManager of the used \c DiagnosticsEngine. + /// Sets the \c SourceManager of the used \c DiagnosticsEngine. /// /// This is called from the \c ClangTidyCheck base class. void setSourceManager(SourceManager *SourceMgr); - /// \brief Should be called when starting to process new translation unit. + /// Should be called when starting to process new translation unit. void setCurrentFile(StringRef File); - /// \brief Returns the main file name of the current translation unit. + /// Returns the main file name of the current translation unit. StringRef getCurrentFile() const { return CurrentFile; } - /// \brief Sets ASTContext for the current translation unit. + /// Sets ASTContext for the current translation unit. void setASTContext(ASTContext *Context); - /// \brief Gets the language options from the AST context. + /// Gets the language options from the AST context. const LangOptions &getLangOpts() const { return LangOpts; } - /// \brief Returns the name of the clang-tidy check which produced this + /// Returns the name of the clang-tidy check which produced this /// diagnostic ID. std::string getCheckName(unsigned DiagnosticID) const; - /// \brief Returns \c true if the check is enabled for the \c CurrentFile. + /// Returns \c true if the check is enabled for the \c CurrentFile. /// /// The \c CurrentFile can be changed using \c setCurrentFile. bool isCheckEnabled(StringRef CheckName) const; - /// \brief Returns \c true if the check should be upgraded to error for the + /// Returns \c true if the check should be upgraded to error for the /// \c CurrentFile. bool treatAsError(StringRef CheckName) const; - /// \brief Returns global options. + /// Returns global options. const ClangTidyGlobalOptions &getGlobalOptions() const; - /// \brief Returns options for \c CurrentFile. + /// Returns options for \c CurrentFile. /// /// The \c CurrentFile can be changed using \c setCurrentFile. const ClangTidyOptions &getOptions() const; - /// \brief Returns options for \c File. Does not change or depend on + /// Returns options for \c File. Does not change or depend on /// \c CurrentFile. ClangTidyOptions getOptionsForFile(StringRef File) const; - /// \brief Returns \c ClangTidyStats containing issued and ignored diagnostic + /// Returns \c ClangTidyStats containing issued and ignored diagnostic /// counters. const ClangTidyStats &getStats() const { return Stats; } - /// \brief Control profile collection in clang-tidy. + /// Control profile collection in clang-tidy. void setEnableProfiling(bool Profile); bool getEnableProfiling() const { return Profile; } - /// \brief Control storage of profile date. + /// Control storage of profile date. void setProfileStoragePrefix(StringRef ProfilePrefix); llvm::Optional getProfileStorageParams() const; - /// \brief Should be called when starting to process new translation unit. + /// Should be called when starting to process new translation unit. void setCurrentBuildDirectory(StringRef BuildDirectory) { CurrentBuildDirectory = BuildDirectory; } - /// \brief Returns build directory of the current translation unit. + /// Returns build directory of the current translation unit. const std::string &getCurrentBuildDirectory() { return CurrentBuildDirectory; } - /// \brief If the experimental alpha checkers from the static analyzer can be + /// If the experimental alpha checkers from the static analyzer can be /// enabled. bool canEnableAnalyzerAlphaCheckers() const { return AllowEnablingAnalyzerAlphaCheckers; @@ -239,11 +217,11 @@ class ClangTidyContext { /// examining source files other than the one in which the diagnostic is /// located, and in some use cases we cannot rely on such other files being /// mapped in the SourceMapper. -bool ShouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, +bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info, ClangTidyContext &Context, bool CheckMacroExpansion = true); -/// \brief A diagnostic consumer that turns each \c Diagnostic into a +/// 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 @@ -267,11 +245,11 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { void finalizeLastError(); void removeIncompatibleErrors(); - /// \brief Returns the \c HeaderFilter constructed for the options set in the + /// Returns the \c HeaderFilter constructed for the options set in the /// context. llvm::Regex *getHeaderFilter(); - /// \brief Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter + /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter /// according to the diagnostic \p Location. void checkFilters(SourceLocation Location, const SourceManager &Sources); bool passesLineFilter(StringRef FileName, unsigned LineNumber) const; diff --git a/ClangTidyForceLinker.h b/ClangTidyForceLinker.h new file mode 100644 index 0000000..3ab7001 --- /dev/null +++ b/ClangTidyForceLinker.h @@ -0,0 +1,129 @@ +//===- ClangTidyForceLinker.h - clang-tidy --------------------------------===// +// +// 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_CLANG_TIDY_CLANGTIDYFORCELINKER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYFORCELINKER_H + +#include "clang/Config/config.h" +#include "llvm/Support/Compiler.h" + +namespace clang { +namespace tidy { + +// This anchor is used to force the linker to link the CERTModule. +extern volatile int CERTModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination = + CERTModuleAnchorSource; + +// This anchor is used to force the linker to link the AbseilModule. +extern volatile int AbseilModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination = + AbseilModuleAnchorSource; + +// This anchor is used to force the linker to link the BoostModule. +extern volatile int BoostModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination = + BoostModuleAnchorSource; + +// This anchor is used to force the linker to link the BugproneModule. +extern volatile int BugproneModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination = + BugproneModuleAnchorSource; + +// This anchor is used to force the linker to link the LinuxKernelModule. +extern volatile int LinuxKernelModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED LinuxKernelModuleAnchorDestination = + LinuxKernelModuleAnchorSource; + +// This anchor is used to force the linker to link the LLVMModule. +extern volatile int LLVMModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination = + LLVMModuleAnchorSource; + +// This anchor is used to force the linker to link the CppCoreGuidelinesModule. +extern volatile int CppCoreGuidelinesModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination = + CppCoreGuidelinesModuleAnchorSource; + +// This anchor is used to force the linker to link the DarwinModule. +extern volatile int DarwinModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED DarwinModuleAnchorDestination = + DarwinModuleAnchorSource; + +// This anchor is used to force the linker to link the FuchsiaModule. +extern volatile int FuchsiaModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination = + FuchsiaModuleAnchorSource; + +// This anchor is used to force the linker to link the GoogleModule. +extern volatile int GoogleModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination = + GoogleModuleAnchorSource; + +// This anchor is used to force the linker to link the AndroidModule. +extern volatile int AndroidModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination = + AndroidModuleAnchorSource; + +// This anchor is used to force the linker to link the MiscModule. +extern volatile int MiscModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination = + MiscModuleAnchorSource; + +// This anchor is used to force the linker to link the ModernizeModule. +extern volatile int ModernizeModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination = + ModernizeModuleAnchorSource; + +#if CLANG_ENABLE_STATIC_ANALYZER && \ + !defined(CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS) +// This anchor is used to force the linker to link the MPIModule. +extern volatile int MPIModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination = + MPIModuleAnchorSource; +#endif + +// This anchor is used to force the linker to link the OpenMPModule. +extern volatile int OpenMPModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED OpenMPModuleAnchorDestination = + OpenMPModuleAnchorSource; + +// This anchor is used to force the linker to link the PerformanceModule. +extern volatile int PerformanceModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination = + PerformanceModuleAnchorSource; + +// This anchor is used to force the linker to link the PortabilityModule. +extern volatile int PortabilityModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination = + PortabilityModuleAnchorSource; + +// This anchor is used to force the linker to link the ReadabilityModule. +extern volatile int ReadabilityModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = + ReadabilityModuleAnchorSource; + +// This anchor is used to force the linker to link the ObjCModule. +extern volatile int ObjCModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination = + ObjCModuleAnchorSource; + +// This anchor is used to force the linker to link the HICPPModule. +extern volatile int HICPPModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination = + HICPPModuleAnchorSource; + +// This anchor is used to force the linker to link the ZirconModule. +extern volatile int ZirconModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination = + ZirconModuleAnchorSource; + +} // namespace tidy +} // namespace clang + +#endif diff --git a/ClangTidyModule.h b/ClangTidyModule.h index 378f109..5c484f1 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -13,28 +13,28 @@ #include "llvm/ADT/StringRef.h" #include #include +#include #include #include namespace clang { namespace tidy { -/// \brief A collection of \c ClangTidyCheckFactory instances. +/// A collection of \c ClangTidyCheckFactory instances. /// /// All clang-tidy modules register their check factories with an instance of /// this object. class ClangTidyCheckFactories { public: - typedef std::function - CheckFactory; + using CheckFactory = std::function( + StringRef Name, ClangTidyContext *Context)>; - /// \brief Registers check \p Factory with name \p Name. + /// Registers check \p Factory with name \p Name. /// /// For all checks that have default constructors, use \c registerCheck. void registerCheckFactory(StringRef Name, CheckFactory Factory); - /// \brief Registers the \c CheckType with the name \p Name. + /// Registers the \c CheckType with the name \p Name. /// /// This method should be used for all \c ClangTidyChecks that don't require /// constructor parameters. @@ -58,16 +58,13 @@ class ClangTidyCheckFactories { template void registerCheck(StringRef CheckName) { registerCheckFactory(CheckName, [](StringRef Name, ClangTidyContext *Context) { - return new CheckType(Name, Context); + return std::make_unique(Name, Context); }); } - /// \brief Create instances of all checks matching \p CheckRegexString and - /// store them in \p Checks. - /// - /// The caller takes ownership of the return \c ClangTidyChecks. - void createChecks(ClangTidyContext *Context, - std::vector> &Checks); + /// Create instances of checks that are enabled. + std::vector> + createChecks(ClangTidyContext *Context); typedef std::map FactoryMap; FactoryMap::const_iterator begin() const { return Factories.begin(); } @@ -78,17 +75,17 @@ class ClangTidyCheckFactories { FactoryMap Factories; }; -/// \brief A clang-tidy module groups a number of \c ClangTidyChecks and gives +/// A clang-tidy module groups a number of \c ClangTidyChecks and gives /// them a prefixed name. class ClangTidyModule { public: virtual ~ClangTidyModule() {} - /// \brief Implement this function in order to register all \c CheckFactories + /// Implement this function in order to register all \c CheckFactories /// belonging to this module. virtual void addCheckFactories(ClangTidyCheckFactories &CheckFactories) = 0; - /// \brief Gets default options for checks defined in this module. + /// Gets default options for checks defined in this module. virtual ClangTidyOptions getModuleOptions(); }; diff --git a/GlobList.h b/GlobList.h new file mode 100644 index 0000000..4edb03b --- /dev/null +++ b/GlobList.h @@ -0,0 +1,50 @@ +//===--- GlobList.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_CLANG_TIDY_GLOBLIST_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Regex.h" +#include + +namespace clang { +namespace tidy { + +/// Read-only set of strings represented as a list of positive and negative +/// globs. +/// +/// Positive globs add all matched strings to the set, negative globs remove +/// them in the order of appearance in the list. +class GlobList { +public: + /// \p Globs is a comma-separated list of globs (only the '*' metacharacter is + /// supported) with an optional '-' prefix to denote exclusion. + /// + /// An empty \p Globs string is interpreted as one glob that matches an empty + /// string. + GlobList(StringRef Globs); + + /// Returns \c true if the pattern matches \p S. The result is the last + /// matching glob's Positive flag. + bool contains(StringRef S); + +private: + + struct GlobListItem { + bool IsPositive; + mutable llvm::Regex Regex; + }; + std::vector Items; +}; + +} // end namespace tidy +} // end namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt index c9d9ac9..a5cacdc 100644 --- a/tool/CMakeLists.txt +++ b/tool/CMakeLists.txt @@ -27,14 +27,17 @@ target_link_libraries(O2codecheck clangTidyBugproneModule clangTidyCERTModule clangTidyCppCoreGuidelinesModule + clangTidyDarwinModule clangTidyFuchsiaModule clangTidyGoogleModule clangTidyHICPPModule + clangTidyLinuxKernelModule clangTidyLLVMModule clangTidyMiscModule clangTidyModernizeModule clangTidyMPIModule clangTidyObjCModule + clangTidyOpenMPModule clangTidyPerformanceModule clangTidyPortabilityModule clangTidyReadabilityModule diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index 329a1e9..ad6182d 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -1,9 +1,8 @@ //===--- tools/extra/clang-tidy/ClangTidyMain.cpp - Clang tidy tool -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -16,8 +15,12 @@ //===----------------------------------------------------------------------===// #include "../ClangTidy.h" +#include "../ClangTidyForceLinker.h" +#include "../GlobList.h" #include "clang/Tooling/CommonOptionsParser.h" +#include "llvm/Support/InitLLVM.h" #include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" using namespace clang::ast_matchers; @@ -83,8 +86,8 @@ headers to output diagnostics from. Diagnostics from the main file of each translation unit are always displayed. Can be used together with -line-filter. -This option overrides the 'HeaderFilter' option -in .clang-tidy file, if any. +This option overrides the 'HeaderFilterRegex' +option in .clang-tidy file, if any. )"), cl::init(""), cl::cat(ClangTidyCategory)); @@ -288,7 +291,7 @@ static std::unique_ptr createOptionsProvider( if (!Config.empty()) { if (llvm::ErrorOr ParsedConfig = parseConfiguration(Config)) { - return llvm::make_unique( + return std::make_unique( GlobalOptions, ClangTidyOptions::getDefaults().mergeWith(DefaultOptions), *ParsedConfig, OverrideOptions); @@ -298,34 +301,10 @@ static std::unique_ptr createOptionsProvider( return nullptr; } } - return llvm::make_unique(GlobalOptions, DefaultOptions, + return std::make_unique(GlobalOptions, DefaultOptions, OverrideOptions, std::move(FS)); } -llvm::IntrusiveRefCntPtr -getVfsOverlayFromFile(const std::string &OverlayFile) { - llvm::IntrusiveRefCntPtr OverlayFS( - new vfs::OverlayFileSystem(vfs::getRealFileSystem())); - llvm::ErrorOr> Buffer = - OverlayFS->getBufferForFile(OverlayFile); - if (!Buffer) { - llvm::errs() << "Can't load virtual filesystem overlay file '" - << OverlayFile << "': " << Buffer.getError().message() - << ".\n"; - return nullptr; - } - - IntrusiveRefCntPtr FS = vfs::getVFSFromYAML( - std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile); - if (!FS) { - llvm::errs() << "Error: invalid virtual filesystem overlay file '" - << OverlayFile << "'.\n"; - return nullptr; - } - OverlayFS->pushOverlay(FS); - return OverlayFS; -} - llvm::IntrusiveRefCntPtr getVfsFromFile(const std::string &OverlayFile, llvm::IntrusiveRefCntPtr BaseFS) { @@ -349,6 +328,7 @@ getVfsFromFile(const std::string &OverlayFile, } static int clangTidyMain(int argc, const char **argv) { + llvm::InitLLVM X(argc, argv); CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory, cl::ZeroOrMore); llvm::IntrusiveRefCntPtr BaseFS( @@ -360,9 +340,7 @@ static int clangTidyMain(int argc, const char **argv) { if (!VfsFromFile) return 1; BaseFS->pushOverlay(VfsFromFile); - } - if (!BaseFS) - return 1; + } auto OwningOptionsProvider = createOptionsProvider(BaseFS); auto *OptionsProvider = OwningOptionsProvider.get(); @@ -467,7 +445,7 @@ static int clangTidyMain(int argc, const char **argv) { if (!ExportFixes.empty() && !Errors.empty()) { std::error_code EC; - llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None); + llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::OF_None); if (EC) { llvm::errs() << "Error opening output file: " << EC.message() << '\n'; return 1; @@ -508,106 +486,6 @@ static int clangTidyMain(int argc, const char **argv) { return 0; } -// This anchor is used to force the linker to link the CERTModule. -extern volatile int CERTModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination = - CERTModuleAnchorSource; - -// This anchor is used to force the linker to link the AbseilModule. -extern volatile int AbseilModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination = - AbseilModuleAnchorSource; - -// This anchor is used to force the linker to link the BoostModule. -extern volatile int BoostModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination = - BoostModuleAnchorSource; - -// This anchor is used to force the linker to link the BugproneModule. -extern volatile int BugproneModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination = - BugproneModuleAnchorSource; - -// This anchor is used to force the linker to link the LLVMModule. -extern volatile int LLVMModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination = - LLVMModuleAnchorSource; - -// This anchor is used to force the linker to link the CppCoreGuidelinesModule. -extern volatile int CppCoreGuidelinesModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination = - CppCoreGuidelinesModuleAnchorSource; - -// This anchor is used to force the linker to link the FuchsiaModule. -extern volatile int FuchsiaModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination = - FuchsiaModuleAnchorSource; - -// This anchor is used to force the linker to link the GoogleModule. -extern volatile int GoogleModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination = - GoogleModuleAnchorSource; - -// This anchor is used to force the linker to link the AndroidModule. -extern volatile int AndroidModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination = - AndroidModuleAnchorSource; - -// This anchor is used to force the linker to link the MiscModule. -extern volatile int MiscModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination = - MiscModuleAnchorSource; - -// This anchor is used to force the linker to link the ModernizeModule. -extern volatile int ModernizeModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination = - ModernizeModuleAnchorSource; - -// This anchor is used to force the linker to link the MPIModule. -extern volatile int MPIModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination = - MPIModuleAnchorSource; - -// This anchor is used to force the linker to link the PerformanceModule. -extern volatile int PerformanceModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination = - PerformanceModuleAnchorSource; - -// This anchor is used to force the linker to link the PortabilityModule. -extern volatile int PortabilityModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination = - PortabilityModuleAnchorSource; - -// This anchor is used to force the linker to link the ReadabilityModule. -extern volatile int ReadabilityModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = - ReadabilityModuleAnchorSource; - -// This anchor is used to force the linker to link the ObjCModule. -extern volatile int ObjCModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination = - ObjCModuleAnchorSource; - -// This anchor is used to force the linker to link the HICPPModule. -extern volatile int HICPPModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination = - HICPPModuleAnchorSource; - -// This anchor is used to force the linker to link the ZirconModule. -extern volatile int ZirconModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination = - ZirconModuleAnchorSource; - -// This anchor is used to force the linker to link the AliceO2Module. -extern volatile int AliceO2ModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AliceO2ModuleAnchorDestination = - AliceO2ModuleAnchorSource; - -// This anchor is used to force the linker to link the ReportingModule. -extern volatile int ReportingModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ReportingModuleAnchorDestination = - ReportingModuleAnchorSource; - } // namespace tidy } // namespace clang From 05bc055a6009cf60197ececaff5afe4fd005e1e1 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 15 Nov 2020 12:58:42 +0100 Subject: [PATCH 09/20] Bump to Clang 11 (#36) * Bump to Clang 11 * Update ClangTidyMain.cpp Restore the main function. * Update CMakeLists.txt Adding clangTidyLLVMLibcModule as suggested by @aeroknin Co-authored-by: Peter Hristov --- ClangTidy.h | 25 +- ClangTidyCheck.h | 417 +++++++++++++++++++++++++++++---- ClangTidyDiagnosticConsumer.h | 24 +- ClangTidyForceLinker.h | 61 ++--- ClangTidyModule.h | 15 +- ClangTidyOptions.h | 180 ++++++++------ ClangTidyProfiling.h | 7 +- aliceO2/MemberNamesCheck.h | 1 + aliceO2/NamespaceNamingCheck.h | 1 + aliceO2/SizeofCheck.h | 1 + plugin/FooCheck.h | 1 + reporting/InterfaceLister.h | 1 + reporting/VirtFuncLister.h | 1 + tool/CMakeLists.txt | 1 + tool/ClangTidyMain.cpp | 59 +++-- 15 files changed, 605 insertions(+), 190 deletions(-) diff --git a/ClangTidy.h b/ClangTidy.h index a9433f6..99dcbb6 100644 --- a/ClangTidy.h +++ b/ClangTidy.h @@ -9,19 +9,22 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H -#include "ClangTidyCheck.h" #include "ClangTidyDiagnosticConsumer.h" #include "ClangTidyOptions.h" -#include "llvm/Support/raw_ostream.h" #include #include +namespace llvm { +class raw_ostream; +} // namespace llvm + namespace clang { +class ASTConsumer; class CompilerInstance; namespace tooling { class CompilationDatabase; -} +} // namespace tooling namespace tidy { @@ -33,14 +36,14 @@ class ClangTidyASTConsumerFactory { ClangTidyContext &Context, IntrusiveRefCntPtr OverlayFS = nullptr); - /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks. + /// Returns an ASTConsumer that runs the specified clang-tidy checks. std::unique_ptr CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File); - /// \brief Get the list of enabled checks. + /// Get the list of enabled checks. std::vector getCheckNames(); - /// \brief Get the union of options from all checks. + /// Get the union of options from all checks. ClangTidyOptions::OptionMap getCheckOptions(); private: @@ -49,12 +52,12 @@ class ClangTidyASTConsumerFactory { std::unique_ptr CheckFactories; }; -/// \brief Fills the list of check names that are enabled when the provided +/// Fills the list of check names that are enabled when the provided /// filters are applied. std::vector getCheckNames(const ClangTidyOptions &Options, bool AllowEnablingAnalyzerAlphaCheckers); -/// \brief Returns the effective check-specific options. +/// Returns the effective check-specific options. /// /// The method configures ClangTidy with the specified \p Options and collects /// effective options from all created checks. The returned set of options @@ -64,7 +67,7 @@ ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options, bool AllowEnablingAnalyzerAlphaCheckers); -/// \brief Run a set of clang-tidy checks on a set of files. +/// Run a set of clang-tidy checks on a set of files. /// /// \param EnableCheckProfile If provided, it enables check profile collection /// in MatchFinder, and will contain the result of the profile. @@ -82,7 +85,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context, // FIXME: This interface will need to be significantly extended to be useful. // FIXME: Implement confidence levels for displaying/fixing errors. // -/// \brief Displays the found \p Errors to the users. If \p Fix is true, \p +/// Displays the found \p Errors to the users. If \p Fix is true, \p /// Errors containing fixes are automatically applied and reformatted. If no /// clang-format configuration file is found, the given \P FormatStyle is used. void handleErrors(llvm::ArrayRef Errors, @@ -90,7 +93,7 @@ void handleErrors(llvm::ArrayRef Errors, unsigned &WarningsAsErrorsCount, llvm::IntrusiveRefCntPtr BaseFS); -/// \brief Serializes replacements into YAML and writes them to the specified +/// Serializes replacements into YAML and writes them to the specified /// output stream. void exportReplacements(StringRef MainFilePath, const std::vector &Errors, diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h index 3064a41..54b7251 100644 --- a/ClangTidyCheck.h +++ b/ClangTidyCheck.h @@ -13,19 +13,86 @@ #include "ClangTidyOptions.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/StringExtras.h" -#include +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Error.h" #include +#include #include namespace clang { class CompilerInstance; +class SourceManager; namespace tidy { -/// \brief Base class for all clang-tidy checks. +/// This class should be specialized by any enum type that needs to be converted +/// to and from an \ref llvm::StringRef. +template struct OptionEnumMapping { + // Specializations of this struct must implement this function. + static ArrayRef> getEnumMapping() = delete; +}; + +template class OptionError : public llvm::ErrorInfo { + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } + +public: + void log(raw_ostream &OS) const override { OS << this->message(); } +}; + +class MissingOptionError : public OptionError { +public: + explicit MissingOptionError(std::string OptionName) + : OptionName(OptionName) {} + + std::string message() const override; + static char ID; +private: + const std::string OptionName; +}; + +class UnparseableEnumOptionError + : public OptionError { +public: + explicit UnparseableEnumOptionError(std::string LookupName, + std::string LookupValue) + : LookupName(LookupName), LookupValue(LookupValue) {} + explicit UnparseableEnumOptionError(std::string LookupName, + std::string LookupValue, + std::string SuggestedValue) + : LookupName(LookupName), LookupValue(LookupValue), + SuggestedValue(SuggestedValue) {} + + std::string message() const override; + static char ID; + +private: + const std::string LookupName; + const std::string LookupValue; + const llvm::Optional SuggestedValue; +}; + +class UnparseableIntegerOptionError + : public OptionError { +public: + explicit UnparseableIntegerOptionError(std::string LookupName, + std::string LookupValue, + bool IsBoolean = false) + : LookupName(LookupName), LookupValue(LookupValue), IsBoolean(IsBoolean) { + } + + std::string message() const override; + static char ID; + +private: + const std::string LookupName; + const std::string LookupValue; + const bool IsBoolean; +}; + +/// Base class for all clang-tidy checks. /// /// To implement a ``ClangTidyCheck``, write a subclass and override some of the /// base class's methods. E.g. to implement a check that validates namespace @@ -46,18 +113,31 @@ namespace tidy { /// useful/necessary. class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { public: - /// \brief Initializes the check with \p CheckName and \p Context. + /// Initializes the check with \p CheckName and \p Context. /// /// Derived classes must implement the constructor with this signature or /// delegate it. If a check needs to read options, it can do this in the /// constructor using the Options.get() methods below. ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context); - /// \brief Override this to register ``PPCallbacks`` in the preprocessor. + /// Override this to disable registering matchers and PP callbacks if an + /// invalid language version is being used. + /// + /// For example if a check is examining overloaded functions then this should + /// be overridden to return false when the CPlusPlus flag is not set in + /// \p LangOpts. + virtual bool isLanguageVersionSupported(const LangOptions &LangOpts) const { + return true; + } + + /// Override this to register ``PPCallbacks`` in the preprocessor. /// /// This should be used for clang-tidy checks that analyze preprocessor- /// dependent properties, e.g. include directives and macro definitions. /// + /// This will only be executed if the function isLanguageVersionSupported + /// returns true. + /// /// There are two Preprocessors to choose from that differ in how they handle /// modular #includes: /// - PP is the real Preprocessor. It doesn't walk into modular #includes and @@ -71,7 +151,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {} - /// \brief Override this to register AST matchers with \p Finder. + /// Override this to register AST matchers with \p Finder. /// /// This should be used by clang-tidy checks that analyze code properties that /// dependent on AST knowledge. @@ -80,96 +160,303 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// "this" will be used as callback, but you can also specify other callback /// classes. Thereby, different matchers can trigger different callbacks. /// + /// This will only be executed if the function isLanguageVersionSupported + /// returns true. + /// /// If you need to merge information between the different matchers, you can /// store these as members of the derived class. However, note that all /// matches occur in the order of the AST traversal. virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {} - /// \brief ``ClangTidyChecks`` that register ASTMatchers should do the actual + /// ``ClangTidyChecks`` that register ASTMatchers should do the actual /// work in here. virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} - /// \brief Add a diagnostic with the check's name. + /// Add a diagnostic with the check's name. DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - /// \brief Should store all options supported by this check with their + /// Should store all options supported by this check with their /// current values or default values for options that haven't been overridden. /// /// The check should use ``Options.store()`` to store each option it supports /// whether it has the default value or it has been overridden. virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {} - /// \brief Provides access to the ``ClangTidyCheck`` options via check-local + /// Provides access to the ``ClangTidyCheck`` options via check-local /// names. /// /// Methods of this class prepend ``CheckName + "."`` to translate check-local /// option names to global option names. class OptionsView { public: - /// \brief Initializes the instance using \p CheckName + "." as a prefix. + /// Initializes the instance using \p CheckName + "." as a prefix. OptionsView(StringRef CheckName, const ClangTidyOptions::OptionMap &CheckOptions); - /// \brief Read a named option from the ``Context``. + /// 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 + /// a ``MissingOptionError``. + llvm::Expected 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; + std::string get(StringRef LocalName, StringRef Default) const { + if (llvm::Expected Val = get(LocalName)) + return *Val; + else + llvm::consumeError(Val.takeError()); + return Default.str(); + } + + /// 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 a ``MissingOptionError``. + llvm::Expected getLocalOrGlobal(StringRef LocalName) const; - /// \brief Read a named option from the ``Context``. + /// 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 Default. - std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const; + /// present either, returns \p Default. + std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const { + if (llvm::Expected Val = getLocalOrGlobal(LocalName)) + return *Val; + else + llvm::consumeError(Val.takeError()); + return Default.str(); + } - /// \brief Read a named option from the ``Context`` and parse it as an + /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. /// /// Reads the option with the check-local name \p LocalName from the /// ``CheckOptions``. If the corresponding key is not present, returns - /// \p Default. + /// a ``MissingOptionError``. If the corresponding key can't be parsed as + /// a ``T``, return an ``UnparseableIntegerOptionError``. template - typename std::enable_if::value, T>::type - get(StringRef LocalName, T Default) const { - std::string Value = get(LocalName, ""); - T Result = Default; - if (!Value.empty()) - StringRef(Value).getAsInteger(10, Result); - return Result; + std::enable_if_t::value, llvm::Expected> + get(StringRef LocalName) const { + if (llvm::Expected Value = get(LocalName)) { + T Result{}; + if (!StringRef(*Value).getAsInteger(10, Result)) + return Result; + return llvm::make_error( + (NamePrefix + LocalName).str(), *Value); + } else + return std::move(Value.takeError()); + } + + /// Read a named option from the ``Context`` and parse it as an + /// integral type ``T``. + /// + /// Reads the option with the check-local name \p LocalName from the + /// ``CheckOptions``. If the corresponding key is not present or it can't be + /// parsed as a ``T``, returns \p Default. + template + std::enable_if_t::value, T> get(StringRef LocalName, + T Default) const { + if (llvm::Expected ValueOr = get(LocalName)) + return *ValueOr; + else + logErrToStdErr(ValueOr.takeError()); + return Default; + } + + /// Read a named option from the ``Context`` and parse it as an + /// integral type ``T``. + /// + /// 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 a ``MissingOptionError``. If the corresponding + /// key can't be parsed as a ``T``, return an + /// ``UnparseableIntegerOptionError``. + template + std::enable_if_t::value, llvm::Expected> + getLocalOrGlobal(StringRef LocalName) const { + llvm::Expected ValueOr = get(LocalName); + bool IsGlobal = false; + if (!ValueOr) { + IsGlobal = true; + llvm::consumeError(ValueOr.takeError()); + ValueOr = getLocalOrGlobal(LocalName); + if (!ValueOr) + return std::move(ValueOr.takeError()); + } + T Result{}; + if (!StringRef(*ValueOr).getAsInteger(10, Result)) + return Result; + return llvm::make_error( + (IsGlobal ? LocalName.str() : (NamePrefix + LocalName).str()), + *ValueOr); } - /// \brief Read a named option from the ``Context`` and parse it as an + /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. /// /// 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 Default. + /// present either or it can't be parsed as a ``T``, returns \p Default. template - typename std::enable_if::value, T>::type + std::enable_if_t::value, T> getLocalOrGlobal(StringRef LocalName, T Default) const { - std::string Value = getLocalOrGlobal(LocalName, ""); - T Result = Default; - if (!Value.empty()) - StringRef(Value).getAsInteger(10, Result); - return Result; + if (llvm::Expected ValueOr = getLocalOrGlobal(LocalName)) + return *ValueOr; + else + logErrToStdErr(ValueOr.takeError()); + return Default; + } + + /// Read a named option from the ``Context`` and parse it as an + /// enum type ``T``. + /// + /// Reads the option with the check-local name \p LocalName from the + /// ``CheckOptions``. If the corresponding key is not present, returns a + /// ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a + /// ``UnparseableEnumOptionError``. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. + template + std::enable_if_t::value, llvm::Expected> + get(StringRef LocalName, bool IgnoreCase = false) { + if (llvm::Expected ValueOr = + getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) + return static_cast(*ValueOr); + else + return std::move(ValueOr.takeError()); } - /// \brief Stores an option with the check-local name \p LocalName with + /// Read a named option from the ``Context`` and parse it as an + /// enum type ``T``. + /// + /// Reads the option with the check-local name \p LocalName from the + /// ``CheckOptions``. If the corresponding key is not present or it can't be + /// parsed as a ``T``, returns \p Default. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. + template + std::enable_if_t::value, T> + get(StringRef LocalName, T Default, bool IgnoreCase = false) { + if (auto ValueOr = get(LocalName, IgnoreCase)) + return *ValueOr; + else + logErrToStdErr(ValueOr.takeError()); + return Default; + } + + /// Read a named option from the ``Context`` and parse it as an + /// enum type ``T``. + /// + /// 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 a ``MissingOptionError``. If the key can't be + /// parsed as a ``T`` returns a ``UnparseableEnumOptionError``. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. + template + std::enable_if_t::value, llvm::Expected> + getLocalOrGlobal(StringRef LocalName, + bool IgnoreCase = false) { + if (llvm::Expected ValueOr = + getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) + return static_cast(*ValueOr); + else + return std::move(ValueOr.takeError()); + } + + /// Read a named option from the ``Context`` and parse it as an + /// enum type ``T``. + /// + /// 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 or it can't be parsed as a ``T``, returns \p Default. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. + template + std::enable_if_t::value, T> + getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) { + if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) + return *ValueOr; + else + logErrToStdErr(ValueOr.takeError()); + return Default; + } + + /// Stores an option with the check-local name \p LocalName with /// string value \p Value to \p Options. void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const; - /// \brief Stores an option with the check-local name \p LocalName with - /// ``int64_t`` value \p Value to \p Options. - void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - int64_t Value) const; + /// Stores an option with the check-local name \p LocalName with + /// integer value \p Value to \p Options. + template + std::enable_if_t::value> + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + T Value) const { + storeInt(Options, LocalName, Value); + } + + /// Stores an option with the check-local name \p LocalName as the string + /// representation of the Enum \p Value to \p Options. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. + template + std::enable_if_t::value> + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) { + ArrayRef> Mapping = + OptionEnumMapping::getEnumMapping(); + auto Iter = llvm::find_if( + Mapping, [&](const std::pair &NameAndEnum) { + return NameAndEnum.first == Value; + }); + assert(Iter != Mapping.end() && "Unknown Case Value"); + store(Options, LocalName, Iter->second); + } private: + using NameAndValue = std::pair; + + llvm::Expected getEnumInt(StringRef LocalName, + ArrayRef Mapping, + bool CheckGlobal, bool IgnoreCase); + + template + std::enable_if_t::value, std::vector> + typeEraseMapping() { + ArrayRef> Mapping = + OptionEnumMapping::getEnumMapping(); + std::vector Result; + Result.reserve(Mapping.size()); + for (auto &MappedItem : Mapping) { + Result.emplace_back(static_cast(MappedItem.first), + MappedItem.second); + } + return Result; + } + + void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + int64_t Value) const; + + static void logErrToStdErr(llvm::Error &&Err); + std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; }; @@ -182,12 +469,60 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { protected: OptionsView Options; - /// \brief Returns the main file name of the current translation unit. + /// Returns the main file name of the current translation unit. StringRef getCurrentMainFile() const { return Context->getCurrentFile(); } - /// \brief Returns the language options from the context. + /// Returns the language options from the context. const LangOptions &getLangOpts() const { return Context->getLangOpts(); } }; +/// Read a named option from the ``Context`` and parse it as a bool. +/// +/// Reads the option with the check-local name \p LocalName from the +/// ``CheckOptions``. If the corresponding key is not present, returns +/// a ``MissingOptionError``. If the corresponding key can't be parsed as +/// a bool, return an ``UnparseableIntegerOptionError``. +template <> +llvm::Expected +ClangTidyCheck::OptionsView::get(StringRef LocalName) const; + +/// Read a named option from the ``Context`` and parse it as a bool. +/// +/// Reads the option with the check-local name \p LocalName from the +/// ``CheckOptions``. If the corresponding key is not present or it can't be +/// parsed as a bool, returns \p Default. +template <> +bool ClangTidyCheck::OptionsView::get(StringRef LocalName, + bool Default) const; + +/// Read a named option from the ``Context`` and parse it as a bool. +/// +/// 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 a ``MissingOptionError``. If the corresponding +/// key can't be parsed as a bool, return an +/// ``UnparseableIntegerOptionError``. +template <> +llvm::Expected +ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const; + +/// Read a named option from the ``Context`` and parse it as a bool. +/// +/// 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 or it can't be parsed as a bool, returns \p Default. +template <> +bool ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName, + bool Default) const; + +/// Stores an option with the check-local name \p LocalName with +/// bool value \p Value to \p Options. +template <> +void ClangTidyCheck::OptionsView::store( + ClangTidyOptions::OptionMap &Options, StringRef LocalName, + bool Value) const; + } // namespace tidy } // namespace clang diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index 0d39296..eaa7f18 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -12,17 +12,15 @@ #include "ClangTidyOptions.h" #include "ClangTidyProfiling.h" #include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceManager.h" #include "clang/Tooling/Core/Diagnostic.h" -#include "clang/Tooling/Refactoring.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/Timer.h" +#include "llvm/Support/Regex.h" namespace clang { class ASTContext; class CompilerInstance; +class SourceManager; namespace ast_matchers { class MatchFinder; } @@ -44,6 +42,7 @@ struct ClangTidyError : tooling::Diagnostic { bool IsWarningAsError); bool IsWarningAsError; + std::vector EnabledDiagnosticAliases; }; /// Contains displayed and ignored diagnostic counters for a ClangTidy @@ -154,7 +153,7 @@ class ClangTidyContext { /// Should be called when starting to process new translation unit. void setCurrentBuildDirectory(StringRef BuildDirectory) { - CurrentBuildDirectory = BuildDirectory; + CurrentBuildDirectory = std::string(BuildDirectory); } /// Returns build directory of the current translation unit. @@ -174,7 +173,8 @@ class ClangTidyContext { return DiagLevelAndFormatString( static_cast( DiagEngine->getDiagnosticLevel(DiagnosticID, Loc)), - DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID)); + std::string( + DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID))); } private: @@ -211,15 +211,12 @@ class ClangTidyContext { /// 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. -/// The `CheckMacroExpansion` parameter determines whether the function should -/// handle the case where the diagnostic is inside a macro expansion. A degree -/// of control over this is needed because handling this case can require -/// examining source files other than the one in which the diagnostic is -/// located, and in some use cases we cannot rely on such other files being -/// mapped in the SourceMapper. +/// 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 CheckMacroExpansion = true); + bool AllowIO = true); /// A diagnostic consumer that turns each \c Diagnostic into a /// \c SourceManager-independent \c ClangTidyError. @@ -244,6 +241,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { private: void finalizeLastError(); void removeIncompatibleErrors(); + void removeDuplicatedDiagnosticsOfAliasCheckers(); /// Returns the \c HeaderFilter constructed for the options set in the /// context. diff --git a/ClangTidyForceLinker.h b/ClangTidyForceLinker.h index 3ab7001..1d6bd2a 100644 --- a/ClangTidyForceLinker.h +++ b/ClangTidyForceLinker.h @@ -15,16 +15,16 @@ namespace clang { namespace tidy { -// This anchor is used to force the linker to link the CERTModule. -extern volatile int CERTModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination = - CERTModuleAnchorSource; - // This anchor is used to force the linker to link the AbseilModule. extern volatile int AbseilModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination = AbseilModuleAnchorSource; +// This anchor is used to force the linker to link the AndroidModule. +extern volatile int AndroidModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination = + AndroidModuleAnchorSource; + // This anchor is used to force the linker to link the BoostModule. extern volatile int BoostModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination = @@ -35,15 +35,10 @@ extern volatile int BugproneModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination = BugproneModuleAnchorSource; -// This anchor is used to force the linker to link the LinuxKernelModule. -extern volatile int LinuxKernelModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED LinuxKernelModuleAnchorDestination = - LinuxKernelModuleAnchorSource; - -// This anchor is used to force the linker to link the LLVMModule. -extern volatile int LLVMModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination = - LLVMModuleAnchorSource; +// This anchor is used to force the linker to link the CERTModule. +extern volatile int CERTModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination = + CERTModuleAnchorSource; // This anchor is used to force the linker to link the CppCoreGuidelinesModule. extern volatile int CppCoreGuidelinesModuleAnchorSource; @@ -65,10 +60,25 @@ extern volatile int GoogleModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination = GoogleModuleAnchorSource; -// This anchor is used to force the linker to link the AndroidModule. -extern volatile int AndroidModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination = - AndroidModuleAnchorSource; +// This anchor is used to force the linker to link the HICPPModule. +extern volatile int HICPPModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination = + HICPPModuleAnchorSource; + +// This anchor is used to force the linker to link the LinuxKernelModule. +extern volatile int LinuxKernelModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED LinuxKernelModuleAnchorDestination = + LinuxKernelModuleAnchorSource; + +// This anchor is used to force the linker to link the LLVMModule. +extern volatile int LLVMModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination = + LLVMModuleAnchorSource; + +// This anchor is used to force the linker to link the LLVMLibcModule. +extern volatile int LLVMLibcModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED LLVMLibcModuleAnchorDestination = + LLVMLibcModuleAnchorSource; // This anchor is used to force the linker to link the MiscModule. extern volatile int MiscModuleAnchorSource; @@ -88,6 +98,11 @@ static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination = MPIModuleAnchorSource; #endif +// This anchor is used to force the linker to link the ObjCModule. +extern volatile int ObjCModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination = + ObjCModuleAnchorSource; + // This anchor is used to force the linker to link the OpenMPModule. extern volatile int OpenMPModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED OpenMPModuleAnchorDestination = @@ -108,16 +123,6 @@ extern volatile int ReadabilityModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = ReadabilityModuleAnchorSource; -// This anchor is used to force the linker to link the ObjCModule. -extern volatile int ObjCModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination = - ObjCModuleAnchorSource; - -// This anchor is used to force the linker to link the HICPPModule. -extern volatile int HICPPModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination = - HICPPModuleAnchorSource; - // This anchor is used to force the linker to link the ZirconModule. extern volatile int ZirconModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination = diff --git a/ClangTidyModule.h b/ClangTidyModule.h index 5c484f1..31cf477 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -9,17 +9,20 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H -#include "ClangTidy.h" +#include "ClangTidyOptions.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include #include #include #include -#include namespace clang { namespace tidy { +class ClangTidyCheck; +class ClangTidyContext; + /// A collection of \c ClangTidyCheckFactory instances. /// /// All clang-tidy modules register their check factories with an instance of @@ -27,12 +30,12 @@ namespace tidy { class ClangTidyCheckFactories { public: using CheckFactory = std::function( - StringRef Name, ClangTidyContext *Context)>; + llvm::StringRef Name, ClangTidyContext *Context)>; /// Registers check \p Factory with name \p Name. /// /// For all checks that have default constructors, use \c registerCheck. - void registerCheckFactory(StringRef Name, CheckFactory Factory); + void registerCheckFactory(llvm::StringRef Name, CheckFactory Factory); /// Registers the \c CheckType with the name \p Name. /// @@ -55,9 +58,9 @@ class ClangTidyCheckFactories { /// } /// }; /// \endcode - template void registerCheck(StringRef CheckName) { + template void registerCheck(llvm::StringRef CheckName) { registerCheckFactory(CheckName, - [](StringRef Name, ClangTidyContext *Context) { + [](llvm::StringRef Name, ClangTidyContext *Context) { return std::make_unique(Name, Context); }); } diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index 87c7cf5..0f3c1d4 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -25,30 +25,30 @@ namespace clang { namespace tidy { -/// \brief Contains a list of line ranges in a single file. +/// Contains a list of line ranges in a single file. struct FileFilter { - /// \brief File name. + /// File name. std::string Name; - /// \brief LineRange is a pair (inclusive). + /// LineRange is a pair (inclusive). typedef std::pair LineRange; - /// \brief A list of line ranges in this file, for which we show warnings. + /// A list of line ranges in this file, for which we show warnings. std::vector LineRanges; }; -/// \brief Global options. These options are neither stored nor read from +/// Global options. These options are neither stored nor read from /// configuration files. struct ClangTidyGlobalOptions { - /// \brief Output warnings from certain line ranges of certain files only. + /// Output warnings from certain line ranges of certain files only. /// If empty, no warnings will be filtered. std::vector LineFilter; }; -/// \brief Contains options for clang-tidy. These options may be read from +/// Contains options for clang-tidy. These options may be read from /// configuration files, and may be different for different translation units. struct ClangTidyOptions { - /// \brief These options are used for all settings that haven't been + /// These options are used for all settings that haven't been /// overridden by the \c OptionsProvider. /// /// Allow no checks and no headers by default. This method initializes @@ -56,24 +56,26 @@ struct ClangTidyOptions { /// of each registered \c ClangTidyModule. static ClangTidyOptions getDefaults(); - /// \brief Creates a new \c ClangTidyOptions instance combined from all fields + /// Creates a new \c ClangTidyOptions instance combined from all fields /// of this instance overridden by the fields of \p Other that have a value. - ClangTidyOptions mergeWith(const ClangTidyOptions &Other) const; + /// \p Order specifies precedence of \p Other option. + ClangTidyOptions mergeWith(const ClangTidyOptions &Other, + unsigned Order) const; - /// \brief Checks filter. + /// Checks filter. llvm::Optional Checks; - /// \brief WarningsAsErrors filter. + /// WarningsAsErrors filter. llvm::Optional WarningsAsErrors; - /// \brief Output warnings from headers matching this filter. Warnings from + /// Output warnings from headers matching this filter. Warnings from /// main files will always be displayed. llvm::Optional HeaderFilterRegex; - /// \brief Output warnings from system headers matching \c HeaderFilterRegex. + /// Output warnings from system headers matching \c HeaderFilterRegex. llvm::Optional SystemHeaders; - /// \brief Format code around applied fixes with clang-format using this + /// Format code around applied fixes with clang-format using this /// style. /// /// Can be one of: @@ -87,28 +89,52 @@ struct ClangTidyOptions { /// See clang-format documentation for more about configuring format style. llvm::Optional FormatStyle; - /// \brief Specifies the name or e-mail of the user running clang-tidy. + /// Specifies the name or e-mail of the user running clang-tidy. /// /// This option is used, for example, to place the correct user name in TODO() /// comments in the relevant check. llvm::Optional User; + /// Helper structure for storing option value with priority of the value. + struct ClangTidyValue { + ClangTidyValue() : Value(), Priority(0) {} + ClangTidyValue(const char *Value) : Value(Value), Priority(0) {} + ClangTidyValue(llvm::StringRef Value, unsigned Priority = 0) + : Value(Value), Priority(Priority) {} + + std::string Value; + /// Priority stores relative precedence of the value loaded from config + /// files to disambigute local vs global value from different levels. + unsigned Priority; + }; typedef std::pair StringPair; - typedef std::map OptionMap; + typedef std::map OptionMap; - /// \brief Key-value mapping used to store check-specific options. + /// Key-value mapping used to store check-specific options. OptionMap CheckOptions; typedef std::vector ArgList; - /// \brief Add extra compilation arguments to the end of the list. + /// Add extra compilation arguments to the end of the list. llvm::Optional ExtraArgs; - /// \brief Add extra compilation arguments to the start of the list. + /// Add extra compilation arguments to the start of the list. llvm::Optional ExtraArgsBefore; + + /// Only used in the FileOptionsProvider and ConfigOptionsProvider. If true + /// 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 + /// configuration file will be used. + llvm::Optional InheritParentConfig; + + /// Use colors in diagnostics. If missing, it will be auto detected. + llvm::Optional UseColor; }; -/// \brief Abstract interface for retrieving various ClangTidy options. +/// Abstract interface for retrieving various ClangTidy options. class ClangTidyOptionsProvider { public: static const char OptionsSourceTypeDefaultBinary[]; @@ -117,10 +143,10 @@ class ClangTidyOptionsProvider { virtual ~ClangTidyOptionsProvider() {} - /// \brief Returns global options, which are independent of the file. + /// Returns global options, which are independent of the file. virtual const ClangTidyGlobalOptions &getGlobalOptions() = 0; - /// \brief ClangTidyOptions and its source. + /// ClangTidyOptions and its source. // /// clang-tidy has 3 types of the sources in order of increasing priority: /// * clang-tidy binary. @@ -130,17 +156,17 @@ class ClangTidyOptionsProvider { /// * '-checks' commandline option. typedef std::pair OptionsSource; - /// \brief Returns an ordered vector of OptionsSources, in order of increasing + /// Returns an ordered vector of OptionsSources, in order of increasing /// priority. virtual std::vector getRawOptions(llvm::StringRef FileName) = 0; - /// \brief Returns options applying to a specific translation unit with the + /// Returns options applying to a specific translation unit with the /// specified \p FileName. ClangTidyOptions getOptions(llvm::StringRef FileName); }; -/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which +/// Implementation of the \c ClangTidyOptionsProvider interface, which /// returns the same options for all files. class DefaultOptionsProvider : public ClangTidyOptionsProvider { public: @@ -157,38 +183,15 @@ class DefaultOptionsProvider : public ClangTidyOptionsProvider { ClangTidyOptions DefaultOptions; }; -/// \brief Implementation of ClangTidyOptions interface, which is used for -/// '-config' command-line option. -class ConfigOptionsProvider : public DefaultOptionsProvider { -public: - ConfigOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &ConfigOptions, - const ClangTidyOptions &OverrideOptions); - std::vector getRawOptions(llvm::StringRef FileName) override; - -private: - ClangTidyOptions ConfigOptions; - ClangTidyOptions OverrideOptions; -}; - -/// \brief Implementation of the \c ClangTidyOptionsProvider interface, which -/// tries to find a configuration file in the closest parent directory of each -/// source file. -/// -/// By default, files named ".clang-tidy" will be considered, and the -/// \c clang::tidy::parseConfiguration function will be used for parsing, but a -/// custom set of configuration file names and parsing functions can be -/// specified using the appropriate constructor. -class FileOptionsProvider : public DefaultOptionsProvider { +class FileOptionsBaseProvider : public DefaultOptionsProvider { public: - // \brief A pair of configuration file base name and a function parsing + // A pair of configuration file base name and a function parsing // configuration from text in the corresponding format. typedef std::pair( llvm::StringRef)>> ConfigFileHandler; - /// \brief Configuration file handlers listed in the order of priority. + /// Configuration file handlers listed in the order of priority. /// /// Custom configuration file formats can be supported by constructing the /// list of handlers and passing it to the appropriate \c FileOptionsProvider @@ -199,7 +202,7 @@ class FileOptionsProvider : public DefaultOptionsProvider { /// FileOptionsProvider::ConfigFileHandlers ConfigHandlers; /// ConfigHandlers.emplace_back(".my-tidy-config", parseMyConfigFormat); /// ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration); - /// return llvm::make_unique( + /// return std::make_unique( /// GlobalOptions, DefaultOptions, OverrideOptions, ConfigHandlers); /// \endcode /// @@ -207,7 +210,58 @@ class FileOptionsProvider : public DefaultOptionsProvider { /// take precedence over ".clang-tidy" if both reside in the same directory. typedef std::vector ConfigFileHandlers; - /// \brief Initializes the \c FileOptionsProvider instance. + FileOptionsBaseProvider( + const ClangTidyGlobalOptions &GlobalOptions, + const ClangTidyOptions &DefaultOptions, + const ClangTidyOptions &OverrideOptions, + llvm::IntrusiveRefCntPtr FS = nullptr); + + FileOptionsBaseProvider(const ClangTidyGlobalOptions &GlobalOptions, + const ClangTidyOptions &DefaultOptions, + const ClangTidyOptions &OverrideOptions, + const ConfigFileHandlers &ConfigHandlers); + +protected: + void addRawFileOptions(llvm::StringRef AbsolutePath, + std::vector &CurOptions); + + /// Try to read configuration files from \p Directory using registered + /// \c ConfigHandlers. + llvm::Optional tryReadConfigFile(llvm::StringRef Directory); + + llvm::StringMap CachedOptions; + ClangTidyOptions OverrideOptions; + ConfigFileHandlers ConfigHandlers; + llvm::IntrusiveRefCntPtr FS; +}; + +/// Implementation of ClangTidyOptions interface, which is used for +/// '-config' command-line option. +class ConfigOptionsProvider : public FileOptionsBaseProvider { +public: + ConfigOptionsProvider( + const ClangTidyGlobalOptions &GlobalOptions, + const ClangTidyOptions &DefaultOptions, + const ClangTidyOptions &ConfigOptions, + const ClangTidyOptions &OverrideOptions, + llvm::IntrusiveRefCntPtr FS = nullptr); + std::vector getRawOptions(llvm::StringRef FileName) override; + +private: + ClangTidyOptions ConfigOptions; +}; + +/// Implementation of the \c ClangTidyOptionsProvider interface, which +/// tries to find a configuration file in the closest parent directory of each +/// source file. +/// +/// By default, files named ".clang-tidy" will be considered, and the +/// \c clang::tidy::parseConfiguration function will be used for parsing, but a +/// custom set of configuration file names and parsing functions can be +/// specified using the appropriate constructor. +class FileOptionsProvider : public FileOptionsBaseProvider { +public: + /// Initializes the \c FileOptionsProvider instance. /// /// \param GlobalOptions are just stored and returned to the caller of /// \c getGlobalOptions. @@ -223,7 +277,7 @@ class FileOptionsProvider : public DefaultOptionsProvider { const ClangTidyOptions &OverrideOptions, llvm::IntrusiveRefCntPtr FS = nullptr); - /// \brief Initializes the \c FileOptionsProvider instance with a custom set + /// Initializes the \c FileOptionsProvider instance with a custom set /// of configuration file handlers. /// /// \param GlobalOptions are just stored and returned to the caller of @@ -246,27 +300,17 @@ class FileOptionsProvider : public DefaultOptionsProvider { const ConfigFileHandlers &ConfigHandlers); std::vector getRawOptions(llvm::StringRef FileName) override; - -protected: - /// \brief Try to read configuration files from \p Directory using registered - /// \c ConfigHandlers. - llvm::Optional tryReadConfigFile(llvm::StringRef Directory); - - llvm::StringMap CachedOptions; - ClangTidyOptions OverrideOptions; - ConfigFileHandlers ConfigHandlers; - llvm::IntrusiveRefCntPtr FS; }; -/// \brief Parses LineFilter from JSON and stores it to the \p Options. +/// Parses LineFilter from JSON and stores it to the \p Options. std::error_code parseLineFilter(llvm::StringRef LineFilter, ClangTidyGlobalOptions &Options); -/// \brief Parses configuration from JSON and returns \c ClangTidyOptions or an +/// Parses configuration from JSON and returns \c ClangTidyOptions or an /// error. llvm::ErrorOr parseConfiguration(llvm::StringRef Config); -/// \brief Serializes configuration to a YAML-encoded string. +/// Serializes configuration to a YAML-encoded string. std::string configurationAsText(const ClangTidyOptions &Options); } // end namespace tidy diff --git a/ClangTidyProfiling.h b/ClangTidyProfiling.h index a266e38..9487a34 100644 --- a/ClangTidyProfiling.h +++ b/ClangTidyProfiling.h @@ -13,10 +13,11 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" #include -#include -#include + +namespace llvm { +class raw_ostream; +} // namespace llvm namespace clang { namespace tidy { diff --git a/aliceO2/MemberNamesCheck.h b/aliceO2/MemberNamesCheck.h index 2c48e4e..f61119e 100644 --- a/aliceO2/MemberNamesCheck.h +++ b/aliceO2/MemberNamesCheck.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_MEMBER_NAMES_H #include "../ClangTidy.h" +#include "../ClangTidyCheck.h" #include namespace clang { diff --git a/aliceO2/NamespaceNamingCheck.h b/aliceO2/NamespaceNamingCheck.h index e931dc9..17cc9e9 100644 --- a/aliceO2/NamespaceNamingCheck.h +++ b/aliceO2/NamespaceNamingCheck.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_NAMESPACE_NAMING_H #include "../ClangTidy.h" +#include "../ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/aliceO2/SizeofCheck.h b/aliceO2/SizeofCheck.h index 8abd8e3..c291f5f 100644 --- a/aliceO2/SizeofCheck.h +++ b/aliceO2/SizeofCheck.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_SIZEOF_H #include "../ClangTidy.h" +#include "../ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/plugin/FooCheck.h b/plugin/FooCheck.h index 042bd19..2039ccc 100644 --- a/plugin/FooCheck.h +++ b/plugin/FooCheck.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PLUGIN_FOO_H #include "../ClangTidy.h" +#include "../ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/reporting/InterfaceLister.h b/reporting/InterfaceLister.h index c2e0a47..f517be6 100644 --- a/reporting/InterfaceLister.h +++ b/reporting/InterfaceLister.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INTERFACELISTER_NAMES_H #include "../ClangTidy.h" +#include "../ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/reporting/VirtFuncLister.h b/reporting/VirtFuncLister.h index b71cfe1..5f3a6b2 100644 --- a/reporting/VirtFuncLister.h +++ b/reporting/VirtFuncLister.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_VIRTFUNCLISTER_NAMES_H #include "../ClangTidy.h" +#include "../ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt index a5cacdc..8371e0a 100644 --- a/tool/CMakeLists.txt +++ b/tool/CMakeLists.txt @@ -33,6 +33,7 @@ target_link_libraries(O2codecheck clangTidyHICPPModule clangTidyLinuxKernelModule clangTidyLLVMModule + clangTidyLLVMLibcModule clangTidyMiscModule clangTidyModernizeModule clangTidyMPIModule diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index ad6182d..70d9bef 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -22,9 +22,8 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/WithColor.h" -using namespace clang::ast_matchers; -using namespace clang::driver; using namespace clang::tooling; using namespace llvm; @@ -35,17 +34,20 @@ static cl::extrahelp ClangTidyHelp(R"( Configuration files: clang-tidy attempts to read configuration for each source file from a .clang-tidy file located in the closest parent directory of the source - file. If any configuration options have a corresponding command-line - option, command-line option takes precedence. The effective - configuration can be inspected using -dump-config: + file. If InheritParentConfig is true in a config file, the configuration file + in the parent directory (if any exists) will be taken and current config file + will be applied on top of the parent one. If any configuration options have + a corresponding command-line option, command-line option takes precedence. + The effective configuration can be inspected using -dump-config: $ clang-tidy -dump-config --- - Checks: '-*,some-check' - WarningsAsErrors: '' - HeaderFilterRegex: '' - FormatStyle: none - User: user + Checks: '-*,some-check' + WarningsAsErrors: '' + HeaderFilterRegex: '' + FormatStyle: none + InheritParentConfig: true + User: user CheckOptions: - key: some-check.SomeOption value: 'some value' @@ -225,6 +227,15 @@ over the real file system. cl::value_desc("filename"), cl::cat(ClangTidyCategory)); +static cl::opt UseColor("use-color", cl::desc(R"( +Use colors in diagnostics. If not set, colors +will be used if the terminal connected to +standard output supports colors. +This option overrides the 'UseColor' option in +.clang-tidy file, if any. +)"), + cl::init(false), cl::cat(ClangTidyCategory)); + namespace clang { namespace tidy { @@ -287,14 +298,16 @@ static std::unique_ptr createOptionsProvider( OverrideOptions.SystemHeaders = SystemHeaders; if (FormatStyle.getNumOccurrences() > 0) OverrideOptions.FormatStyle = FormatStyle; + if (UseColor.getNumOccurrences() > 0) + OverrideOptions.UseColor = UseColor; if (!Config.empty()) { if (llvm::ErrorOr ParsedConfig = parseConfiguration(Config)) { return std::make_unique( GlobalOptions, - ClangTidyOptions::getDefaults().mergeWith(DefaultOptions), - *ParsedConfig, OverrideOptions); + ClangTidyOptions::getDefaults().mergeWith(DefaultOptions, 0), + *ParsedConfig, OverrideOptions, std::move(FS)); } else { llvm::errs() << "Error: invalid configuration specified.\n" << ParsedConfig.getError().message() << "\n"; @@ -327,10 +340,16 @@ getVfsFromFile(const std::string &OverlayFile, return FS; } -static int clangTidyMain(int argc, const char **argv) { +int clangTidyMain(int argc, const char **argv) { llvm::InitLLVM X(argc, argv); - CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory, - cl::ZeroOrMore); + llvm::Expected OptionsParser = + CommonOptionsParser::create(argc, argv, ClangTidyCategory, + cl::ZeroOrMore); + if (!OptionsParser) { + llvm::WithColor::error() << llvm::toString(OptionsParser.takeError()); + return 1; + } + llvm::IntrusiveRefCntPtr BaseFS( new vfs::OverlayFileSystem(vfs::getRealFileSystem())); @@ -361,12 +380,12 @@ static int clangTidyMain(int argc, const char **argv) { SmallString<256> ProfilePrefix = MakeAbsolute(StoreCheckProfile); StringRef FileName("dummy"); - auto PathList = OptionsParser.getSourcePathList(); + auto PathList = OptionsParser->getSourcePathList(); if (!PathList.empty()) { FileName = PathList.front(); } - SmallString<256> FilePath = MakeAbsolute(FileName); + SmallString<256> FilePath = MakeAbsolute(std::string(FileName)); ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FilePath); std::vector EnabledChecks = @@ -405,7 +424,7 @@ static int clangTidyMain(int argc, const char **argv) { getCheckOptions(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers); llvm::outs() << configurationAsText( ClangTidyOptions::getDefaults().mergeWith( - EffectiveOptions)) + EffectiveOptions, 0)) << "\n"; return 0; } @@ -429,7 +448,7 @@ static int clangTidyMain(int argc, const char **argv) { ClangTidyContext Context(std::move(OwningOptionsProvider), AllowEnablingAnalyzerAlphaCheckers); std::vector Errors = - runClangTidy(Context, OptionsParser.getCompilations(), PathList, BaseFS, + runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS, EnableCheckProfile, ProfilePrefix); bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) { return E.DiagLevel == ClangTidyError::Error; @@ -467,7 +486,7 @@ static int clangTidyMain(int argc, const char **argv) { llvm::errs() << WErrorCount << " warning" << Plural << " treated as error" << Plural << "\n"; } - return WErrorCount; + return 1; } if (FoundErrors) { From d41ae7663e65cf562c78637a8f09c65b07000872 Mon Sep 17 00:00:00 2001 From: Peter Hristov Date: Wed, 18 Aug 2021 13:35:15 +0200 Subject: [PATCH 10/20] Bump to Clang 12 (#37) Co-authored-by: hristov --- ClangTidyCheck.h | 79 ++++++++++++++++++++++++++++------- ClangTidyDiagnosticConsumer.h | 8 ++++ ClangTidyForceLinker.h | 14 ++++++- ClangTidyModule.h | 4 +- ClangTidyOptions.h | 67 ++++++++++++++++------------- GlobList.h | 8 ++-- README.md | 2 +- clang-tidy-config.h | 10 +++++ tool/CMakeLists.txt | 2 + tool/ClangTidyMain.cpp | 64 +++++++++++++++++++++------- tool/ClangTidyMain.h | 23 ++++++++++ 11 files changed, 212 insertions(+), 69 deletions(-) create mode 100644 clang-tidy-config.h create mode 100644 tool/ClangTidyMain.h diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h index 54b7251..9fa0d63 100644 --- a/ClangTidyCheck.h +++ b/ClangTidyCheck.h @@ -176,6 +176,15 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + /// Add a diagnostic with the check's name. + DiagnosticBuilder diag(StringRef Description, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + + /// Adds a diagnostic to report errors in the check's configuration. + DiagnosticBuilder + configurationDiag(StringRef Description, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + /// Should store all options supported by this check with their /// current values or default values for options that haven't been overridden. /// @@ -192,7 +201,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { public: /// Initializes the instance using \p CheckName + "." as a prefix. OptionsView(StringRef CheckName, - const ClangTidyOptions::OptionMap &CheckOptions); + const ClangTidyOptions::OptionMap &CheckOptions, + ClangTidyContext *Context); /// Read a named option from the ``Context``. /// @@ -268,7 +278,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { if (llvm::Expected ValueOr = get(LocalName)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -314,7 +324,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { if (llvm::Expected ValueOr = getLocalOrGlobal(LocalName)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -330,7 +340,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, llvm::Expected> - get(StringRef LocalName, bool IgnoreCase = false) { + get(StringRef LocalName, bool IgnoreCase = false) const { if (llvm::Expected ValueOr = getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) return static_cast(*ValueOr); @@ -349,11 +359,11 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, T> - get(StringRef LocalName, T Default, bool IgnoreCase = false) { + get(StringRef LocalName, T Default, bool IgnoreCase = false) const { if (auto ValueOr = get(LocalName, IgnoreCase)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -370,8 +380,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, llvm::Expected> - getLocalOrGlobal(StringRef LocalName, - bool IgnoreCase = false) { + getLocalOrGlobal(StringRef LocalName, bool IgnoreCase = false) const { if (llvm::Expected ValueOr = getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) return static_cast(*ValueOr); @@ -391,14 +400,40 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, T> - getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) { + getLocalOrGlobal(StringRef LocalName, T Default, + bool IgnoreCase = false) const { if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } + /// Returns the value for the option \p LocalName represented as a ``T``. + /// If the option is missing returns None, if the option can't be parsed + /// as a ``T``, log that to stderr and return None. + template + llvm::Optional getOptional(StringRef LocalName) const { + if (auto ValueOr = get(LocalName)) + return *ValueOr; + else + reportOptionParsingError(ValueOr.takeError()); + return llvm::None; + } + + /// Returns the value for the local or global option \p LocalName + /// represented as a ``T``. + /// If the option is missing returns None, if the + /// option can't be parsed as a ``T``, log that to stderr and return None. + template + llvm::Optional getOptionalLocalOrGlobal(StringRef LocalName) const { + if (auto ValueOr = getLocalOrGlobal(LocalName)) + return *ValueOr; + else + reportOptionParsingError(ValueOr.takeError()); + return llvm::None; + } + /// Stores an option with the check-local name \p LocalName with /// string value \p Value to \p Options. void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, @@ -420,7 +455,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value> - store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) { + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + T Value) const { ArrayRef> Mapping = OptionEnumMapping::getEnumMapping(); auto Iter = llvm::find_if( @@ -436,11 +472,11 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { llvm::Expected getEnumInt(StringRef LocalName, ArrayRef Mapping, - bool CheckGlobal, bool IgnoreCase); + bool CheckGlobal, bool IgnoreCase) const; template std::enable_if_t::value, std::vector> - typeEraseMapping() { + typeEraseMapping() const { ArrayRef> Mapping = OptionEnumMapping::getEnumMapping(); std::vector Result; @@ -455,10 +491,12 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, int64_t Value) const; - static void logErrToStdErr(llvm::Error &&Err); + /// Emits a diagnostic if \p Err is not a MissingOptionError. + void reportOptionParsingError(llvm::Error &&Err) const; std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; + ClangTidyContext *Context; }; private: @@ -523,6 +561,19 @@ void ClangTidyCheck::OptionsView::store( ClangTidyOptions::OptionMap &Options, StringRef LocalName, bool Value) const; +/// Returns the value for the option \p LocalName. +/// If the option is missing returns None. +template <> +Optional ClangTidyCheck::OptionsView::getOptional( + StringRef LocalName) const; + +/// Returns the value for the local or global option \p LocalName. +/// If the option is missing returns None. +template <> +Optional +ClangTidyCheck::OptionsView::getOptionalLocalOrGlobal( + StringRef LocalName) const; + } // namespace tidy } // namespace clang diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index eaa7f18..0792931 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -96,6 +96,14 @@ class ClangTidyContext { StringRef Message, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + DiagnosticBuilder diag(StringRef CheckName, StringRef Message, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + + /// Report any errors to do with reading the configuration using this method. + DiagnosticBuilder + configurationDiag(StringRef Message, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + /// Sets the \c SourceManager of the used \c DiagnosticsEngine. /// /// This is called from the \c ClangTidyCheck base class. diff --git a/ClangTidyForceLinker.h b/ClangTidyForceLinker.h index 1d6bd2a..2691d90 100644 --- a/ClangTidyForceLinker.h +++ b/ClangTidyForceLinker.h @@ -9,7 +9,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYFORCELINKER_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYFORCELINKER_H -#include "clang/Config/config.h" +#include "clang-tidy-config.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -20,6 +20,11 @@ extern volatile int AbseilModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination = AbseilModuleAnchorSource; +// This anchor is used to force the linker to link the AlteraModule. +extern volatile int AlteraModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED AlteraModuleAnchorDestination = + AlteraModuleAnchorSource; + // This anchor is used to force the linker to link the AndroidModule. extern volatile int AndroidModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination = @@ -40,6 +45,11 @@ extern volatile int CERTModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination = CERTModuleAnchorSource; +// This anchor is used to force the linker to link the ConcurrencyModule. +extern volatile int ConcurrencyModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED ConcurrencyModuleAnchorDestination = + ConcurrencyModuleAnchorSource; + // This anchor is used to force the linker to link the CppCoreGuidelinesModule. extern volatile int CppCoreGuidelinesModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination = @@ -90,7 +100,7 @@ extern volatile int ModernizeModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination = ModernizeModuleAnchorSource; -#if CLANG_ENABLE_STATIC_ANALYZER && \ +#if CLANG_TIDY_ENABLE_STATIC_ANALYZER && \ !defined(CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS) // This anchor is used to force the linker to link the MPIModule. extern volatile int MPIModuleAnchorSource; diff --git a/ClangTidyModule.h b/ClangTidyModule.h index 31cf477..dd21a8d 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -13,9 +13,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include -#include #include -#include namespace clang { namespace tidy { @@ -69,7 +67,7 @@ class ClangTidyCheckFactories { std::vector> createChecks(ClangTidyContext *Context); - typedef std::map FactoryMap; + typedef llvm::StringMap FactoryMap; FactoryMap::const_iterator begin() const { return Factories.begin(); } FactoryMap::const_iterator end() const { return Factories.end(); } bool empty() const { return Factories.empty(); } diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index 0f3c1d4..d8a4a14 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -14,9 +14,9 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/VirtualFileSystem.h" #include -#include #include #include #include @@ -56,11 +56,15 @@ struct ClangTidyOptions { /// of each registered \c ClangTidyModule. static ClangTidyOptions getDefaults(); + /// Overwrites all fields in here by the fields of \p Other that have a value. + /// \p Order specifies precedence of \p Other option. + ClangTidyOptions &mergeWith(const ClangTidyOptions &Other, unsigned Order); + /// Creates a new \c ClangTidyOptions instance combined from all fields /// of this instance overridden by the fields of \p Other that have a value. /// \p Order specifies precedence of \p Other option. - ClangTidyOptions mergeWith(const ClangTidyOptions &Other, - unsigned Order) const; + LLVM_NODISCARD ClangTidyOptions merge(const ClangTidyOptions &Other, + unsigned Order) const; /// Checks filter. llvm::Optional Checks; @@ -108,7 +112,7 @@ struct ClangTidyOptions { unsigned Priority; }; typedef std::pair StringPair; - typedef std::map OptionMap; + typedef llvm::StringMap OptionMap; /// Key-value mapping used to store check-specific options. OptionMap CheckOptions; @@ -170,9 +174,10 @@ class ClangTidyOptionsProvider { /// returns the same options for all files. class DefaultOptionsProvider : public ClangTidyOptionsProvider { public: - DefaultOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &Options) - : GlobalOptions(GlobalOptions), DefaultOptions(Options) {} + DefaultOptionsProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions Options) + : GlobalOptions(std::move(GlobalOptions)), + DefaultOptions(std::move(Options)) {} const ClangTidyGlobalOptions &getGlobalOptions() override { return GlobalOptions; } @@ -184,11 +189,11 @@ class DefaultOptionsProvider : public ClangTidyOptionsProvider { }; class FileOptionsBaseProvider : public DefaultOptionsProvider { -public: +protected: // A pair of configuration file base name and a function parsing // configuration from text in the corresponding format. typedef std::pair( - llvm::StringRef)>> + llvm::MemoryBufferRef)>> ConfigFileHandler; /// Configuration file handlers listed in the order of priority. @@ -210,16 +215,15 @@ class FileOptionsBaseProvider : public DefaultOptionsProvider { /// take precedence over ".clang-tidy" if both reside in the same directory. typedef std::vector ConfigFileHandlers; - FileOptionsBaseProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - llvm::IntrusiveRefCntPtr FS = nullptr); + FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + llvm::IntrusiveRefCntPtr FS); - FileOptionsBaseProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - const ConfigFileHandlers &ConfigHandlers); + FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + ConfigFileHandlers ConfigHandlers); protected: void addRawFileOptions(llvm::StringRef AbsolutePath, @@ -240,10 +244,8 @@ class FileOptionsBaseProvider : public DefaultOptionsProvider { class ConfigOptionsProvider : public FileOptionsBaseProvider { public: ConfigOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &ConfigOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions ConfigOptions, ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr FS = nullptr); std::vector getRawOptions(llvm::StringRef FileName) override; @@ -272,9 +274,8 @@ class FileOptionsProvider : public FileOptionsBaseProvider { /// If any of the \param OverrideOptions fields are set, they will override /// whatever options are read from the configuration file. FileOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr FS = nullptr); /// Initializes the \c FileOptionsProvider instance with a custom set @@ -294,10 +295,10 @@ class FileOptionsProvider : public FileOptionsBaseProvider { /// that can parse configuration from this file type. The configuration files /// in each directory are searched for in the order of appearance in /// \p ConfigHandlers. - FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - const ConfigFileHandlers &ConfigHandlers); + FileOptionsProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + ConfigFileHandlers ConfigHandlers); std::vector getRawOptions(llvm::StringRef FileName) override; }; @@ -308,7 +309,13 @@ std::error_code parseLineFilter(llvm::StringRef LineFilter, /// Parses configuration from JSON and returns \c ClangTidyOptions or an /// error. -llvm::ErrorOr parseConfiguration(llvm::StringRef Config); +llvm::ErrorOr +parseConfiguration(llvm::MemoryBufferRef Config); + +using DiagCallback = llvm::function_ref; + +llvm::ErrorOr +parseConfigurationWithDiags(llvm::MemoryBufferRef Config, DiagCallback Handler); /// Serializes configuration to a YAML-encoded string. std::string configurationAsText(const ClangTidyOptions &Options); diff --git a/GlobList.h b/GlobList.h index 4edb03b..fe68a34 100644 --- a/GlobList.h +++ b/GlobList.h @@ -10,9 +10,9 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" -#include namespace clang { namespace tidy { @@ -33,15 +33,15 @@ class GlobList { /// Returns \c true if the pattern matches \p S. The result is the last /// matching glob's Positive flag. - bool contains(StringRef S); + bool contains(StringRef S) const; private: struct GlobListItem { bool IsPositive; - mutable llvm::Regex Regex; + llvm::Regex Regex; }; - std::vector Items; + SmallVector Items; }; } // end namespace tidy diff --git a/README.md b/README.md index fb8e067..358de1e 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ It offers: In the build directory of AliceO2 (containing the CMake compilations database in form of `compile_command.json`), run - run_O2CodeChecker.py -clang-tidy-binary `which O2codecheck` -checks=-*,alice* + run_O2CodeChecker.py -clang-tidy-binary `which O2codecheck` -checks=*,alice* diff --git a/clang-tidy-config.h b/clang-tidy-config.h new file mode 100644 index 0000000..c3847d4 --- /dev/null +++ b/clang-tidy-config.h @@ -0,0 +1,10 @@ +/* This generated file is for internal use. Do not include it from headers. */ + +#ifdef CLANG_TIDY_CONFIG_H +#error clang-tidy-config.h can only be included once +#else +#define CLANG_TIDY_CONFIG_H + +#define CLANG_TIDY_ENABLE_STATIC_ANALYZER 1 + +#endif diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt index 8371e0a..4d00fa4 100644 --- a/tool/CMakeLists.txt +++ b/tool/CMakeLists.txt @@ -21,11 +21,13 @@ target_link_libraries(O2codecheck clangTidyReportingModule # include checkers available from main clang-tidy + clangTidyAlteraModule clangTidyAndroidModule clangTidyAbseilModule clangTidyBoostModule clangTidyBugproneModule clangTidyCERTModule + clangTidyConcurrencyModule clangTidyCppCoreGuidelinesModule clangTidyDarwinModule clangTidyFuchsiaModule diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index 70d9bef..176d5e8 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -14,6 +14,7 @@ /// //===----------------------------------------------------------------------===// +#include "ClangTidyMain.h" #include "../ClangTidy.h" #include "../ClangTidyForceLinker.h" #include "../GlobList.h" @@ -167,6 +168,16 @@ each source file in its parent directories. )"), cl::init(""), cl::cat(ClangTidyCategory)); +static cl::opt ConfigFile("config-file", cl::desc(R"( +Specify the path of .clang-tidy or custom config file: + e.g. --config-file=/some/path/myTidyConfigFile +This option internally works exactly the same way as + --config option after reading specified config file. +Use either --config-file or --config, not both. +)"), + cl::init(""), + cl::cat(ClangTidyCategory)); + static cl::opt DumpConfig("dump-config", cl::desc(R"( Dumps configuration in the YAML format to stdout. This option can be used along with a @@ -301,21 +312,45 @@ static std::unique_ptr createOptionsProvider( if (UseColor.getNumOccurrences() > 0) OverrideOptions.UseColor = UseColor; - if (!Config.empty()) { - if (llvm::ErrorOr ParsedConfig = - parseConfiguration(Config)) { + auto LoadConfig = + [&](StringRef Configuration, + StringRef Source) -> std::unique_ptr { + llvm::ErrorOr ParsedConfig = + parseConfiguration(MemoryBufferRef(Configuration, Source)); + if (ParsedConfig) return std::make_unique( - GlobalOptions, - ClangTidyOptions::getDefaults().mergeWith(DefaultOptions, 0), - *ParsedConfig, OverrideOptions, std::move(FS)); - } else { - llvm::errs() << "Error: invalid configuration specified.\n" - << ParsedConfig.getError().message() << "\n"; + std::move(GlobalOptions), + ClangTidyOptions::getDefaults().merge(DefaultOptions, 0), + std::move(*ParsedConfig), std::move(OverrideOptions), std::move(FS)); + llvm::errs() << "Error: invalid configuration specified.\n" + << ParsedConfig.getError().message() << "\n"; + return nullptr; + }; + + if (ConfigFile.getNumOccurrences() > 0) { + if (Config.getNumOccurrences() > 0) { + llvm::errs() << "Error: --config-file and --config are " + "mutually exclusive. Specify only one.\n"; return nullptr; } + + llvm::ErrorOr> Text = + llvm::MemoryBuffer::getFile(ConfigFile); + if (std::error_code EC = Text.getError()) { + llvm::errs() << "Error: can't read config-file '" << ConfigFile + << "': " << EC.message() << "\n"; + return nullptr; + } + + return LoadConfig((*Text)->getBuffer(), ConfigFile); } - return std::make_unique(GlobalOptions, DefaultOptions, - OverrideOptions, std::move(FS)); + + if (Config.getNumOccurrences() > 0) + return LoadConfig(Config, ""); + + return std::make_unique( + std::move(GlobalOptions), std::move(DefaultOptions), + std::move(OverrideOptions), std::move(FS)); } llvm::IntrusiveRefCntPtr @@ -358,7 +393,7 @@ int clangTidyMain(int argc, const char **argv) { getVfsFromFile(VfsOverlay, BaseFS); if (!VfsFromFile) return 1; - BaseFS->pushOverlay(VfsFromFile); + BaseFS->pushOverlay(std::move(VfsFromFile)); } auto OwningOptionsProvider = createOptionsProvider(BaseFS); @@ -422,9 +457,8 @@ int clangTidyMain(int argc, const char **argv) { if (DumpConfig) { EffectiveOptions.CheckOptions = getCheckOptions(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers); - llvm::outs() << configurationAsText( - ClangTidyOptions::getDefaults().mergeWith( - EffectiveOptions, 0)) + llvm::outs() << configurationAsText(ClangTidyOptions::getDefaults().merge( + EffectiveOptions, 0)) << "\n"; return 0; } diff --git a/tool/ClangTidyMain.h b/tool/ClangTidyMain.h new file mode 100644 index 0000000..f87f84b --- /dev/null +++ b/tool/ClangTidyMain.h @@ -0,0 +1,23 @@ +//===--- tools/extra/clang-tidy/ClangTidyMain.h - Clang tidy tool -------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file This file declares the main function for the clang-tidy tool. +/// +/// This tool uses the Clang Tooling infrastructure, see +/// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +/// for details on setting it up with LLVM source tree. +/// +//===----------------------------------------------------------------------===// + +namespace clang { +namespace tidy { + +int clangTidyMain(int argc, const char **argv); + +} // namespace tidy +} // namespace clang From 9b46b24114792e4b18405371292ad3d2582969f5 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 4 Nov 2021 21:08:26 +0100 Subject: [PATCH 11/20] Bump to Clang 13 --- ClangTidy.h | 21 ++- ClangTidyCheck.h | 288 ++++++++++------------------------ ClangTidyDiagnosticConsumer.h | 11 +- tool/ClangTidyMain.cpp | 25 ++- 4 files changed, 128 insertions(+), 217 deletions(-) diff --git a/ClangTidy.h b/ClangTidy.h index 99dcbb6..bbe4fe6 100644 --- a/ClangTidy.h +++ b/ClangTidy.h @@ -79,17 +79,28 @@ runClangTidy(clang::tidy::ClangTidyContext &Context, const tooling::CompilationDatabase &Compilations, ArrayRef InputFiles, llvm::IntrusiveRefCntPtr BaseFS, - bool EnableCheckProfile = false, + bool ApplyAnyFix, bool EnableCheckProfile = false, llvm::StringRef StoreCheckProfile = StringRef()); +/// Controls what kind of fixes clang-tidy is allowed to apply. +enum FixBehaviour { + /// Don't try to apply any fix. + FB_NoFix, + /// Only apply fixes added to warnings. + FB_Fix, + /// Apply fixes found in notes. + FB_FixNotes +}; + // FIXME: This interface will need to be significantly extended to be useful. // FIXME: Implement confidence levels for displaying/fixing errors. // -/// Displays the found \p Errors to the users. If \p Fix is true, \p -/// Errors containing fixes are automatically applied and reformatted. If no -/// clang-format configuration file is found, the given \P FormatStyle is used. +/// Displays the found \p Errors to the users. If \p Fix is \ref FB_Fix or \ref +/// FB_FixNotes, \p Errors containing fixes are automatically applied and +/// reformatted. If no clang-format configuration file is found, the given \P +/// FormatStyle is used. void handleErrors(llvm::ArrayRef Errors, - ClangTidyContext &Context, bool Fix, + ClangTidyContext &Context, FixBehaviour Fix, unsigned &WarningsAsErrorsCount, llvm::IntrusiveRefCntPtr BaseFS); diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h index 9fa0d63..20e9b8e 100644 --- a/ClangTidyCheck.h +++ b/ClangTidyCheck.h @@ -14,7 +14,6 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/Optional.h" -#include "llvm/Support/Error.h" #include #include #include @@ -33,65 +32,6 @@ template struct OptionEnumMapping { static ArrayRef> getEnumMapping() = delete; }; -template class OptionError : public llvm::ErrorInfo { - std::error_code convertToErrorCode() const override { - return llvm::inconvertibleErrorCode(); - } - -public: - void log(raw_ostream &OS) const override { OS << this->message(); } -}; - -class MissingOptionError : public OptionError { -public: - explicit MissingOptionError(std::string OptionName) - : OptionName(OptionName) {} - - std::string message() const override; - static char ID; -private: - const std::string OptionName; -}; - -class UnparseableEnumOptionError - : public OptionError { -public: - explicit UnparseableEnumOptionError(std::string LookupName, - std::string LookupValue) - : LookupName(LookupName), LookupValue(LookupValue) {} - explicit UnparseableEnumOptionError(std::string LookupName, - std::string LookupValue, - std::string SuggestedValue) - : LookupName(LookupName), LookupValue(LookupValue), - SuggestedValue(SuggestedValue) {} - - std::string message() const override; - static char ID; - -private: - const std::string LookupName; - const std::string LookupValue; - const llvm::Optional SuggestedValue; -}; - -class UnparseableIntegerOptionError - : public OptionError { -public: - explicit UnparseableIntegerOptionError(std::string LookupName, - std::string LookupValue, - bool IsBoolean = false) - : LookupName(LookupName), LookupValue(LookupValue), IsBoolean(IsBoolean) { - } - - std::string message() const override; - static char ID; - -private: - const std::string LookupName; - const std::string LookupValue; - const bool IsBoolean; -}; - /// Base class for all clang-tidy checks. /// /// To implement a ``ClangTidyCheck``, write a subclass and override some of the @@ -198,6 +138,13 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// Methods of this class prepend ``CheckName + "."`` to translate check-local /// option names to global option names. class OptionsView { + void diagnoseBadIntegerOption(const Twine &Lookup, + StringRef Unparsed) const; + void diagnoseBadBooleanOption(const Twine &Lookup, + StringRef Unparsed) const; + void diagnoseBadEnumOption(const Twine &Lookup, StringRef Unparsed, + StringRef Suggestion = StringRef()) const; + public: /// Initializes the instance using \p CheckName + "." as a prefix. OptionsView(StringRef CheckName, @@ -207,30 +154,24 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 - /// a ``MissingOptionError``. - llvm::Expected get(StringRef LocalName) const; + /// ``CheckOptions``. If the corresponding key is not present, return + /// ``None``. + llvm::Optional 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 { - if (llvm::Expected Val = get(LocalName)) - return *Val; - else - llvm::consumeError(Val.takeError()); - return Default.str(); - } + std::string 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, returns a ``MissingOptionError``. - llvm::Expected getLocalOrGlobal(StringRef LocalName) const; + /// present either, return ``None``. + llvm::Optional getLocalOrGlobal(StringRef LocalName) const; /// Read a named option from the ``Context``. /// @@ -238,48 +179,42 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 { - if (llvm::Expected Val = getLocalOrGlobal(LocalName)) - return *Val; - else - llvm::consumeError(Val.takeError()); - return Default.str(); - } + std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const; /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. /// /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, returns - /// a ``MissingOptionError``. If the corresponding key can't be parsed as - /// a ``T``, return an ``UnparseableIntegerOptionError``. + /// ``CheckOptions``. If the corresponding key is not present, return + /// ``None``. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return ``None``. template - std::enable_if_t::value, llvm::Expected> + std::enable_if_t::value, llvm::Optional> get(StringRef LocalName) const { - if (llvm::Expected Value = get(LocalName)) { + if (llvm::Optional Value = get(LocalName)) { T Result{}; if (!StringRef(*Value).getAsInteger(10, Result)) return Result; - return llvm::make_error( - (NamePrefix + LocalName).str(), *Value); - } else - return std::move(Value.takeError()); + diagnoseBadIntegerOption(NamePrefix + LocalName, *Value); + } + return None; } /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. /// /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present or it can't be - /// parsed as a ``T``, returns \p Default. + /// ``CheckOptions``. If the corresponding key is not present, return + /// \p Default. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return \p Default. template std::enable_if_t::value, T> get(StringRef LocalName, T Default) const { - if (llvm::Expected ValueOr = get(LocalName)) - return *ValueOr; - else - reportOptionParsingError(ValueOr.takeError()); - return Default; + return get(LocalName).getValueOr(Default); } /// Read a named option from the ``Context`` and parse it as an @@ -288,27 +223,27 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 a ``MissingOptionError``. If the corresponding - /// key can't be parsed as a ``T``, return an - /// ``UnparseableIntegerOptionError``. + /// present either, return ``None``. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return ``None``. template - std::enable_if_t::value, llvm::Expected> + std::enable_if_t::value, llvm::Optional> getLocalOrGlobal(StringRef LocalName) const { - llvm::Expected ValueOr = get(LocalName); + llvm::Optional ValueOr = get(LocalName); bool IsGlobal = false; if (!ValueOr) { IsGlobal = true; - llvm::consumeError(ValueOr.takeError()); ValueOr = getLocalOrGlobal(LocalName); if (!ValueOr) - return std::move(ValueOr.takeError()); + return None; } T Result{}; if (!StringRef(*ValueOr).getAsInteger(10, Result)) return Result; - return llvm::make_error( - (IsGlobal ? LocalName.str() : (NamePrefix + LocalName).str()), - *ValueOr); + diagnoseBadIntegerOption( + IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr); + return None; } /// Read a named option from the ``Context`` and parse it as an @@ -317,54 +252,53 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 or it can't be parsed as a ``T``, returns \p Default. + /// present either, return \p Default. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return \p Default. template std::enable_if_t::value, T> getLocalOrGlobal(StringRef LocalName, T Default) const { - if (llvm::Expected ValueOr = getLocalOrGlobal(LocalName)) - return *ValueOr; - else - reportOptionParsingError(ValueOr.takeError()); - return Default; + return getLocalOrGlobal(LocalName).getValueOr(Default); } /// Read a named option from the ``Context`` and parse it as an /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, returns a - /// ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a - /// ``UnparseableEnumOptionError``. + /// ``CheckOptions``. If the corresponding key is not present, return + /// ``None``. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return ``None``. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, llvm::Expected> + std::enable_if_t::value, llvm::Optional> get(StringRef LocalName, bool IgnoreCase = false) const { - if (llvm::Expected ValueOr = + if (llvm::Optional ValueOr = getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) return static_cast(*ValueOr); - else - return std::move(ValueOr.takeError()); + return None; } /// Read a named option from the ``Context`` and parse it as an /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present or it can't be - /// parsed as a ``T``, returns \p Default. + /// ``CheckOptions``. If the corresponding key is not present, return + /// \p Default. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return \p Default. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, T> get(StringRef LocalName, T Default, bool IgnoreCase = false) const { - if (auto ValueOr = get(LocalName, IgnoreCase)) - return *ValueOr; - else - reportOptionParsingError(ValueOr.takeError()); - return Default; + return get(LocalName, IgnoreCase).getValueOr(Default); } /// Read a named option from the ``Context`` and parse it as an @@ -373,19 +307,20 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 a ``MissingOptionError``. If the key can't be - /// parsed as a ``T`` returns a ``UnparseableEnumOptionError``. + /// present either, returns ``None``. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return ``None``. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, llvm::Expected> + std::enable_if_t::value, llvm::Optional> getLocalOrGlobal(StringRef LocalName, bool IgnoreCase = false) const { - if (llvm::Expected ValueOr = + if (llvm::Optional ValueOr = getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) return static_cast(*ValueOr); - else - return std::move(ValueOr.takeError()); + return None; } /// Read a named option from the ``Context`` and parse it as an @@ -394,7 +329,10 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 or it can't be parsed as a ``T``, returns \p Default. + /// present either return \p Default. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return \p Default. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. @@ -402,36 +340,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { std::enable_if_t::value, T> getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) const { - if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) - return *ValueOr; - else - reportOptionParsingError(ValueOr.takeError()); - return Default; - } - - /// Returns the value for the option \p LocalName represented as a ``T``. - /// If the option is missing returns None, if the option can't be parsed - /// as a ``T``, log that to stderr and return None. - template - llvm::Optional getOptional(StringRef LocalName) const { - if (auto ValueOr = get(LocalName)) - return *ValueOr; - else - reportOptionParsingError(ValueOr.takeError()); - return llvm::None; - } - - /// Returns the value for the local or global option \p LocalName - /// represented as a ``T``. - /// If the option is missing returns None, if the - /// option can't be parsed as a ``T``, log that to stderr and return None. - template - llvm::Optional getOptionalLocalOrGlobal(StringRef LocalName) const { - if (auto ValueOr = getLocalOrGlobal(LocalName)) - return *ValueOr; - else - reportOptionParsingError(ValueOr.takeError()); - return llvm::None; + return getLocalOrGlobal(LocalName, IgnoreCase).getValueOr(Default); } /// Stores an option with the check-local name \p LocalName with @@ -470,7 +379,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { private: using NameAndValue = std::pair; - llvm::Expected getEnumInt(StringRef LocalName, + llvm::Optional getEnumInt(StringRef LocalName, ArrayRef Mapping, bool CheckGlobal, bool IgnoreCase) const; @@ -491,8 +400,6 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, int64_t Value) const; - /// Emits a diagnostic if \p Err is not a MissingOptionError. - void reportOptionParsingError(llvm::Error &&Err) const; std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; @@ -516,44 +423,27 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// Read a named option from the ``Context`` and parse it as a bool. /// /// Reads the option with the check-local name \p LocalName from the -/// ``CheckOptions``. If the corresponding key is not present, returns -/// a ``MissingOptionError``. If the corresponding key can't be parsed as -/// a bool, return an ``UnparseableIntegerOptionError``. +/// ``CheckOptions``. If the corresponding key is not present, return +/// ``None``. +/// +/// If the corresponding key can't be parsed as a bool, emit a +/// diagnostic and return ``None``. template <> -llvm::Expected +llvm::Optional ClangTidyCheck::OptionsView::get(StringRef LocalName) const; /// Read a named option from the ``Context`` and parse it as a bool. /// /// Reads the option with the check-local name \p LocalName from the -/// ``CheckOptions``. If the corresponding key is not present or it can't be -/// parsed as a bool, returns \p Default. -template <> -bool ClangTidyCheck::OptionsView::get(StringRef LocalName, - bool Default) const; - -/// Read a named option from the ``Context`` and parse it as a bool. +/// ``CheckOptions``. If the corresponding key is not present, return +/// \p Default. /// -/// 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 a ``MissingOptionError``. If the corresponding -/// key can't be parsed as a bool, return an -/// ``UnparseableIntegerOptionError``. +/// If the corresponding key can't be parsed as a bool, emit a +/// diagnostic and return \p Default. template <> -llvm::Expected +llvm::Optional ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const; -/// Read a named option from the ``Context`` and parse it as a bool. -/// -/// 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 or it can't be parsed as a bool, returns \p Default. -template <> -bool ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName, - bool Default) const; - /// Stores an option with the check-local name \p LocalName with /// bool value \p Value to \p Options. template <> @@ -561,18 +451,6 @@ void ClangTidyCheck::OptionsView::store( ClangTidyOptions::OptionMap &Options, StringRef LocalName, bool Value) const; -/// Returns the value for the option \p LocalName. -/// If the option is missing returns None. -template <> -Optional ClangTidyCheck::OptionsView::getOptional( - StringRef LocalName) const; - -/// Returns the value for the local or global option \p LocalName. -/// If the option is missing returns None. -template <> -Optional -ClangTidyCheck::OptionsView::getOptionalLocalOrGlobal( - StringRef LocalName) const; } // namespace tidy } // namespace clang diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index 0792931..13372cc 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -226,6 +226,13 @@ bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info, ClangTidyContext &Context, bool AllowIO = true); +/// Gets the Fix attached to \p Diagnostic. +/// If there isn't a Fix attached to the diagnostic and \p AnyFix is true, Check +/// to see if exactly one note has a Fix and return it. Otherwise return +/// nullptr. +const llvm::StringMap * +getFixIt(const tooling::Diagnostic &Diagnostic, bool AnyFix); + /// A diagnostic consumer that turns each \c Diagnostic into a /// \c SourceManager-independent \c ClangTidyError. // @@ -235,7 +242,8 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { public: ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx, DiagnosticsEngine *ExternalDiagEngine = nullptr, - bool RemoveIncompatibleErrors = true); + bool RemoveIncompatibleErrors = true, + bool GetFixesFromNotes = false); // FIXME: The concept of converting between FixItHints and Replacements is // more generic and should be pulled out into a more useful Diagnostics @@ -265,6 +273,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { ClangTidyContext &Context; DiagnosticsEngine *ExternalDiagEngine; bool RemoveIncompatibleErrors; + bool GetFixesFromNotes; std::vector Errors; std::unique_ptr HeaderFilter; bool LastErrorRelatesToUserCode; diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index 176d5e8..d171944 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -127,6 +127,15 @@ well. )"), cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt FixNotes("fix-notes", cl::desc(R"( +If a warning has no fix, but a single fix can +be found through an associated diagnostic note, +apply the fix. +Specifying this flag will implicitly enable the +'--fix' flag. +)"), + cl::init(false), cl::cat(ClangTidyCategory)); + static cl::opt FormatStyle("format-style", cl::desc(R"( Style for formatting code around applied fixes: - 'none' (default) turns off formatting @@ -483,18 +492,22 @@ int clangTidyMain(int argc, const char **argv) { AllowEnablingAnalyzerAlphaCheckers); std::vector Errors = runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS, - EnableCheckProfile, ProfilePrefix); + FixNotes, EnableCheckProfile, ProfilePrefix); bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) { return E.DiagLevel == ClangTidyError::Error; }) != Errors.end(); - const bool DisableFixes = Fix && FoundErrors && !FixErrors; + // --fix-errors and --fix-notes imply --fix. + FixBehaviour Behaviour = FixNotes ? FB_FixNotes + : (Fix || FixErrors) ? FB_Fix + : FB_NoFix; + + const bool DisableFixes = FoundErrors && !FixErrors; unsigned WErrorCount = 0; - // -fix-errors implies -fix. - handleErrors(Errors, Context, (FixErrors || Fix) && !DisableFixes, WErrorCount, - BaseFS); + handleErrors(Errors, Context, DisableFixes ? FB_NoFix : Behaviour, + WErrorCount, BaseFS); if (!ExportFixes.empty() && !Errors.empty()) { std::error_code EC; @@ -508,7 +521,7 @@ int clangTidyMain(int argc, const char **argv) { if (!Quiet) { printStats(Context.getStats()); - if (DisableFixes) + if (DisableFixes && Behaviour != FB_NoFix) llvm::errs() << "Found compiler errors, but -fix-errors was not specified.\n" "Fixes have NOT been applied.\n\n"; From a22935e5c83433d7f5bf23fc91348b409a710f5d Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 28 Feb 2023 23:52:55 +0100 Subject: [PATCH 12/20] Bump to Clang 15 --- ClangTidy.h | 11 ++- ClangTidyCheck.h | 28 ++++--- ClangTidyDiagnosticConsumer.h | 88 +++++++++++++--------- ClangTidyModule.h | 4 + ClangTidyOptions.h | 6 +- GlobList.h | 28 +++++-- NoLintDirectiveHandler.h | 51 +++++++++++++ aliceO2/NamespaceNamingCheck.cpp | 2 +- tool/ClangTidyMain.cpp | 125 +++++++++++++++++++++++++++++-- 9 files changed, 278 insertions(+), 65 deletions(-) create mode 100644 NoLintDirectiveHandler.h diff --git a/ClangTidy.h b/ClangTidy.h index bbe4fe6..51d9e22 100644 --- a/ClangTidy.h +++ b/ClangTidy.h @@ -11,6 +11,7 @@ #include "ClangTidyDiagnosticConsumer.h" #include "ClangTidyOptions.h" +#include "llvm/ADT/StringSet.h" #include #include @@ -38,7 +39,7 @@ class ClangTidyASTConsumerFactory { /// Returns an ASTConsumer that runs the specified clang-tidy checks. std::unique_ptr - CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File); + createASTConsumer(clang::CompilerInstance &Compiler, StringRef File); /// Get the list of enabled checks. std::vector getCheckNames(); @@ -57,6 +58,14 @@ class ClangTidyASTConsumerFactory { std::vector 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 diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h index 20e9b8e..abf528d 100644 --- a/ClangTidyCheck.h +++ b/ClangTidyCheck.h @@ -20,7 +20,6 @@ namespace clang { -class CompilerInstance; class SourceManager; namespace tidy { @@ -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. @@ -156,14 +155,14 @@ 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 get(StringRef LocalName) const; + llvm::Optional 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``. /// @@ -171,7 +170,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 getLocalOrGlobal(StringRef LocalName) const; + llvm::Optional getLocalOrGlobal(StringRef LocalName) const; /// Read a named option from the ``Context``. /// @@ -179,7 +178,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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``. @@ -193,7 +192,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { template std::enable_if_t::value, llvm::Optional> get(StringRef LocalName) const { - if (llvm::Optional Value = get(LocalName)) { + if (llvm::Optional Value = get(LocalName)) { T Result{}; if (!StringRef(*Value).getAsInteger(10, Result)) return Result; @@ -214,7 +213,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { template std::enable_if_t::value, T> get(StringRef LocalName, T Default) const { - return get(LocalName).getValueOr(Default); + return get(LocalName).value_or(Default); } /// Read a named option from the ``Context`` and parse it as an @@ -230,7 +229,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { template std::enable_if_t::value, llvm::Optional> getLocalOrGlobal(StringRef LocalName) const { - llvm::Optional ValueOr = get(LocalName); + llvm::Optional ValueOr = get(LocalName); bool IsGlobal = false; if (!ValueOr) { IsGlobal = true; @@ -259,7 +258,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { template std::enable_if_t::value, T> getLocalOrGlobal(StringRef LocalName, T Default) const { - return getLocalOrGlobal(LocalName).getValueOr(Default); + return getLocalOrGlobal(LocalName).value_or(Default); } /// Read a named option from the ``Context`` and parse it as an @@ -298,7 +297,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { template std::enable_if_t::value, T> get(StringRef LocalName, T Default, bool IgnoreCase = false) const { - return get(LocalName, IgnoreCase).getValueOr(Default); + return get(LocalName, IgnoreCase).value_or(Default); } /// Read a named option from the ``Context`` and parse it as an @@ -340,7 +339,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { std::enable_if_t::value, T> getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) const { - return getLocalOrGlobal(LocalName, IgnoreCase).getValueOr(Default); + return getLocalOrGlobal(LocalName, IgnoreCase).value_or(Default); } /// Stores an option with the check-local name \p LocalName with @@ -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. diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index 13372cc..261e4f7 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -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. @@ -45,18 +41,13 @@ struct ClangTidyError : tooling::Diagnostic { std::vector 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 + @@ -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 &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. @@ -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; } @@ -175,6 +188,10 @@ class ClangTidyContext { return AllowEnablingAnalyzerAlphaCheckers; } + void setSelfContainedDiags(bool Value) { SelfContainedDiags = Value; } + + bool areDiagsSelfContained() const { return SelfContainedDiags; } + using DiagLevelAndFormatString = std::pair; DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, SourceLocation Loc) { @@ -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; @@ -194,7 +216,7 @@ class ClangTidyContext { std::string CurrentFile; ClangTidyOptions CurrentOptions; - class CachedGlobList; + std::unique_ptr CheckFilter; std::unique_ptr WarningAsErrorFilter; @@ -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 @@ -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 @@ -274,6 +289,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { DiagnosticsEngine *ExternalDiagEngine; bool RemoveIncompatibleErrors; bool GetFixesFromNotes; + bool EnableNolintBlocks; std::vector Errors; std::unique_ptr HeaderFilter; bool LastErrorRelatesToUserCode; diff --git a/ClangTidyModule.h b/ClangTidyModule.h index dd21a8d..f44457d 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -67,6 +67,10 @@ class ClangTidyCheckFactories { std::vector> createChecks(ClangTidyContext *Context); + /// Create instances of checks that are enabled for the current Language. + std::vector> + createChecksForLanguage(ClangTidyContext *Context); + typedef llvm::StringMap FactoryMap; FactoryMap::const_iterator begin() const { return Factories.begin(); } FactoryMap::const_iterator end() const { return Factories.end(); } diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index d8a4a14..3f09d39 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -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 StringPair; @@ -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 InheritParentConfig; diff --git a/GlobList.h b/GlobList.h index fe68a34..3eec92e 100644 --- a/GlobList.h +++ b/GlobList.h @@ -11,6 +11,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" @@ -24,19 +25,23 @@ namespace tidy { /// them in the order of appearance in the list. class GlobList { public: + virtual ~GlobList() = default; + /// \p Globs is a comma-separated list of globs (only the '*' metacharacter is /// supported) with an optional '-' prefix to denote exclusion. /// /// An empty \p Globs string is interpreted as one glob that matches an empty /// string. - GlobList(StringRef Globs); + /// + /// \p KeepNegativeGlobs a bool flag indicating whether to keep negative + /// globs from \p Globs or not. When false, negative globs are simply ignored. + GlobList(StringRef Globs, bool KeepNegativeGlobs = true); /// Returns \c true if the pattern matches \p S. The result is the last /// matching glob's Positive flag. - bool contains(StringRef S) const; + virtual bool contains(StringRef S) const; private: - struct GlobListItem { bool IsPositive; llvm::Regex Regex; @@ -44,7 +49,20 @@ class GlobList { SmallVector Items; }; -} // end namespace tidy -} // end namespace clang +/// A \p GlobList that caches search results, so that search is performed only +/// once for the same query. +class CachedGlobList final : public GlobList { +public: + using GlobList::GlobList; + + /// \see GlobList::contains + bool contains(StringRef S) const override; + +private: + mutable llvm::StringMap Cache; +}; + +} // namespace tidy +} // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H diff --git a/NoLintDirectiveHandler.h b/NoLintDirectiveHandler.h new file mode 100644 index 0000000..db9fd59 --- /dev/null +++ b/NoLintDirectiveHandler.h @@ -0,0 +1,51 @@ +//===-- clang-tools-extra/clang-tidy/NoLintDirectiveHandler.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_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace clang { +namespace tooling { +struct Diagnostic; +} // namespace tooling +} // namespace clang + +namespace llvm { +template class SmallVectorImpl; +} // namespace llvm + +namespace clang { +namespace tidy { + +/// This class is used to locate NOLINT comments in the file being analyzed, to +/// decide whether a diagnostic should be suppressed. +/// This class keeps a cache of every NOLINT comment found so that files do not +/// have to be repeatedly parsed each time a new diagnostic is raised. +class NoLintDirectiveHandler { +public: + NoLintDirectiveHandler(); + ~NoLintDirectiveHandler(); + + bool shouldSuppress(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Diag, llvm::StringRef DiagName, + llvm::SmallVectorImpl &NoLintErrors, + bool AllowIO, bool EnableNoLintBlocks); + +private: + class Impl; + std::unique_ptr PImpl; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H diff --git a/aliceO2/NamespaceNamingCheck.cpp b/aliceO2/NamespaceNamingCheck.cpp index edd94d2..ca9790a 100644 --- a/aliceO2/NamespaceNamingCheck.cpp +++ b/aliceO2/NamespaceNamingCheck.cpp @@ -143,7 +143,7 @@ void NamespaceNamingCheck::check(const MatchFinder::MatchResult &Result) { bool NamespaceNamingCheck::fixNamespaceName(std::string &name) { - std::string replace_option = Options.get(name, ""); + std::string replace_option = Options.get(name, "").str(); if( replace_option != "" ) { name = replace_option; diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index d171944..6e9618d 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -19,7 +19,9 @@ #include "../ClangTidyForceLinker.h" #include "../GlobList.h" #include "clang/Tooling/CommonOptionsParser.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/PluginLoader.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" @@ -50,8 +52,7 @@ Configuration files: InheritParentConfig: true User: user CheckOptions: - - key: some-check.SomeOption - value: 'some value' + some-check.SomeOption: 'some value' ... )"); @@ -169,8 +170,7 @@ line or a specific configuration file. static cl::opt Config("config", cl::desc(R"( Specifies a configuration in YAML/JSON format: -config="{Checks: '*', - CheckOptions: [{key: x, - value: y}]}" + CheckOptions: {x: y}}" When the value is empty, clang-tidy will attempt to find a file named .clang-tidy for each source file in its parent directories. @@ -256,6 +256,12 @@ This option overrides the 'UseColor' option in )"), cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt VerifyConfig("verify-config", cl::desc(R"( +Check the config files to ensure each check and +option is recognized. +)"), + cl::init(false), cl::cat(ClangTidyCategory)); + namespace clang { namespace tidy { @@ -384,8 +390,81 @@ getVfsFromFile(const std::string &OverlayFile, return FS; } +static StringRef closest(StringRef Value, const StringSet<> &Allowed) { + unsigned MaxEdit = 5U; + StringRef Closest; + for (auto Item : Allowed.keys()) { + unsigned Cur = Value.edit_distance_insensitive(Item, true, MaxEdit); + if (Cur < MaxEdit) { + Closest = Item; + MaxEdit = Cur; + } + } + return Closest; +} + +static constexpr StringLiteral VerifyConfigWarningEnd = " [-verify-config]\n"; + +static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob, + StringRef Source) { + llvm::StringRef Cur, Rest; + bool AnyInvalid = false; + for (std::tie(Cur, Rest) = CheckGlob.split(','); + !(Cur.empty() && Rest.empty()); std::tie(Cur, Rest) = Rest.split(',')) { + Cur = Cur.trim(); + if (Cur.empty()) + continue; + Cur.consume_front("-"); + if (Cur.startswith("clang-diagnostic")) + continue; + if (Cur.contains('*')) { + SmallString<128> RegexText("^"); + StringRef MetaChars("()^$|*+?.[]\\{}"); + for (char C : Cur) { + if (C == '*') + RegexText.push_back('.'); + else if (MetaChars.contains(C)) + RegexText.push_back('\\'); + RegexText.push_back(C); + } + RegexText.push_back('$'); + llvm::Regex Glob(RegexText); + std::string Error; + if (!Glob.isValid(Error)) { + AnyInvalid = true; + llvm::WithColor::error(llvm::errs(), Source) + << "building check glob '" << Cur << "' " << Error << "'\n"; + continue; + } + if (llvm::none_of(AllChecks.keys(), + [&Glob](StringRef S) { return Glob.match(S); })) { + AnyInvalid = true; + llvm::WithColor::warning(llvm::errs(), Source) + << "check glob '" << Cur << "' doesn't match any known check" + << VerifyConfigWarningEnd; + } + } else { + if (AllChecks.contains(Cur)) + continue; + AnyInvalid = true; + llvm::raw_ostream &Output = llvm::WithColor::warning(llvm::errs(), Source) + << "unknown check '" << Cur << '\''; + llvm::StringRef Closest = closest(Cur, AllChecks); + if (!Closest.empty()) + Output << "; did you mean '" << Closest << '\''; + Output << VerifyConfigWarningEnd; + } + } + return AnyInvalid; +} + int clangTidyMain(int argc, const char **argv) { llvm::InitLLVM X(argc, argv); + + // Enable help for -load option, if plugins are enabled. + if (cl::Option *LoadOpt = cl::getRegisteredOptions().lookup("load")) + LoadOpt->addCategory(ClangTidyCategory); + llvm::Expected OptionsParser = CommonOptionsParser::create(argc, argv, ClangTidyCategory, cl::ZeroOrMore); @@ -472,6 +551,38 @@ int clangTidyMain(int argc, const char **argv) { return 0; } + if (VerifyConfig) { + std::vector RawOptions = + OptionsProvider->getRawOptions(FileName); + NamesAndOptions Valid = + getAllChecksAndOptions(AllowEnablingAnalyzerAlphaCheckers); + bool AnyInvalid = false; + for (const std::pair &OptionWithSource : + RawOptions) { + const ClangTidyOptions &Opts = OptionWithSource.first; + if (Opts.Checks) + AnyInvalid |= + verifyChecks(Valid.Names, *Opts.Checks, OptionWithSource.second); + + for (auto Key : Opts.CheckOptions.keys()) { + if (Valid.Options.contains(Key)) + continue; + AnyInvalid = true; + auto &Output = + llvm::WithColor::warning(llvm::errs(), OptionWithSource.second) + << "unknown check option '" << Key << '\''; + llvm::StringRef Closest = closest(Key, Valid.Options); + if (!Closest.empty()) + Output << "; did you mean '" << Closest << '\''; + Output << VerifyConfigWarningEnd; + } + } + if (AnyInvalid) + return 1; + llvm::outs() << "No config errors detected.\n"; + return 0; + } + if (EnabledChecks.empty()) { llvm::errs() << "Error: no checks enabled.\n"; llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); @@ -493,9 +604,9 @@ int clangTidyMain(int argc, const char **argv) { std::vector Errors = runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS, FixNotes, EnableCheckProfile, ProfilePrefix); - bool FoundErrors = llvm::find_if(Errors, [](const ClangTidyError &E) { - return E.DiagLevel == ClangTidyError::Error; - }) != Errors.end(); + bool FoundErrors = llvm::any_of(Errors, [](const ClangTidyError &E) { + return E.DiagLevel == ClangTidyError::Error; + }); // --fix-errors and --fix-notes imply --fix. FixBehaviour Behaviour = FixNotes ? FB_FixNotes From 1f7dc38543c634d0ad9851e992326dde87a9ce3f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 9 Aug 2024 18:55:57 +0200 Subject: [PATCH 13/20] Bump to LLVM 17.0.6 --- ClangTidyCheck.h | 68 +++++++++++++++++------------------ ClangTidyDiagnosticConsumer.h | 15 +++++++- ClangTidyForceLinker.h | 6 ++-- ClangTidyModule.h | 10 +++--- ClangTidyModuleRegistry.h | 6 ++-- ClangTidyOptions.h | 48 ++++++++++++++----------- ClangTidyProfiling.h | 14 ++++---- FileExtensionsSet.h | 19 ++++++++++ GlobList.h | 6 ++-- NoLintDirectiveHandler.h | 12 +++---- tool/CMakeLists.txt | 4 ++- 11 files changed, 117 insertions(+), 91 deletions(-) create mode 100644 FileExtensionsSet.h diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h index abf528d..17e9df9 100644 --- a/ClangTidyCheck.h +++ b/ClangTidyCheck.h @@ -13,7 +13,7 @@ #include "ClangTidyOptions.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/Optional.h" +#include #include #include #include @@ -154,8 +154,8 @@ 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 get(StringRef LocalName) const; + /// ``std::nullopt``. + std::optional get(StringRef LocalName) const; /// Read a named option from the ``Context``. /// @@ -169,8 +169,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 getLocalOrGlobal(StringRef LocalName) const; + /// present either, return ``std::nullopt``. + std::optional getLocalOrGlobal(StringRef LocalName) const; /// Read a named option from the ``Context``. /// @@ -185,20 +185,20 @@ 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``. + /// ``std::nullopt``. /// /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``None``. + /// diagnostic and return ``std::nullopt``. template - std::enable_if_t::value, llvm::Optional> + std::enable_if_t::value, std::optional> get(StringRef LocalName) const { - if (llvm::Optional Value = get(LocalName)) { + if (std::optional Value = get(LocalName)) { T Result{}; if (!StringRef(*Value).getAsInteger(10, Result)) return Result; diagnoseBadIntegerOption(NamePrefix + LocalName, *Value); } - return None; + return std::nullopt; } /// Read a named option from the ``Context`` and parse it as an @@ -222,27 +222,27 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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``. + /// present either, return ``std::nullopt``. /// /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``None``. + /// diagnostic and return ``std::nullopt``. template - std::enable_if_t::value, llvm::Optional> + std::enable_if_t::value, std::optional> getLocalOrGlobal(StringRef LocalName) const { - llvm::Optional ValueOr = get(LocalName); + std::optional ValueOr = get(LocalName); bool IsGlobal = false; if (!ValueOr) { IsGlobal = true; ValueOr = getLocalOrGlobal(LocalName); if (!ValueOr) - return None; + return std::nullopt; } T Result{}; if (!StringRef(*ValueOr).getAsInteger(10, Result)) return Result; diagnoseBadIntegerOption( IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr); - return None; + return std::nullopt; } /// Read a named option from the ``Context`` and parse it as an @@ -266,20 +266,20 @@ 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``. + /// ``std::nullopt``. /// /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``None``. + /// diagnostic and return ``std::nullopt``. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, llvm::Optional> + std::enable_if_t::value, std::optional> get(StringRef LocalName, bool IgnoreCase = false) const { - if (llvm::Optional ValueOr = + if (std::optional ValueOr = getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) return static_cast(*ValueOr); - return None; + return std::nullopt; } /// Read a named option from the ``Context`` and parse it as an @@ -306,20 +306,20 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// 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 ``None``. + /// present either, returns ``std::nullopt``. /// /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``None``. + /// diagnostic and return ``std::nullopt``. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, llvm::Optional> + std::enable_if_t::value, std::optional> getLocalOrGlobal(StringRef LocalName, bool IgnoreCase = false) const { - if (llvm::Optional ValueOr = + if (std::optional ValueOr = getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) return static_cast(*ValueOr); - return None; + return std::nullopt; } /// Read a named option from the ``Context`` and parse it as an @@ -378,9 +378,9 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { private: using NameAndValue = std::pair; - llvm::Optional getEnumInt(StringRef LocalName, - ArrayRef Mapping, - bool CheckGlobal, bool IgnoreCase) const; + std::optional getEnumInt(StringRef LocalName, + ArrayRef Mapping, + bool CheckGlobal, bool IgnoreCase) const; template std::enable_if_t::value, std::vector> @@ -407,7 +407,6 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { private: void run(const ast_matchers::MatchFinder::MatchResult &Result) override; - StringRef getID() const override { return CheckName; } std::string CheckName; ClangTidyContext *Context; @@ -422,18 +421,19 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { bool areDiagsSelfContained() const { return Context->areDiagsSelfContained(); } + StringRef getID() const override { return CheckName; } }; /// Read a named option from the ``Context`` and parse it as a bool. /// /// Reads the option with the check-local name \p LocalName from the /// ``CheckOptions``. If the corresponding key is not present, return -/// ``None``. +/// ``std::nullopt``. /// /// If the corresponding key can't be parsed as a bool, emit a -/// diagnostic and return ``None``. +/// diagnostic and return ``std::nullopt``. template <> -llvm::Optional +std::optional ClangTidyCheck::OptionsView::get(StringRef LocalName) const; /// Read a named option from the ``Context`` and parse it as a bool. @@ -445,7 +445,7 @@ ClangTidyCheck::OptionsView::get(StringRef LocalName) const; /// If the corresponding key can't be parsed as a bool, emit a /// diagnostic and return \p Default. template <> -llvm::Optional +std::optional ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const; /// Stores an option with the check-local name \p LocalName with diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index 261e4f7..15f1b67 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -11,12 +11,14 @@ #include "ClangTidyOptions.h" #include "ClangTidyProfiling.h" +#include "FileExtensionsSet.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" +#include namespace clang { @@ -159,6 +161,14 @@ class ClangTidyContext { /// \c CurrentFile. ClangTidyOptions getOptionsForFile(StringRef File) const; + const FileExtensionsSet &getHeaderFileExtensions() const { + return HeaderFileExtensions; + } + + const FileExtensionsSet &getImplementationFileExtensions() const { + return ImplementationFileExtensions; + } + /// Returns \c ClangTidyStats containing issued and ignored diagnostic /// counters. const ClangTidyStats &getStats() const { return Stats; } @@ -169,7 +179,7 @@ class ClangTidyContext { /// Control storage of profile date. void setProfileStoragePrefix(StringRef ProfilePrefix); - llvm::Optional + std::optional getProfileStorageParams() const; /// Should be called when starting to process new translation unit. @@ -220,6 +230,9 @@ class ClangTidyContext { std::unique_ptr CheckFilter; std::unique_ptr WarningAsErrorFilter; + FileExtensionsSet HeaderFileExtensions; + FileExtensionsSet ImplementationFileExtensions; + LangOptions LangOpts; ClangTidyStats Stats; diff --git a/ClangTidyForceLinker.h b/ClangTidyForceLinker.h index 2691d90..adde913 100644 --- a/ClangTidyForceLinker.h +++ b/ClangTidyForceLinker.h @@ -12,8 +12,7 @@ #include "clang-tidy-config.h" #include "llvm/Support/Compiler.h" -namespace clang { -namespace tidy { +namespace clang::tidy { // This anchor is used to force the linker to link the AbseilModule. extern volatile int AbseilModuleAnchorSource; @@ -138,7 +137,6 @@ extern volatile int ZirconModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination = ZirconModuleAnchorSource; -} // namespace tidy -} // namespace clang +} // namespace clang::tidy #endif diff --git a/ClangTidyModule.h b/ClangTidyModule.h index f44457d..0e55c1e 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -15,8 +15,7 @@ #include #include -namespace clang { -namespace tidy { +namespace clang::tidy { class ClangTidyCheck; class ClangTidyContext; @@ -65,11 +64,11 @@ class ClangTidyCheckFactories { /// Create instances of checks that are enabled. std::vector> - createChecks(ClangTidyContext *Context); + createChecks(ClangTidyContext *Context) const; /// Create instances of checks that are enabled for the current Language. std::vector> - createChecksForLanguage(ClangTidyContext *Context); + createChecksForLanguage(ClangTidyContext *Context) const; typedef llvm::StringMap FactoryMap; FactoryMap::const_iterator begin() const { return Factories.begin(); } @@ -94,7 +93,6 @@ class ClangTidyModule { virtual ClangTidyOptions getModuleOptions(); }; -} // end namespace tidy -} // end namespace clang +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H diff --git a/ClangTidyModuleRegistry.h b/ClangTidyModuleRegistry.h index 891671a..30ffe18 100644 --- a/ClangTidyModuleRegistry.h +++ b/ClangTidyModuleRegistry.h @@ -12,12 +12,10 @@ #include "ClangTidyModule.h" #include "llvm/Support/Registry.h" -namespace clang { -namespace tidy { +namespace clang::tidy { typedef llvm::Registry ClangTidyModuleRegistry; -} // end namespace tidy -} // end namespace clang +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index 3f09d39..b3b7143 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -10,20 +10,19 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/VirtualFileSystem.h" #include +#include #include #include #include #include -namespace clang { -namespace tidy { +namespace clang::tidy { /// Contains a list of line ranges in a single file. struct FileFilter { @@ -63,21 +62,29 @@ struct ClangTidyOptions { /// Creates a new \c ClangTidyOptions instance combined from all fields /// of this instance overridden by the fields of \p Other that have a value. /// \p Order specifies precedence of \p Other option. - LLVM_NODISCARD ClangTidyOptions merge(const ClangTidyOptions &Other, - unsigned Order) const; + [[nodiscard]] ClangTidyOptions merge(const ClangTidyOptions &Other, + unsigned Order) const; /// Checks filter. - llvm::Optional Checks; + std::optional Checks; /// WarningsAsErrors filter. - llvm::Optional WarningsAsErrors; + std::optional WarningsAsErrors; + + /// File extensions to consider to determine if a given diagnostic is located + /// in a header file. + std::optional> HeaderFileExtensions; + + /// File extensions to consider to determine if a given diagnostic is located + /// is located in an implementation file. + std::optional> ImplementationFileExtensions; /// Output warnings from headers matching this filter. Warnings from /// main files will always be displayed. - llvm::Optional HeaderFilterRegex; + std::optional HeaderFilterRegex; /// Output warnings from system headers matching \c HeaderFilterRegex. - llvm::Optional SystemHeaders; + std::optional SystemHeaders; /// Format code around applied fixes with clang-format using this /// style. @@ -91,25 +98,25 @@ struct ClangTidyOptions { /// * '{inline-formatting-style-in-yaml-format}'. /// /// See clang-format documentation for more about configuring format style. - llvm::Optional FormatStyle; + std::optional FormatStyle; /// Specifies the name or e-mail of the user running clang-tidy. /// /// This option is used, for example, to place the correct user name in TODO() /// comments in the relevant check. - llvm::Optional User; + std::optional User; /// Helper structure for storing option value with priority of the value. struct ClangTidyValue { - ClangTidyValue() : Value(), Priority(0) {} - ClangTidyValue(const char *Value) : Value(Value), Priority(0) {} + ClangTidyValue() = default; + ClangTidyValue(const char *Value) : Value(Value) {} ClangTidyValue(llvm::StringRef Value, unsigned Priority = 0) : Value(Value), Priority(Priority) {} std::string Value; /// Priority stores relative precedence of the value loaded from config /// files to disambiguate local vs global value from different levels. - unsigned Priority; + unsigned Priority = 0; }; typedef std::pair StringPair; typedef llvm::StringMap OptionMap; @@ -120,10 +127,10 @@ struct ClangTidyOptions { typedef std::vector ArgList; /// Add extra compilation arguments to the end of the list. - llvm::Optional ExtraArgs; + std::optional ExtraArgs; /// Add extra compilation arguments to the start of the list. - llvm::Optional ExtraArgsBefore; + std::optional ExtraArgsBefore; /// Only used in the FileOptionsProvider and ConfigOptionsProvider. If true /// and using a FileOptionsProvider, it will take a configuration file in the @@ -132,10 +139,10 @@ struct ClangTidyOptions { /// 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 InheritParentConfig; + std::optional InheritParentConfig; /// Use colors in diagnostics. If missing, it will be auto detected. - llvm::Optional UseColor; + std::optional UseColor; }; /// Abstract interface for retrieving various ClangTidy options. @@ -231,7 +238,7 @@ class FileOptionsBaseProvider : public DefaultOptionsProvider { /// Try to read configuration files from \p Directory using registered /// \c ConfigHandlers. - llvm::Optional tryReadConfigFile(llvm::StringRef Directory); + std::optional tryReadConfigFile(llvm::StringRef Directory); llvm::StringMap CachedOptions; ClangTidyOptions OverrideOptions; @@ -320,7 +327,6 @@ parseConfigurationWithDiags(llvm::MemoryBufferRef Config, DiagCallback Handler); /// Serializes configuration to a YAML-encoded string. std::string configurationAsText(const ClangTidyOptions &Options); -} // end namespace tidy -} // end namespace clang +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H diff --git a/ClangTidyProfiling.h b/ClangTidyProfiling.h index 9487a34..b6f7d66 100644 --- a/ClangTidyProfiling.h +++ b/ClangTidyProfiling.h @@ -9,18 +9,17 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/Timer.h" +#include #include namespace llvm { class raw_ostream; } // namespace llvm -namespace clang { -namespace tidy { +namespace clang::tidy { class ClangTidyProfiling { public: @@ -35,9 +34,9 @@ class ClangTidyProfiling { }; private: - llvm::Optional TG; + std::optional TG; - llvm::Optional Storage; + std::optional Storage; void printUserFriendlyTable(llvm::raw_ostream &OS); void printAsJSON(llvm::raw_ostream &OS); @@ -49,12 +48,11 @@ class ClangTidyProfiling { ClangTidyProfiling() = default; - ClangTidyProfiling(llvm::Optional Storage); + ClangTidyProfiling(std::optional Storage); ~ClangTidyProfiling(); }; -} // end namespace tidy -} // end namespace clang +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H diff --git a/FileExtensionsSet.h b/FileExtensionsSet.h new file mode 100644 index 0000000..417b1b6 --- /dev/null +++ b/FileExtensionsSet.h @@ -0,0 +1,19 @@ +//===--- FileExtensionsSet.h - clang-tidy -----------------------*- 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_CLANG_TIDY_FILE_EXTENSIONS_SET_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FILE_EXTENSIONS_SET_H + +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringRef.h" + +namespace clang::tidy { +typedef llvm::SmallSet FileExtensionsSet; +} // namespace clang::tidy + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FILE_EXTENSIONS_SET_H diff --git a/GlobList.h b/GlobList.h index 3eec92e..44af182 100644 --- a/GlobList.h +++ b/GlobList.h @@ -15,8 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" -namespace clang { -namespace tidy { +namespace clang::tidy { /// Read-only set of strings represented as a list of positive and negative /// globs. @@ -62,7 +61,6 @@ class CachedGlobList final : public GlobList { mutable llvm::StringMap Cache; }; -} // namespace tidy -} // namespace clang +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H diff --git a/NoLintDirectiveHandler.h b/NoLintDirectiveHandler.h index db9fd59..e862195 100644 --- a/NoLintDirectiveHandler.h +++ b/NoLintDirectiveHandler.h @@ -13,18 +13,15 @@ #include "llvm/ADT/StringRef.h" #include -namespace clang { -namespace tooling { +namespace clang::tooling { struct Diagnostic; -} // namespace tooling -} // namespace clang +} // namespace clang::tooling namespace llvm { template class SmallVectorImpl; } // namespace llvm -namespace clang { -namespace tidy { +namespace clang::tidy { /// This class is used to locate NOLINT comments in the file being analyzed, to /// decide whether a diagnostic should be suppressed. @@ -45,7 +42,6 @@ class NoLintDirectiveHandler { std::unique_ptr PImpl; }; -} // namespace tidy -} // namespace clang +} // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt index 4d00fa4..5d9de7e 100644 --- a/tool/CMakeLists.txt +++ b/tool/CMakeLists.txt @@ -57,7 +57,9 @@ install(PROGRAMS run_O2CodeChecker.py DESTINATION bin) # we need to install the builtin headers in a path which is searched by the tool # FIXME: a soft link would be better -install(DIRECTORY ${LLVM_LIBRARY_DIR}/clang/${LLVM_PACKAGE_VERSION}/include DESTINATION lib/clang/${LLVM_PACKAGE_VERSION}) +string(REPLACE "." ";" LLVM_PACKAGE_VERSION_LIST ${LLVM_PACKAGE_VERSION}) +list(GET LLVM_PACKAGE_VERSION_LIST 0 LLVM_PACKAGE_VERSION_MAJOR) +install(DIRECTORY ${LLVM_LIBRARY_DIR}/clang/${LLVM_PACKAGE_VERSION_MAJOR}/include DESTINATION lib/clang/${LLVM_PACKAGE_VERSION_MAJOR}) IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # On MacOS we need to do the same with C++ headers since they are in a non-standard location From d2738dda59553b70dd642d10c3718119e8d0a536 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 20 Aug 2024 17:21:08 +0200 Subject: [PATCH 14/20] Bump to LLVM 18.1.8 --- ClangTidyCheck.h | 105 ++++++++++++++++++++++++++++------ ClangTidyDiagnosticConsumer.h | 30 ++++++---- ClangTidyModule.h | 2 +- ClangTidyModuleRegistry.h | 2 +- ClangTidyOptions.h | 17 +++--- FileExtensionsSet.h | 2 +- 6 files changed, 117 insertions(+), 41 deletions(-) diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h index 17e9df9..656a2f0 100644 --- a/ClangTidyCheck.h +++ b/ClangTidyCheck.h @@ -184,13 +184,13 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// integral type ``T``. /// /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, return - /// ``std::nullopt``. + /// ``CheckOptions``. If the corresponding key is not present, + /// return ``std::nullopt``. /// /// If the corresponding key can't be parsed as a ``T``, emit a /// diagnostic and return ``std::nullopt``. template - std::enable_if_t::value, std::optional> + std::enable_if_t, std::optional> get(StringRef LocalName) const { if (std::optional Value = get(LocalName)) { T Result{}; @@ -201,6 +201,31 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { return std::nullopt; } + /// Read a named option from the ``Context`` and parse it as an + /// integral type ``T``. + /// + /// Reads the option with the check-local name \p LocalName from the + /// ``CheckOptions``. If the corresponding key is `none`, `null`, + /// `-1` or empty, return ``std::nullopt``. If the corresponding + /// key is not present, return \p Default. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return \p Default. + template + std::enable_if_t, std::optional> + get(StringRef LocalName, std::optional Default) const { + if (std::optional Value = get(LocalName)) { + if (Value == "" || Value == "none" || Value == "null" || + (std::is_unsigned_v && Value == "-1")) + return std::nullopt; + T Result{}; + if (!StringRef(*Value).getAsInteger(10, Result)) + return Result; + diagnoseBadIntegerOption(NamePrefix + LocalName, *Value); + } + return Default; + } + /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. /// @@ -211,8 +236,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// If the corresponding key can't be parsed as a ``T``, emit a /// diagnostic and return \p Default. template - std::enable_if_t::value, T> get(StringRef LocalName, - T Default) const { + std::enable_if_t, T> get(StringRef LocalName, + T Default) const { return get(LocalName).value_or(Default); } @@ -227,7 +252,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// If the corresponding key can't be parsed as a ``T``, emit a /// diagnostic and return ``std::nullopt``. template - std::enable_if_t::value, std::optional> + std::enable_if_t, std::optional> getLocalOrGlobal(StringRef LocalName) const { std::optional ValueOr = get(LocalName); bool IsGlobal = false; @@ -245,6 +270,39 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { return std::nullopt; } + /// Read a named option from the ``Context`` and parse it as an + /// integral type ``T``. + /// + /// 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 \p Default. If the value value was found + /// and equals ``none``, ``null``, ``-1`` or empty, return ``std::nullopt``. + /// + /// If the corresponding key can't be parsed as a ``T``, emit a + /// diagnostic and return \p Default. + template + std::enable_if_t, std::optional> + getLocalOrGlobal(StringRef LocalName, std::optional Default) const { + std::optional ValueOr = get(LocalName); + bool IsGlobal = false; + if (!ValueOr) { + IsGlobal = true; + ValueOr = getLocalOrGlobal(LocalName); + if (!ValueOr) + return Default; + } + T Result{}; + if (ValueOr == "" || ValueOr == "none" || ValueOr == "null" || + (std::is_unsigned_v && ValueOr == "-1")) + return std::nullopt; + if (!StringRef(*ValueOr).getAsInteger(10, Result)) + return Result; + diagnoseBadIntegerOption( + IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr); + return Default; + } + /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. /// @@ -256,7 +314,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// If the corresponding key can't be parsed as a ``T``, emit a /// diagnostic and return \p Default. template - std::enable_if_t::value, T> + std::enable_if_t, T> getLocalOrGlobal(StringRef LocalName, T Default) const { return getLocalOrGlobal(LocalName).value_or(Default); } @@ -274,7 +332,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, std::optional> + std::enable_if_t, std::optional> get(StringRef LocalName, bool IgnoreCase = false) const { if (std::optional ValueOr = getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) @@ -286,8 +344,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, return - /// \p Default. + /// ``CheckOptions``. If the corresponding key is not present, + /// return \p Default. /// /// If the corresponding key can't be parsed as a ``T``, emit a /// diagnostic and return \p Default. @@ -295,8 +353,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, T> - get(StringRef LocalName, T Default, bool IgnoreCase = false) const { + std::enable_if_t, T> get(StringRef LocalName, T Default, + bool IgnoreCase = false) const { return get(LocalName, IgnoreCase).value_or(Default); } @@ -314,7 +372,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, std::optional> + std::enable_if_t, std::optional> getLocalOrGlobal(StringRef LocalName, bool IgnoreCase = false) const { if (std::optional ValueOr = getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) @@ -336,7 +394,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value, T> + std::enable_if_t, T> getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) const { return getLocalOrGlobal(LocalName, IgnoreCase).value_or(Default); @@ -350,19 +408,32 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { /// Stores an option with the check-local name \p LocalName with /// integer value \p Value to \p Options. template - std::enable_if_t::value> + std::enable_if_t> store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) const { storeInt(Options, LocalName, Value); } + /// Stores an option with the check-local name \p LocalName with + /// integer value \p Value to \p Options. If the value is empty + /// stores `` + template + std::enable_if_t> + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + std::optional Value) const { + if (Value) + storeInt(Options, LocalName, *Value); + else + store(Options, LocalName, "none"); + } + /// Stores an option with the check-local name \p LocalName as the string /// representation of the Enum \p Value to \p Options. /// /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to /// supply the mapping required to convert between ``T`` and a string. template - std::enable_if_t::value> + std::enable_if_t> store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) const { ArrayRef> Mapping = @@ -383,7 +454,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { bool CheckGlobal, bool IgnoreCase) const; template - std::enable_if_t::value, std::vector> + std::enable_if_t, std::vector> typeEraseMapping() const { ArrayRef> Mapping = OptionEnumMapping::getEnumMapping(); diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h index 15f1b67..9280eb1 100644 --- a/ClangTidyDiagnosticConsumer.h +++ b/ClangTidyDiagnosticConsumer.h @@ -70,7 +70,8 @@ class ClangTidyContext { public: /// Initializes \c ClangTidyContext instance. ClangTidyContext(std::unique_ptr OptionsProvider, - bool AllowEnablingAnalyzerAlphaCheckers = false); + bool AllowEnablingAnalyzerAlphaCheckers = false, + bool EnableModuleHeadersParsing = false); /// Sets the DiagnosticsEngine that diag() will emit diagnostics to. // FIXME: this is required initialization, and should be a constructor param. // Fix the context -> diag engine -> consumer -> context initialization cycle. @@ -86,10 +87,10 @@ class ClangTidyContext { /// tablegen'd diagnostic IDs. /// FIXME: Figure out a way to manage ID spaces. DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc, - StringRef Message, + StringRef Description, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - DiagnosticBuilder diag(StringRef CheckName, StringRef Message, + DiagnosticBuilder diag(StringRef CheckName, StringRef Description, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); DiagnosticBuilder diag(const tooling::Diagnostic &Error); @@ -198,6 +199,12 @@ class ClangTidyContext { return AllowEnablingAnalyzerAlphaCheckers; } + // This method determines whether preprocessor-level module header parsing is + // enabled using the `--experimental-enable-module-headers-parsing` option. + bool canEnableModuleHeadersParsing() const { + return EnableModuleHeadersParsing; + } + void setSelfContainedDiags(bool Value) { SelfContainedDiags = Value; } bool areDiagsSelfContained() const { return SelfContainedDiags; } @@ -205,11 +212,11 @@ class ClangTidyContext { using DiagLevelAndFormatString = std::pair; DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, SourceLocation Loc) { - return DiagLevelAndFormatString( + return { static_cast( DiagEngine->getDiagnosticLevel(DiagnosticID, Loc)), std::string( - DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID))); + DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID))}; } void setOptionsCollector(llvm::StringSet<> *Collector) { @@ -221,7 +228,7 @@ class ClangTidyContext { // Writes to Stats. friend class ClangTidyDiagnosticConsumer; - DiagnosticsEngine *DiagEngine; + DiagnosticsEngine *DiagEngine = nullptr; std::unique_ptr OptionsProvider; std::string CurrentFile; @@ -241,12 +248,13 @@ class ClangTidyContext { llvm::DenseMap CheckNamesByDiagnosticID; - bool Profile; + bool Profile = false; std::string ProfilePrefix; bool AllowEnablingAnalyzerAlphaCheckers; + bool EnableModuleHeadersParsing; - bool SelfContainedDiags; + bool SelfContainedDiags = false; NoLintDirectiveHandler NoLintHandler; llvm::StringSet<> *OptionsCollector = nullptr; @@ -305,9 +313,9 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer { bool EnableNolintBlocks; std::vector Errors; std::unique_ptr HeaderFilter; - bool LastErrorRelatesToUserCode; - bool LastErrorPassesLineFilter; - bool LastErrorWasIgnored; + bool LastErrorRelatesToUserCode = false; + bool LastErrorPassesLineFilter = false; + bool LastErrorWasIgnored = false; }; } // end namespace tidy diff --git a/ClangTidyModule.h b/ClangTidyModule.h index 0e55c1e..28f5433 100644 --- a/ClangTidyModule.h +++ b/ClangTidyModule.h @@ -70,7 +70,7 @@ class ClangTidyCheckFactories { std::vector> createChecksForLanguage(ClangTidyContext *Context) const; - typedef llvm::StringMap FactoryMap; + using FactoryMap = llvm::StringMap; FactoryMap::const_iterator begin() const { return Factories.begin(); } FactoryMap::const_iterator end() const { return Factories.end(); } bool empty() const { return Factories.empty(); } diff --git a/ClangTidyModuleRegistry.h b/ClangTidyModuleRegistry.h index 30ffe18..78d914b 100644 --- a/ClangTidyModuleRegistry.h +++ b/ClangTidyModuleRegistry.h @@ -14,7 +14,7 @@ namespace clang::tidy { -typedef llvm::Registry ClangTidyModuleRegistry; +using ClangTidyModuleRegistry = llvm::Registry; } // namespace clang::tidy diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h index b3b7143..e7636cb 100644 --- a/ClangTidyOptions.h +++ b/ClangTidyOptions.h @@ -30,7 +30,7 @@ struct FileFilter { std::string Name; /// LineRange is a pair (inclusive). - typedef std::pair LineRange; + using LineRange = std::pair; /// A list of line ranges in this file, for which we show warnings. std::vector LineRanges; @@ -118,13 +118,13 @@ struct ClangTidyOptions { /// files to disambiguate local vs global value from different levels. unsigned Priority = 0; }; - typedef std::pair StringPair; - typedef llvm::StringMap OptionMap; + using StringPair = std::pair; + using OptionMap = llvm::StringMap; /// Key-value mapping used to store check-specific options. OptionMap CheckOptions; - typedef std::vector ArgList; + using ArgList = std::vector; /// Add extra compilation arguments to the end of the list. std::optional ExtraArgs; @@ -165,7 +165,7 @@ class ClangTidyOptionsProvider { /// commandline option is specified, clang-tidy will ignore the /// configuration file. /// * '-checks' commandline option. - typedef std::pair OptionsSource; + using OptionsSource = std::pair; /// Returns an ordered vector of OptionsSources, in order of increasing /// priority. @@ -199,9 +199,7 @@ class FileOptionsBaseProvider : public DefaultOptionsProvider { protected: // A pair of configuration file base name and a function parsing // configuration from text in the corresponding format. - typedef std::pair( - llvm::MemoryBufferRef)>> - ConfigFileHandler; + using ConfigFileHandler = std::pair (llvm::MemoryBufferRef)>>; /// Configuration file handlers listed in the order of priority. /// @@ -220,7 +218,7 @@ class FileOptionsBaseProvider : public DefaultOptionsProvider { /// /// With the order of handlers shown above, the ".my-tidy-config" file would /// take precedence over ".clang-tidy" if both reside in the same directory. - typedef std::vector ConfigFileHandlers; + using ConfigFileHandlers = std::vector; FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, @@ -232,7 +230,6 @@ class FileOptionsBaseProvider : public DefaultOptionsProvider { ClangTidyOptions OverrideOptions, ConfigFileHandlers ConfigHandlers); -protected: void addRawFileOptions(llvm::StringRef AbsolutePath, std::vector &CurOptions); diff --git a/FileExtensionsSet.h b/FileExtensionsSet.h index 417b1b6..7ca4e6e 100644 --- a/FileExtensionsSet.h +++ b/FileExtensionsSet.h @@ -13,7 +13,7 @@ #include "llvm/ADT/StringRef.h" namespace clang::tidy { -typedef llvm::SmallSet FileExtensionsSet; +using FileExtensionsSet = llvm::SmallSet; } // namespace clang::tidy #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FILE_EXTENSIONS_SET_H From 4c33e9e082c3d03e8ca57c90aae48d7437df6c2f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 27 Aug 2024 16:23:57 +0200 Subject: [PATCH 15/20] Add -extra-args option --- tool/run_O2CodeChecker.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tool/run_O2CodeChecker.py b/tool/run_O2CodeChecker.py index 2c57d5d..5ced740 100755 --- a/tool/run_O2CodeChecker.py +++ b/tool/run_O2CodeChecker.py @@ -63,7 +63,7 @@ def find_compilation_database(path): def get_tidy_invocation(f, clang_tidy_binary, checks, warningsAsErrors, tmpdir, build_path, - header_filter, config): + header_filter, config, extra_args): """Gets a command line for clang-tidy.""" start = [clang_tidy_binary] if header_filter is not None: @@ -77,6 +77,8 @@ def get_tidy_invocation(f, clang_tidy_binary, checks, warningsAsErrors, tmpdir, start.append('-warnings-as-errors=' + warningsAsErrors) if config: start.append('-config=' + config) + if extra_args is not None: + start.append(extra_args) if tmpdir is not None: start.append('-export-fixes') # Get a temporary file. We immediately close the handle so clang-tidy can @@ -104,7 +106,7 @@ def run_tidy(args, tmpdir, build_path, queue): while True: name = queue.get() invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks, args.warningsAsErrors, - tmpdir, build_path, args.header_filter, args.config) + tmpdir, build_path, args.header_filter, args.config, args.extra_args) sys.stdout.write(' '.join(invocation) + '\n') subprocess.call(invocation) queue.task_done() @@ -130,6 +132,8 @@ def main(): parser.add_argument('-config', default=None, help='config option for check , when not specified, use clang-tidy ' 'default') + parser.add_argument('-extra-args', default=None, + help='Extra arguments to pass to o2codechecker') parser.add_argument('-header-filter', default=None, help='regular expression matching the names of the ' 'headers to output diagnostics from. Diagnostics from ' From 4f0c495b9a1630ac0df1286ebbfe56d2ac62f339 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 28 Aug 2024 13:46:00 +0200 Subject: [PATCH 16/20] Support OMP --- CMakeLists.txt | 9 +- omp.h | 521 ++++++++++++++++++++++++++++++++++++++ tool/run_O2CodeChecker.py | 1 + 3 files changed, 528 insertions(+), 3 deletions(-) create mode 100644 omp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 369cc22..ff1ac6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.4.3) enable_testing() if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # require at least gcc 4.9 !! - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) - message(FATAL_ERROR "GCC version must be at least 4.9!") + # require at least gcc 12.0 !! + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) + message(FATAL_ERROR "GCC version must be at least 12.0!") endif() endif() @@ -55,5 +55,8 @@ add_subdirectory(test) # some extra utilities add_subdirectory(utility) +string(REPLACE "." ";" LLVM_PACKAGE_VERSION_LIST ${LLVM_PACKAGE_VERSION}) +list(GET LLVM_PACKAGE_VERSION_LIST 0 LLVM_PACKAGE_VERSION_MAJOR) +install(FILES omp.h DESTINATION lib/clang/${LLVM_PACKAGE_VERSION_MAJOR}/include) endif() diff --git a/omp.h b/omp.h new file mode 100644 index 0000000..94be362 --- /dev/null +++ b/omp.h @@ -0,0 +1,521 @@ +/* + * include/omp.h.var + */ + + +//===----------------------------------------------------------------------===// +// +// 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 __OMP_H +# define __OMP_H + +# include +# include +# include + +# define KMP_VERSION_MAJOR 5 +# define KMP_VERSION_MINOR 0 +# define KMP_VERSION_BUILD 20140926 +# define KMP_BUILD_DATE "No_Timestamp" + +# ifdef __cplusplus + extern "C" { +# endif + +# define omp_set_affinity_format ompc_set_affinity_format +# define omp_get_affinity_format ompc_get_affinity_format +# define omp_display_affinity ompc_display_affinity +# define omp_capture_affinity ompc_capture_affinity + +# if defined(_WIN32) +# define __KAI_KMPC_CONVENTION __cdecl +# ifndef __KMP_IMP +# define __KMP_IMP __declspec(dllimport) +# endif +# else +# define __KAI_KMPC_CONVENTION +# ifndef __KMP_IMP +# define __KMP_IMP +# endif +# endif + + /* schedule kind constants */ + typedef enum omp_sched_t { + omp_sched_static = 1, + omp_sched_dynamic = 2, + omp_sched_guided = 3, + omp_sched_auto = 4, + omp_sched_monotonic = 0x80000000 + } omp_sched_t; + + /* set API functions */ + extern void __KAI_KMPC_CONVENTION omp_set_num_threads (int); + extern void __KAI_KMPC_CONVENTION omp_set_dynamic (int); + extern void __KAI_KMPC_CONVENTION omp_set_nested (int); + extern void __KAI_KMPC_CONVENTION omp_set_max_active_levels (int); + extern void __KAI_KMPC_CONVENTION omp_set_schedule (omp_sched_t, int); + + /* query API functions */ + extern int __KAI_KMPC_CONVENTION omp_get_num_threads (void); + extern int __KAI_KMPC_CONVENTION omp_get_dynamic (void); + extern int __KAI_KMPC_CONVENTION omp_get_nested (void); + extern int __KAI_KMPC_CONVENTION omp_get_max_threads (void); + extern int __KAI_KMPC_CONVENTION omp_get_thread_num (void); + extern int __KAI_KMPC_CONVENTION omp_get_num_procs (void); + extern int __KAI_KMPC_CONVENTION omp_in_parallel (void); + extern int __KAI_KMPC_CONVENTION omp_in_final (void); + extern int __KAI_KMPC_CONVENTION omp_get_active_level (void); + extern int __KAI_KMPC_CONVENTION omp_get_level (void); + extern int __KAI_KMPC_CONVENTION omp_get_ancestor_thread_num (int); + extern int __KAI_KMPC_CONVENTION omp_get_team_size (int); + extern int __KAI_KMPC_CONVENTION omp_get_thread_limit (void); + extern int __KAI_KMPC_CONVENTION omp_get_max_active_levels (void); + extern void __KAI_KMPC_CONVENTION omp_get_schedule (omp_sched_t *, int *); + extern int __KAI_KMPC_CONVENTION omp_get_max_task_priority (void); + + /* lock API functions */ + typedef struct omp_lock_t { + void * _lk; + } omp_lock_t; + + extern void __KAI_KMPC_CONVENTION omp_init_lock (omp_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_set_lock (omp_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_unset_lock (omp_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_destroy_lock (omp_lock_t *); + extern int __KAI_KMPC_CONVENTION omp_test_lock (omp_lock_t *); + + /* nested lock API functions */ + typedef struct omp_nest_lock_t { + void * _lk; + } omp_nest_lock_t; + + extern void __KAI_KMPC_CONVENTION omp_init_nest_lock (omp_nest_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_set_nest_lock (omp_nest_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_unset_nest_lock (omp_nest_lock_t *); + extern void __KAI_KMPC_CONVENTION omp_destroy_nest_lock (omp_nest_lock_t *); + extern int __KAI_KMPC_CONVENTION omp_test_nest_lock (omp_nest_lock_t *); + + /* OpenMP 5.0 Synchronization hints*/ + typedef enum omp_sync_hint_t { + omp_sync_hint_none = 0, + omp_lock_hint_none = omp_sync_hint_none, + omp_sync_hint_uncontended = 1, + omp_lock_hint_uncontended = omp_sync_hint_uncontended, + omp_sync_hint_contended = (1<<1), + omp_lock_hint_contended = omp_sync_hint_contended, + omp_sync_hint_nonspeculative = (1<<2), + omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, + omp_sync_hint_speculative = (1<<3), + omp_lock_hint_speculative = omp_sync_hint_speculative, + kmp_lock_hint_hle = (1<<16), + kmp_lock_hint_rtm = (1<<17), + kmp_lock_hint_adaptive = (1<<18) + } omp_sync_hint_t; + + /* lock hint type for dynamic user lock */ + typedef omp_sync_hint_t omp_lock_hint_t; + + /* hinted lock initializers */ + extern void __KAI_KMPC_CONVENTION omp_init_lock_with_hint(omp_lock_t *, omp_lock_hint_t); + extern void __KAI_KMPC_CONVENTION omp_init_nest_lock_with_hint(omp_nest_lock_t *, omp_lock_hint_t); + + /* time API functions */ + extern double __KAI_KMPC_CONVENTION omp_get_wtime (void); + extern double __KAI_KMPC_CONVENTION omp_get_wtick (void); + + /* OpenMP 4.0 */ + extern int __KAI_KMPC_CONVENTION omp_get_default_device (void); + extern void __KAI_KMPC_CONVENTION omp_set_default_device (int); + extern int __KAI_KMPC_CONVENTION omp_is_initial_device (void); + extern int __KAI_KMPC_CONVENTION omp_get_num_devices (void); + extern int __KAI_KMPC_CONVENTION omp_get_num_teams (void); + extern int __KAI_KMPC_CONVENTION omp_get_team_num (void); + extern int __KAI_KMPC_CONVENTION omp_get_cancellation (void); + + /* OpenMP 4.5 */ + extern int __KAI_KMPC_CONVENTION omp_get_initial_device (void); + extern void* __KAI_KMPC_CONVENTION omp_target_alloc(size_t, int); + extern void __KAI_KMPC_CONVENTION omp_target_free(void *, int); + extern int __KAI_KMPC_CONVENTION omp_target_is_present(const void *, int); + extern int __KAI_KMPC_CONVENTION omp_target_memcpy(void *, const void *, size_t, size_t, size_t, int, int); + extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect(void *, const void *, size_t, int, const size_t *, + const size_t *, const size_t *, const size_t *, const size_t *, int, int); + extern int __KAI_KMPC_CONVENTION omp_target_associate_ptr(const void *, const void *, size_t, size_t, int); + extern int __KAI_KMPC_CONVENTION omp_target_disassociate_ptr(const void *, int); + + /* OpenMP 5.0 */ + extern int __KAI_KMPC_CONVENTION omp_get_device_num (void); + typedef void * omp_depend_t; + + /* OpenMP 5.1 interop */ + typedef intptr_t omp_intptr_t; + + /* 0..omp_get_num_interop_properties()-1 are reserved for implementation-defined properties */ + typedef enum omp_interop_property { + omp_ipr_fr_id = -1, + omp_ipr_fr_name = -2, + omp_ipr_vendor = -3, + omp_ipr_vendor_name = -4, + omp_ipr_device_num = -5, + omp_ipr_platform = -6, + omp_ipr_device = -7, + omp_ipr_device_context = -8, + omp_ipr_targetsync = -9, + omp_ipr_first = -9 + } omp_interop_property_t; + + #define omp_interop_none 0 + + typedef enum omp_interop_rc { + omp_irc_no_value = 1, + omp_irc_success = 0, + omp_irc_empty = -1, + omp_irc_out_of_range = -2, + omp_irc_type_int = -3, + omp_irc_type_ptr = -4, + omp_irc_type_str = -5, + omp_irc_other = -6 + } omp_interop_rc_t; + + typedef enum omp_interop_fr { + omp_ifr_cuda = 1, + omp_ifr_cuda_driver = 2, + omp_ifr_opencl = 3, + omp_ifr_sycl = 4, + omp_ifr_hip = 5, + omp_ifr_level_zero = 6, + omp_ifr_last = 7 + } omp_interop_fr_t; + + typedef void * omp_interop_t; + + /*! + * The `omp_get_num_interop_properties` routine retrieves the number of implementation-defined properties available for an `omp_interop_t` object. + */ + extern int __KAI_KMPC_CONVENTION omp_get_num_interop_properties(const omp_interop_t); + /*! + * The `omp_get_interop_int` routine retrieves an integer property from an `omp_interop_t` object. + */ + extern omp_intptr_t __KAI_KMPC_CONVENTION omp_get_interop_int(const omp_interop_t, omp_interop_property_t, int *); + /*! + * The `omp_get_interop_ptr` routine retrieves a pointer property from an `omp_interop_t` object. + */ + extern void * __KAI_KMPC_CONVENTION omp_get_interop_ptr(const omp_interop_t, omp_interop_property_t, int *); + /*! + * The `omp_get_interop_str` routine retrieves a string property from an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_str(const omp_interop_t, omp_interop_property_t, int *); + /*! + * The `omp_get_interop_name` routine retrieves a property name from an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_name(const omp_interop_t, omp_interop_property_t); + /*! + * The `omp_get_interop_type_desc` routine retrieves a description of the type of a property associated with an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_type_desc(const omp_interop_t, omp_interop_property_t); + /*! + * The `omp_get_interop_rc_desc` routine retrieves a description of the return code associated with an `omp_interop_t` object. + */ + extern const char * __KAI_KMPC_CONVENTION omp_get_interop_rc_desc(const omp_interop_t, omp_interop_rc_t); + + /* OpenMP 5.1 device memory routines */ + + /*! + * The `omp_target_memcpy_async` routine asynchronously performs a copy between any combination of host and device pointers. + */ + extern int __KAI_KMPC_CONVENTION omp_target_memcpy_async(void *, const void *, size_t, size_t, size_t, int, + int, int, omp_depend_t *); + /*! + * The `omp_target_memcpy_rect_async` routine asynchronously performs a copy between any combination of host and device pointers. + */ + extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect_async(void *, const void *, size_t, int, const size_t *, + const size_t *, const size_t *, const size_t *, const size_t *, int, int, + int, omp_depend_t *); + + /* OpenMP 6.0 device memory routines */ + extern void * __KAI_KMPC_CONVENTION omp_target_memset(void *, int, size_t, int); + extern void * __KAI_KMPC_CONVENTION omp_target_memset_async(void *, int, size_t, int, int, omp_depend_t *); + + /*! + * The `omp_get_mapped_ptr` routine returns the device pointer that is associated with a host pointer for a given device. + */ + extern void * __KAI_KMPC_CONVENTION omp_get_mapped_ptr(const void *, int); + extern int __KAI_KMPC_CONVENTION omp_target_is_accessible(const void *, size_t, int); + + /* kmp API functions */ + extern int __KAI_KMPC_CONVENTION kmp_get_stacksize (void); + extern void __KAI_KMPC_CONVENTION kmp_set_stacksize (int); + extern size_t __KAI_KMPC_CONVENTION kmp_get_stacksize_s (void); + extern void __KAI_KMPC_CONVENTION kmp_set_stacksize_s (size_t); + extern int __KAI_KMPC_CONVENTION kmp_get_blocktime (void); + extern int __KAI_KMPC_CONVENTION kmp_get_library (void); + extern void __KAI_KMPC_CONVENTION kmp_set_blocktime (int); + extern void __KAI_KMPC_CONVENTION kmp_set_library (int); + extern void __KAI_KMPC_CONVENTION kmp_set_library_serial (void); + extern void __KAI_KMPC_CONVENTION kmp_set_library_turnaround (void); + extern void __KAI_KMPC_CONVENTION kmp_set_library_throughput (void); + extern void __KAI_KMPC_CONVENTION kmp_set_defaults (char const *); + extern void __KAI_KMPC_CONVENTION kmp_set_disp_num_buffers (int); + + /* Intel affinity API */ + typedef void * kmp_affinity_mask_t; + + extern int __KAI_KMPC_CONVENTION kmp_set_affinity (kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_get_affinity (kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_get_affinity_max_proc (void); + extern void __KAI_KMPC_CONVENTION kmp_create_affinity_mask (kmp_affinity_mask_t *); + extern void __KAI_KMPC_CONVENTION kmp_destroy_affinity_mask (kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_set_affinity_mask_proc (int, kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_unset_affinity_mask_proc (int, kmp_affinity_mask_t *); + extern int __KAI_KMPC_CONVENTION kmp_get_affinity_mask_proc (int, kmp_affinity_mask_t *); + + /* OpenMP 4.0 affinity API */ + typedef enum omp_proc_bind_t { + omp_proc_bind_false = 0, + omp_proc_bind_true = 1, + omp_proc_bind_master = 2, + omp_proc_bind_close = 3, + omp_proc_bind_spread = 4 + } omp_proc_bind_t; + + extern omp_proc_bind_t __KAI_KMPC_CONVENTION omp_get_proc_bind (void); + + /* OpenMP 4.5 affinity API */ + extern int __KAI_KMPC_CONVENTION omp_get_num_places (void); + extern int __KAI_KMPC_CONVENTION omp_get_place_num_procs (int); + extern void __KAI_KMPC_CONVENTION omp_get_place_proc_ids (int, int *); + extern int __KAI_KMPC_CONVENTION omp_get_place_num (void); + extern int __KAI_KMPC_CONVENTION omp_get_partition_num_places (void); + extern void __KAI_KMPC_CONVENTION omp_get_partition_place_nums (int *); + + extern void * __KAI_KMPC_CONVENTION kmp_malloc (size_t); + extern void * __KAI_KMPC_CONVENTION kmp_aligned_malloc (size_t, size_t); + extern void * __KAI_KMPC_CONVENTION kmp_calloc (size_t, size_t); + extern void * __KAI_KMPC_CONVENTION kmp_realloc (void *, size_t); + extern void __KAI_KMPC_CONVENTION kmp_free (void *); + + extern void __KAI_KMPC_CONVENTION kmp_set_warnings_on(void); + extern void __KAI_KMPC_CONVENTION kmp_set_warnings_off(void); + + /* OpenMP 5.0 Tool Control */ + typedef enum omp_control_tool_result_t { + omp_control_tool_notool = -2, + omp_control_tool_nocallback = -1, + omp_control_tool_success = 0, + omp_control_tool_ignored = 1 + } omp_control_tool_result_t; + + typedef enum omp_control_tool_t { + omp_control_tool_start = 1, + omp_control_tool_pause = 2, + omp_control_tool_flush = 3, + omp_control_tool_end = 4 + } omp_control_tool_t; + + extern int __KAI_KMPC_CONVENTION omp_control_tool(int, int, void*); + + /* OpenMP 5.0 Memory Management */ + typedef uintptr_t omp_uintptr_t; + + typedef enum { + omp_atk_sync_hint = 1, + omp_atk_alignment = 2, + omp_atk_access = 3, + omp_atk_pool_size = 4, + omp_atk_fallback = 5, + omp_atk_fb_data = 6, + omp_atk_pinned = 7, + omp_atk_partition = 8 + } omp_alloctrait_key_t; + + typedef enum { + omp_atv_false = 0, + omp_atv_true = 1, + omp_atv_contended = 3, + omp_atv_uncontended = 4, + omp_atv_serialized = 5, + omp_atv_sequential = omp_atv_serialized, // (deprecated) + omp_atv_private = 6, + omp_atv_all = 7, + omp_atv_thread = 8, + omp_atv_pteam = 9, + omp_atv_cgroup = 10, + omp_atv_default_mem_fb = 11, + omp_atv_null_fb = 12, + omp_atv_abort_fb = 13, + omp_atv_allocator_fb = 14, + omp_atv_environment = 15, + omp_atv_nearest = 16, + omp_atv_blocked = 17, + omp_atv_interleaved = 18 + } omp_alloctrait_value_t; + #define omp_atv_default ((omp_uintptr_t)-1) + + typedef struct { + omp_alloctrait_key_t key; + omp_uintptr_t value; + } omp_alloctrait_t; + +# if defined(_WIN32) + // On Windows cl and icl do not support 64-bit enum, let's use integer then. + typedef omp_uintptr_t omp_allocator_handle_t; + extern __KMP_IMP omp_allocator_handle_t const omp_null_allocator; + extern __KMP_IMP omp_allocator_handle_t const omp_default_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_large_cap_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_const_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_high_bw_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_low_lat_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_cgroup_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_pteam_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const omp_thread_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_host_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc; + extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_device_mem_alloc; + + typedef omp_uintptr_t omp_memspace_handle_t; + extern __KMP_IMP omp_memspace_handle_t const omp_default_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_large_cap_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_const_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_high_bw_mem_space; + extern __KMP_IMP omp_memspace_handle_t const omp_low_lat_mem_space; + extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_host_mem_space; + extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_shared_mem_space; + extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_device_mem_space; +# else +# if __cplusplus >= 201103 + typedef enum omp_allocator_handle_t : omp_uintptr_t +# else + typedef enum omp_allocator_handle_t +# endif + { + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + llvm_omp_target_host_mem_alloc = 100, + llvm_omp_target_shared_mem_alloc = 101, + llvm_omp_target_device_mem_alloc = 102, + KMP_ALLOCATOR_MAX_HANDLE = UINTPTR_MAX + } omp_allocator_handle_t; +# if __cplusplus >= 201103 + typedef enum omp_memspace_handle_t : omp_uintptr_t +# else + typedef enum omp_memspace_handle_t +# endif + { + omp_default_mem_space = 0, + omp_large_cap_mem_space = 1, + omp_const_mem_space = 2, + omp_high_bw_mem_space = 3, + omp_low_lat_mem_space = 4, + llvm_omp_target_host_mem_space = 100, + llvm_omp_target_shared_mem_space = 101, + llvm_omp_target_device_mem_space = 102, + KMP_MEMSPACE_MAX_HANDLE = UINTPTR_MAX + } omp_memspace_handle_t; +# endif + extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_init_allocator(omp_memspace_handle_t m, + int ntraits, omp_alloctrait_t traits[]); + extern void __KAI_KMPC_CONVENTION omp_destroy_allocator(omp_allocator_handle_t allocator); + + extern void __KAI_KMPC_CONVENTION omp_set_default_allocator(omp_allocator_handle_t a); + extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_get_default_allocator(void); +# ifdef __cplusplus + extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, size_t size, + omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, + omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_aligned_calloc(size_t align, size_t nmemb, size_t size, + omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, + omp_allocator_handle_t allocator = omp_null_allocator, + omp_allocator_handle_t free_allocator = omp_null_allocator); + extern void __KAI_KMPC_CONVENTION omp_free(void * ptr, omp_allocator_handle_t a = omp_null_allocator); +# else + extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, size_t size, + omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_aligned_calloc(size_t align, size_t nmemb, size_t size, + omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator); + extern void __KAI_KMPC_CONVENTION omp_free(void *ptr, omp_allocator_handle_t a); +# endif + + /* OpenMP 5.0 Affinity Format */ + extern void __KAI_KMPC_CONVENTION omp_set_affinity_format(char const *); + extern size_t __KAI_KMPC_CONVENTION omp_get_affinity_format(char *, size_t); + extern void __KAI_KMPC_CONVENTION omp_display_affinity(char const *); + extern size_t __KAI_KMPC_CONVENTION omp_capture_affinity(char *, size_t, char const *); + + /* OpenMP 5.0 events */ +# if defined(_WIN32) + // On Windows cl and icl do not support 64-bit enum, let's use integer then. + typedef omp_uintptr_t omp_event_handle_t; +# else + typedef enum omp_event_handle_t { KMP_EVENT_MAX_HANDLE = UINTPTR_MAX } omp_event_handle_t; +# endif + extern void __KAI_KMPC_CONVENTION omp_fulfill_event ( omp_event_handle_t event ); + + /* OpenMP 5.0 Pause Resources */ + typedef enum omp_pause_resource_t { + omp_pause_resume = 0, + omp_pause_soft = 1, + omp_pause_hard = 2 + } omp_pause_resource_t; + extern int __KAI_KMPC_CONVENTION omp_pause_resource(omp_pause_resource_t, int); + extern int __KAI_KMPC_CONVENTION omp_pause_resource_all(omp_pause_resource_t); + + extern int __KAI_KMPC_CONVENTION omp_get_supported_active_levels(void); + + /* OpenMP 5.1 */ + extern void __KAI_KMPC_CONVENTION omp_set_num_teams(int num_teams); + extern int __KAI_KMPC_CONVENTION omp_get_max_teams(void); + extern void __KAI_KMPC_CONVENTION omp_set_teams_thread_limit(int limit); + extern int __KAI_KMPC_CONVENTION omp_get_teams_thread_limit(void); + + /* OpenMP 5.1 Display Environment */ + extern void omp_display_env(int verbose); + +# if defined(_OPENMP) && _OPENMP >= 201811 + #pragma omp begin declare variant match(device={kind(host)}) + static inline int omp_is_initial_device(void) { return 1; } + #pragma omp end declare variant + #pragma omp begin declare variant match(device={kind(nohost)}) + static inline int omp_is_initial_device(void) { return 0; } + #pragma omp end declare variant +# endif + + /* OpenMP 5.2 */ + extern int __KAI_KMPC_CONVENTION omp_in_explicit_task(void); + + /* LLVM Extensions */ + extern void *llvm_omp_target_dynamic_shared_alloc(void); + +# undef __KAI_KMPC_CONVENTION +# undef __KMP_IMP + + /* Warning: + The following typedefs are not standard, deprecated and will be removed in a future release. + */ + typedef int omp_int_t; + typedef double omp_wtime_t; + +# ifdef __cplusplus + } +# endif + +#endif /* __OMP_H */ diff --git a/tool/run_O2CodeChecker.py b/tool/run_O2CodeChecker.py index 5ced740..97c50a2 100755 --- a/tool/run_O2CodeChecker.py +++ b/tool/run_O2CodeChecker.py @@ -88,6 +88,7 @@ def get_tidy_invocation(f, clang_tidy_binary, checks, warningsAsErrors, tmpdir, start.append(name) start.append('-p=' + build_path) start.append(f) + start.append('--extra-arg=-fopenmp') return start From 38a6dadefa00bff083b036b8495c97656635e0db Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:42:24 +0200 Subject: [PATCH 17/20] Use Clang provided public API - Drop our own private copy of the headers - Use the CMake Config *** --- CMakeLists.txt | 2 +- ClangTidy.h | 125 ------- ClangTidyCheck.h | 533 ------------------------------ ClangTidyDiagnosticConsumer.h | 324 ------------------ ClangTidyForceLinker.h | 142 -------- ClangTidyModule.h | 98 ------ ClangTidyModuleRegistry.h | 21 -- ClangTidyOptions.h | 329 ------------------ ClangTidyProfiling.h | 58 ---- aliceO2/AliceO2TidyModule.cpp | 6 +- aliceO2/MemberNamesCheck.h | 4 +- aliceO2/NamespaceNamingCheck.h | 4 +- aliceO2/SizeofCheck.h | 4 +- plugin/FooCheck.h | 4 +- plugin/PluginTidyModule.cpp | 6 +- reporting/InterfaceLister.h | 4 +- reporting/ReportingTidyModule.cpp | 6 +- reporting/VirtFuncLister.h | 4 +- tool/ClangTidyMain.cpp | 6 +- 19 files changed, 25 insertions(+), 1655 deletions(-) delete mode 100644 ClangTidy.h delete mode 100644 ClangTidyCheck.h delete mode 100644 ClangTidyDiagnosticConsumer.h delete mode 100644 ClangTidyForceLinker.h delete mode 100644 ClangTidyModule.h delete mode 100644 ClangTidyModuleRegistry.h delete mode 100644 ClangTidyOptions.h delete mode 100644 ClangTidyProfiling.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ff1ac6c..ff3e144 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) # find clang + llvm - find_package(Clang REQUIRED) + find_package(Clang REQUIRED CONFIG) if( LLVM_FOUND ) list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") diff --git a/ClangTidy.h b/ClangTidy.h deleted file mode 100644 index 51d9e22..0000000 --- a/ClangTidy.h +++ /dev/null @@ -1,125 +0,0 @@ -//===--- ClangTidy.h - clang-tidy -------------------------------*- 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_CLANG_TIDY_CLANGTIDY_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H - -#include "ClangTidyDiagnosticConsumer.h" -#include "ClangTidyOptions.h" -#include "llvm/ADT/StringSet.h" -#include -#include - -namespace llvm { -class raw_ostream; -} // namespace llvm - -namespace clang { - -class ASTConsumer; -class CompilerInstance; -namespace tooling { -class CompilationDatabase; -} // namespace tooling - -namespace tidy { - -class ClangTidyCheckFactories; - -class ClangTidyASTConsumerFactory { -public: - ClangTidyASTConsumerFactory( - ClangTidyContext &Context, - IntrusiveRefCntPtr OverlayFS = nullptr); - - /// Returns an ASTConsumer that runs the specified clang-tidy checks. - std::unique_ptr - createASTConsumer(clang::CompilerInstance &Compiler, StringRef File); - - /// Get the list of enabled checks. - std::vector getCheckNames(); - - /// Get the union of options from all checks. - ClangTidyOptions::OptionMap getCheckOptions(); - -private: - ClangTidyContext &Context; - IntrusiveRefCntPtr OverlayFS; - std::unique_ptr CheckFactories; -}; - -/// Fills the list of check names that are enabled when the provided -/// filters are applied. -std::vector 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 -/// effective options from all created checks. The returned set of options -/// includes default check-specific options for all keys not overridden by \p -/// Options. -ClangTidyOptions::OptionMap -getCheckOptions(const ClangTidyOptions &Options, - bool AllowEnablingAnalyzerAlphaCheckers); - -/// Run a set of clang-tidy checks on a set of files. -/// -/// \param EnableCheckProfile If provided, it enables check profile collection -/// in MatchFinder, and will contain the result of the profile. -/// \param StoreCheckProfile If provided, and EnableCheckProfile is true, -/// the profile will not be output to stderr, but will instead be stored -/// as a JSON file in the specified directory. -std::vector -runClangTidy(clang::tidy::ClangTidyContext &Context, - const tooling::CompilationDatabase &Compilations, - ArrayRef InputFiles, - llvm::IntrusiveRefCntPtr BaseFS, - bool ApplyAnyFix, bool EnableCheckProfile = false, - llvm::StringRef StoreCheckProfile = StringRef()); - -/// Controls what kind of fixes clang-tidy is allowed to apply. -enum FixBehaviour { - /// Don't try to apply any fix. - FB_NoFix, - /// Only apply fixes added to warnings. - FB_Fix, - /// Apply fixes found in notes. - FB_FixNotes -}; - -// FIXME: This interface will need to be significantly extended to be useful. -// FIXME: Implement confidence levels for displaying/fixing errors. -// -/// Displays the found \p Errors to the users. If \p Fix is \ref FB_Fix or \ref -/// FB_FixNotes, \p Errors containing fixes are automatically applied and -/// reformatted. If no clang-format configuration file is found, the given \P -/// FormatStyle is used. -void handleErrors(llvm::ArrayRef Errors, - ClangTidyContext &Context, FixBehaviour Fix, - unsigned &WarningsAsErrorsCount, - llvm::IntrusiveRefCntPtr BaseFS); - -/// Serializes replacements into YAML and writes them to the specified -/// output stream. -void exportReplacements(StringRef MainFilePath, - const std::vector &Errors, - raw_ostream &OS); - -} // end namespace tidy -} // end namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDY_H diff --git a/ClangTidyCheck.h b/ClangTidyCheck.h deleted file mode 100644 index 656a2f0..0000000 --- a/ClangTidyCheck.h +++ /dev/null @@ -1,533 +0,0 @@ -//===--- ClangTidyCheck.h - clang-tidy --------------------------*- 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_CLANG_TIDY_CLANGTIDYCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H - -#include "ClangTidyDiagnosticConsumer.h" -#include "ClangTidyOptions.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Basic/Diagnostic.h" -#include -#include -#include -#include - -namespace clang { - -class SourceManager; - -namespace tidy { - -/// This class should be specialized by any enum type that needs to be converted -/// to and from an \ref llvm::StringRef. -template struct OptionEnumMapping { - // Specializations of this struct must implement this function. - static ArrayRef> getEnumMapping() = delete; -}; - -/// Base class for all clang-tidy checks. -/// -/// To implement a ``ClangTidyCheck``, write a subclass and override some of the -/// base class's methods. E.g. to implement a check that validates namespace -/// declarations, override ``registerMatchers``: -/// -/// ~~~{.cpp} -/// void registerMatchers(ast_matchers::MatchFinder *Finder) override { -/// Finder->addMatcher(namespaceDecl().bind("namespace"), this); -/// } -/// ~~~ -/// -/// and then override ``check(const MatchResult &Result)`` to do the actual -/// check for each match. -/// -/// A new ``ClangTidyCheck`` instance is created per translation unit. -/// -/// FIXME: Figure out whether carrying information from one TU to another is -/// useful/necessary. -class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { -public: - /// Initializes the check with \p CheckName and \p Context. - /// - /// Derived classes must implement the constructor with this signature or - /// delegate it. If a check needs to read options, it can do this in the - /// constructor using the Options.get() methods below. - ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context); - - /// Override this to disable registering matchers and PP callbacks if an - /// invalid language version is being used. - /// - /// For example if a check is examining overloaded functions then this should - /// be overridden to return false when the CPlusPlus flag is not set in - /// \p LangOpts. - virtual bool isLanguageVersionSupported(const LangOptions &LangOpts) const { - return true; - } - - /// Override this to register ``PPCallbacks`` in the preprocessor. - /// - /// This should be used for clang-tidy checks that analyze preprocessor- - /// dependent properties, e.g. include directives and macro definitions. - /// - /// This will only be executed if the function isLanguageVersionSupported - /// returns true. - /// - /// There are two Preprocessors to choose from that differ in how they handle - /// modular #includes: - /// - PP is the real Preprocessor. It doesn't walk into modular #includes and - /// thus doesn't generate PPCallbacks for their contents. - /// - ModuleExpanderPP preprocesses the whole translation unit in the - /// non-modular mode, which allows it to generate PPCallbacks not only for - /// the main file and textual headers, but also for all transitively - /// included modular headers when the analysis runs with modules enabled. - /// When modules are not enabled ModuleExpanderPP just points to the real - /// preprocessor. - virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, - Preprocessor *ModuleExpanderPP) {} - - /// Override this to register AST matchers with \p Finder. - /// - /// This should be used by clang-tidy checks that analyze code properties that - /// dependent on AST knowledge. - /// - /// You can register as many matchers as necessary with \p Finder. Usually, - /// "this" will be used as callback, but you can also specify other callback - /// classes. Thereby, different matchers can trigger different callbacks. - /// - /// This will only be executed if the function isLanguageVersionSupported - /// returns true. - /// - /// If you need to merge information between the different matchers, you can - /// store these as members of the derived class. However, note that all - /// matches occur in the order of the AST traversal. - virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {} - - /// ``ClangTidyChecks`` that register ASTMatchers should do the actual - /// work in here. - virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} - - /// Add a diagnostic with the check's name. - DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, - DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - - /// Add a diagnostic with the check's name. - DiagnosticBuilder diag(StringRef Description, - DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - - /// Adds a diagnostic to report errors in the check's configuration. - DiagnosticBuilder - configurationDiag(StringRef Description, - 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. - /// - /// The check should use ``Options.store()`` to store each option it supports - /// whether it has the default value or it has been overridden. - virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {} - - /// Provides access to the ``ClangTidyCheck`` options via check-local - /// names. - /// - /// Methods of this class prepend ``CheckName + "."`` to translate check-local - /// option names to global option names. - class OptionsView { - void diagnoseBadIntegerOption(const Twine &Lookup, - StringRef Unparsed) const; - void diagnoseBadBooleanOption(const Twine &Lookup, - StringRef Unparsed) const; - void diagnoseBadEnumOption(const Twine &Lookup, StringRef Unparsed, - StringRef Suggestion = StringRef()) const; - - public: - /// Initializes the instance using \p CheckName + "." as a prefix. - OptionsView(StringRef CheckName, - const ClangTidyOptions::OptionMap &CheckOptions, - ClangTidyContext *Context); - - /// 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, return - /// ``std::nullopt``. - std::optional 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. - 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 ``std::nullopt``. - std::optional 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. - StringRef getLocalOrGlobal(StringRef LocalName, StringRef Default) const; - - /// Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, - /// return ``std::nullopt``. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``std::nullopt``. - template - std::enable_if_t, std::optional> - get(StringRef LocalName) const { - if (std::optional Value = get(LocalName)) { - T Result{}; - if (!StringRef(*Value).getAsInteger(10, Result)) - return Result; - diagnoseBadIntegerOption(NamePrefix + LocalName, *Value); - } - return std::nullopt; - } - - /// Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is `none`, `null`, - /// `-1` or empty, return ``std::nullopt``. If the corresponding - /// key is not present, return \p Default. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return \p Default. - template - std::enable_if_t, std::optional> - get(StringRef LocalName, std::optional Default) const { - if (std::optional Value = get(LocalName)) { - if (Value == "" || Value == "none" || Value == "null" || - (std::is_unsigned_v && Value == "-1")) - return std::nullopt; - T Result{}; - if (!StringRef(*Value).getAsInteger(10, Result)) - return Result; - diagnoseBadIntegerOption(NamePrefix + LocalName, *Value); - } - return Default; - } - - /// Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, return - /// \p Default. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return \p Default. - template - std::enable_if_t, T> get(StringRef LocalName, - T Default) const { - return get(LocalName).value_or(Default); - } - - /// Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// 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 ``std::nullopt``. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``std::nullopt``. - template - std::enable_if_t, std::optional> - getLocalOrGlobal(StringRef LocalName) const { - std::optional ValueOr = get(LocalName); - bool IsGlobal = false; - if (!ValueOr) { - IsGlobal = true; - ValueOr = getLocalOrGlobal(LocalName); - if (!ValueOr) - return std::nullopt; - } - T Result{}; - if (!StringRef(*ValueOr).getAsInteger(10, Result)) - return Result; - diagnoseBadIntegerOption( - IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr); - return std::nullopt; - } - - /// Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// 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 \p Default. If the value value was found - /// and equals ``none``, ``null``, ``-1`` or empty, return ``std::nullopt``. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return \p Default. - template - std::enable_if_t, std::optional> - getLocalOrGlobal(StringRef LocalName, std::optional Default) const { - std::optional ValueOr = get(LocalName); - bool IsGlobal = false; - if (!ValueOr) { - IsGlobal = true; - ValueOr = getLocalOrGlobal(LocalName); - if (!ValueOr) - return Default; - } - T Result{}; - if (ValueOr == "" || ValueOr == "none" || ValueOr == "null" || - (std::is_unsigned_v && ValueOr == "-1")) - return std::nullopt; - if (!StringRef(*ValueOr).getAsInteger(10, Result)) - return Result; - diagnoseBadIntegerOption( - IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr); - return Default; - } - - /// Read a named option from the ``Context`` and parse it as an - /// integral type ``T``. - /// - /// 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 \p Default. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return \p Default. - template - std::enable_if_t, T> - getLocalOrGlobal(StringRef LocalName, T Default) const { - return getLocalOrGlobal(LocalName).value_or(Default); - } - - /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T``. - /// - /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, return - /// ``std::nullopt``. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``std::nullopt``. - /// - /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to - /// supply the mapping required to convert between ``T`` and a string. - template - std::enable_if_t, std::optional> - get(StringRef LocalName, bool IgnoreCase = false) const { - if (std::optional ValueOr = - getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) - return static_cast(*ValueOr); - return std::nullopt; - } - - /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T``. - /// - /// Reads the option with the check-local name \p LocalName from the - /// ``CheckOptions``. If the corresponding key is not present, - /// return \p Default. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return \p Default. - /// - /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to - /// supply the mapping required to convert between ``T`` and a string. - template - std::enable_if_t, T> get(StringRef LocalName, T Default, - bool IgnoreCase = false) const { - return get(LocalName, IgnoreCase).value_or(Default); - } - - /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T``. - /// - /// 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 ``std::nullopt``. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return ``std::nullopt``. - /// - /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to - /// supply the mapping required to convert between ``T`` and a string. - template - std::enable_if_t, std::optional> - getLocalOrGlobal(StringRef LocalName, bool IgnoreCase = false) const { - if (std::optional ValueOr = - getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) - return static_cast(*ValueOr); - return std::nullopt; - } - - /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T``. - /// - /// 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 \p Default. - /// - /// If the corresponding key can't be parsed as a ``T``, emit a - /// diagnostic and return \p Default. - /// - /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to - /// supply the mapping required to convert between ``T`` and a string. - template - std::enable_if_t, T> - getLocalOrGlobal(StringRef LocalName, T Default, - bool IgnoreCase = false) const { - return getLocalOrGlobal(LocalName, IgnoreCase).value_or(Default); - } - - /// Stores an option with the check-local name \p LocalName with - /// string value \p Value to \p Options. - void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - StringRef Value) const; - - /// Stores an option with the check-local name \p LocalName with - /// integer value \p Value to \p Options. - template - std::enable_if_t> - store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - T Value) const { - storeInt(Options, LocalName, Value); - } - - /// Stores an option with the check-local name \p LocalName with - /// integer value \p Value to \p Options. If the value is empty - /// stores `` - template - std::enable_if_t> - store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - std::optional Value) const { - if (Value) - storeInt(Options, LocalName, *Value); - else - store(Options, LocalName, "none"); - } - - /// Stores an option with the check-local name \p LocalName as the string - /// representation of the Enum \p Value to \p Options. - /// - /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to - /// supply the mapping required to convert between ``T`` and a string. - template - std::enable_if_t> - store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - T Value) const { - ArrayRef> Mapping = - OptionEnumMapping::getEnumMapping(); - auto Iter = llvm::find_if( - Mapping, [&](const std::pair &NameAndEnum) { - return NameAndEnum.first == Value; - }); - assert(Iter != Mapping.end() && "Unknown Case Value"); - store(Options, LocalName, Iter->second); - } - - private: - using NameAndValue = std::pair; - - std::optional getEnumInt(StringRef LocalName, - ArrayRef Mapping, - bool CheckGlobal, bool IgnoreCase) const; - - template - std::enable_if_t, std::vector> - typeEraseMapping() const { - ArrayRef> Mapping = - OptionEnumMapping::getEnumMapping(); - std::vector Result; - Result.reserve(Mapping.size()); - for (auto &MappedItem : Mapping) { - Result.emplace_back(static_cast(MappedItem.first), - MappedItem.second); - } - return Result; - } - - void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - int64_t Value) const; - - - std::string NamePrefix; - const ClangTidyOptions::OptionMap &CheckOptions; - ClangTidyContext *Context; - }; - -private: - void run(const ast_matchers::MatchFinder::MatchResult &Result) override; - std::string CheckName; - ClangTidyContext *Context; - -protected: - OptionsView Options; - /// Returns the main file name of the current translation unit. - 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(); - } - StringRef getID() const override { return CheckName; } -}; - -/// Read a named option from the ``Context`` and parse it as a bool. -/// -/// Reads the option with the check-local name \p LocalName from the -/// ``CheckOptions``. If the corresponding key is not present, return -/// ``std::nullopt``. -/// -/// If the corresponding key can't be parsed as a bool, emit a -/// diagnostic and return ``std::nullopt``. -template <> -std::optional -ClangTidyCheck::OptionsView::get(StringRef LocalName) const; - -/// Read a named option from the ``Context`` and parse it as a bool. -/// -/// Reads the option with the check-local name \p LocalName from the -/// ``CheckOptions``. If the corresponding key is not present, return -/// \p Default. -/// -/// If the corresponding key can't be parsed as a bool, emit a -/// diagnostic and return \p Default. -template <> -std::optional -ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const; - -/// Stores an option with the check-local name \p LocalName with -/// bool value \p Value to \p Options. -template <> -void ClangTidyCheck::OptionsView::store( - ClangTidyOptions::OptionMap &Options, StringRef LocalName, - bool Value) const; - - -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H diff --git a/ClangTidyDiagnosticConsumer.h b/ClangTidyDiagnosticConsumer.h deleted file mode 100644 index 9280eb1..0000000 --- a/ClangTidyDiagnosticConsumer.h +++ /dev/null @@ -1,324 +0,0 @@ -//===--- ClangTidyDiagnosticConsumer.h - clang-tidy -------------*- 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_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H - -#include "ClangTidyOptions.h" -#include "ClangTidyProfiling.h" -#include "FileExtensionsSet.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" -#include - -namespace clang { - -class ASTContext; -class SourceManager; - -namespace tidy { -class CachedGlobList; - -/// A detected error complete with information to display diagnostic and -/// automatic fix. -/// -/// This is used as an intermediate format to transport Diagnostics without a -/// dependency on a SourceManager. -/// -/// FIXME: Make Diagnostics flexible enough to support this directly. -struct ClangTidyError : tooling::Diagnostic { - ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory, - bool IsWarningAsError); - - bool IsWarningAsError; - std::vector EnabledDiagnosticAliases; -}; - -/// Contains displayed and ignored diagnostic counters for a ClangTidy run. -struct ClangTidyStats { - unsigned ErrorsDisplayed = 0; - unsigned ErrorsIgnoredCheckFilter = 0; - unsigned ErrorsIgnoredNOLINT = 0; - unsigned ErrorsIgnoredNonUserCode = 0; - unsigned ErrorsIgnoredLineFilter = 0; - - unsigned errorsIgnored() const { - return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter + - ErrorsIgnoredNonUserCode + ErrorsIgnoredLineFilter; - } -}; - -/// Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine -/// provided by this context. -/// -/// A \c ClangTidyCheck always has access to the active context to report -/// warnings like: -/// \code -/// Context->Diag(Loc, "Single-argument constructors must be explicit") -/// << FixItHint::CreateInsertion(Loc, "explicit "); -/// \endcode -class ClangTidyContext { -public: - /// Initializes \c ClangTidyContext instance. - ClangTidyContext(std::unique_ptr OptionsProvider, - bool AllowEnablingAnalyzerAlphaCheckers = false, - bool EnableModuleHeadersParsing = false); - /// Sets the DiagnosticsEngine that diag() will emit diagnostics to. - // FIXME: this is required initialization, and should be a constructor param. - // Fix the context -> diag engine -> consumer -> context initialization cycle. - void setDiagnosticsEngine(DiagnosticsEngine *DiagEngine) { - this->DiagEngine = DiagEngine; - } - - ~ClangTidyContext(); - - /// Report any errors detected using this method. - /// - /// This is still under heavy development and will likely change towards using - /// tablegen'd diagnostic IDs. - /// FIXME: Figure out a way to manage ID spaces. - DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc, - StringRef Description, - DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - - DiagnosticBuilder diag(StringRef CheckName, StringRef Description, - 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 &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. - void setSourceManager(SourceManager *SourceMgr); - - /// Should be called when starting to process new translation unit. - void setCurrentFile(StringRef File); - - /// Returns the main file name of the current translation unit. - StringRef getCurrentFile() const { return CurrentFile; } - - /// Sets ASTContext for the current translation unit. - void setASTContext(ASTContext *Context); - - /// Gets the language options from the AST context. - const LangOptions &getLangOpts() const { return LangOpts; } - - /// Returns the name of the clang-tidy check which produced this - /// diagnostic ID. - std::string getCheckName(unsigned DiagnosticID) const; - - /// Returns \c true if the check is enabled for the \c CurrentFile. - /// - /// The \c CurrentFile can be changed using \c setCurrentFile. - bool isCheckEnabled(StringRef CheckName) const; - - /// Returns \c true if the check should be upgraded to error for the - /// \c CurrentFile. - bool treatAsError(StringRef CheckName) const; - - /// Returns global options. - const ClangTidyGlobalOptions &getGlobalOptions() const; - - /// Returns options for \c CurrentFile. - /// - /// The \c CurrentFile can be changed using \c setCurrentFile. - const ClangTidyOptions &getOptions() const; - - /// Returns options for \c File. Does not change or depend on - /// \c CurrentFile. - ClangTidyOptions getOptionsForFile(StringRef File) const; - - const FileExtensionsSet &getHeaderFileExtensions() const { - return HeaderFileExtensions; - } - - const FileExtensionsSet &getImplementationFileExtensions() const { - return ImplementationFileExtensions; - } - - /// Returns \c ClangTidyStats containing issued and ignored diagnostic - /// counters. - const ClangTidyStats &getStats() const { return Stats; } - - /// Control profile collection in clang-tidy. - void setEnableProfiling(bool Profile); - bool getEnableProfiling() const { return Profile; } - - /// Control storage of profile date. - void setProfileStoragePrefix(StringRef ProfilePrefix); - std::optional - getProfileStorageParams() const; - - /// Should be called when starting to process new translation unit. - void setCurrentBuildDirectory(StringRef BuildDirectory) { - CurrentBuildDirectory = std::string(BuildDirectory); - } - - /// Returns build directory of the current translation unit. - const std::string &getCurrentBuildDirectory() const { - return CurrentBuildDirectory; - } - - /// If the experimental alpha checkers from the static analyzer can be - /// enabled. - bool canEnableAnalyzerAlphaCheckers() const { - return AllowEnablingAnalyzerAlphaCheckers; - } - - // This method determines whether preprocessor-level module header parsing is - // enabled using the `--experimental-enable-module-headers-parsing` option. - bool canEnableModuleHeadersParsing() const { - return EnableModuleHeadersParsing; - } - - void setSelfContainedDiags(bool Value) { SelfContainedDiags = Value; } - - bool areDiagsSelfContained() const { return SelfContainedDiags; } - - using DiagLevelAndFormatString = std::pair; - DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, - SourceLocation Loc) { - return { - static_cast( - DiagEngine->getDiagnosticLevel(DiagnosticID, Loc)), - std::string( - DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID))}; - } - - void setOptionsCollector(llvm::StringSet<> *Collector) { - OptionsCollector = Collector; - } - llvm::StringSet<> *getOptionsCollector() const { return OptionsCollector; } - -private: - // Writes to Stats. - friend class ClangTidyDiagnosticConsumer; - - DiagnosticsEngine *DiagEngine = nullptr; - std::unique_ptr OptionsProvider; - - std::string CurrentFile; - ClangTidyOptions CurrentOptions; - - std::unique_ptr CheckFilter; - std::unique_ptr WarningAsErrorFilter; - - FileExtensionsSet HeaderFileExtensions; - FileExtensionsSet ImplementationFileExtensions; - - LangOptions LangOpts; - - ClangTidyStats Stats; - - std::string CurrentBuildDirectory; - - llvm::DenseMap CheckNamesByDiagnosticID; - - bool Profile = false; - std::string ProfilePrefix; - - bool AllowEnablingAnalyzerAlphaCheckers; - bool EnableModuleHeadersParsing; - - bool SelfContainedDiags = false; - - 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 -/// to see if exactly one note has a Fix and return it. Otherwise return -/// nullptr. -const llvm::StringMap * -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 EnableNolintBlocks = true); - - // FIXME: The concept of converting between FixItHints and Replacements is - // more generic and should be pulled out into a more useful Diagnostics - // library. - void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Info) override; - - // Retrieve the diagnostics that were captured. - std::vector take(); - -private: - void finalizeLastError(); - void removeIncompatibleErrors(); - void removeDuplicatedDiagnosticsOfAliasCheckers(); - - /// Returns the \c HeaderFilter constructed for the options set in the - /// context. - llvm::Regex *getHeaderFilter(); - - /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter - /// according to the diagnostic \p Location. - void checkFilters(SourceLocation Location, const SourceManager &Sources); - bool passesLineFilter(StringRef FileName, unsigned LineNumber) const; - - void forwardDiagnostic(const Diagnostic &Info); - - ClangTidyContext &Context; - DiagnosticsEngine *ExternalDiagEngine; - bool RemoveIncompatibleErrors; - bool GetFixesFromNotes; - bool EnableNolintBlocks; - std::vector Errors; - std::unique_ptr HeaderFilter; - bool LastErrorRelatesToUserCode = false; - bool LastErrorPassesLineFilter = false; - bool LastErrorWasIgnored = false; -}; - -} // end namespace tidy -} // end namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H diff --git a/ClangTidyForceLinker.h b/ClangTidyForceLinker.h deleted file mode 100644 index adde913..0000000 --- a/ClangTidyForceLinker.h +++ /dev/null @@ -1,142 +0,0 @@ -//===- ClangTidyForceLinker.h - clang-tidy --------------------------------===// -// -// 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_CLANG_TIDY_CLANGTIDYFORCELINKER_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYFORCELINKER_H - -#include "clang-tidy-config.h" -#include "llvm/Support/Compiler.h" - -namespace clang::tidy { - -// This anchor is used to force the linker to link the AbseilModule. -extern volatile int AbseilModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AbseilModuleAnchorDestination = - AbseilModuleAnchorSource; - -// This anchor is used to force the linker to link the AlteraModule. -extern volatile int AlteraModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AlteraModuleAnchorDestination = - AlteraModuleAnchorSource; - -// This anchor is used to force the linker to link the AndroidModule. -extern volatile int AndroidModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination = - AndroidModuleAnchorSource; - -// This anchor is used to force the linker to link the BoostModule. -extern volatile int BoostModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination = - BoostModuleAnchorSource; - -// This anchor is used to force the linker to link the BugproneModule. -extern volatile int BugproneModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination = - BugproneModuleAnchorSource; - -// This anchor is used to force the linker to link the CERTModule. -extern volatile int CERTModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination = - CERTModuleAnchorSource; - -// This anchor is used to force the linker to link the ConcurrencyModule. -extern volatile int ConcurrencyModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ConcurrencyModuleAnchorDestination = - ConcurrencyModuleAnchorSource; - -// This anchor is used to force the linker to link the CppCoreGuidelinesModule. -extern volatile int CppCoreGuidelinesModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination = - CppCoreGuidelinesModuleAnchorSource; - -// This anchor is used to force the linker to link the DarwinModule. -extern volatile int DarwinModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED DarwinModuleAnchorDestination = - DarwinModuleAnchorSource; - -// This anchor is used to force the linker to link the FuchsiaModule. -extern volatile int FuchsiaModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED FuchsiaModuleAnchorDestination = - FuchsiaModuleAnchorSource; - -// This anchor is used to force the linker to link the GoogleModule. -extern volatile int GoogleModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination = - GoogleModuleAnchorSource; - -// This anchor is used to force the linker to link the HICPPModule. -extern volatile int HICPPModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination = - HICPPModuleAnchorSource; - -// This anchor is used to force the linker to link the LinuxKernelModule. -extern volatile int LinuxKernelModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED LinuxKernelModuleAnchorDestination = - LinuxKernelModuleAnchorSource; - -// This anchor is used to force the linker to link the LLVMModule. -extern volatile int LLVMModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination = - LLVMModuleAnchorSource; - -// This anchor is used to force the linker to link the LLVMLibcModule. -extern volatile int LLVMLibcModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED LLVMLibcModuleAnchorDestination = - LLVMLibcModuleAnchorSource; - -// This anchor is used to force the linker to link the MiscModule. -extern volatile int MiscModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination = - MiscModuleAnchorSource; - -// This anchor is used to force the linker to link the ModernizeModule. -extern volatile int ModernizeModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination = - ModernizeModuleAnchorSource; - -#if CLANG_TIDY_ENABLE_STATIC_ANALYZER && \ - !defined(CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS) -// This anchor is used to force the linker to link the MPIModule. -extern volatile int MPIModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination = - MPIModuleAnchorSource; -#endif - -// This anchor is used to force the linker to link the ObjCModule. -extern volatile int ObjCModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ObjCModuleAnchorDestination = - ObjCModuleAnchorSource; - -// This anchor is used to force the linker to link the OpenMPModule. -extern volatile int OpenMPModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED OpenMPModuleAnchorDestination = - OpenMPModuleAnchorSource; - -// This anchor is used to force the linker to link the PerformanceModule. -extern volatile int PerformanceModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination = - PerformanceModuleAnchorSource; - -// This anchor is used to force the linker to link the PortabilityModule. -extern volatile int PortabilityModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination = - PortabilityModuleAnchorSource; - -// This anchor is used to force the linker to link the ReadabilityModule. -extern volatile int ReadabilityModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = - ReadabilityModuleAnchorSource; - -// This anchor is used to force the linker to link the ZirconModule. -extern volatile int ZirconModuleAnchorSource; -static int LLVM_ATTRIBUTE_UNUSED ZirconModuleAnchorDestination = - ZirconModuleAnchorSource; - -} // namespace clang::tidy - -#endif diff --git a/ClangTidyModule.h b/ClangTidyModule.h deleted file mode 100644 index 28f5433..0000000 --- a/ClangTidyModule.h +++ /dev/null @@ -1,98 +0,0 @@ -//===--- ClangTidyModule.h - clang-tidy -------------------------*- 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_CLANG_TIDY_CLANGTIDYMODULE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H - -#include "ClangTidyOptions.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include -#include - -namespace clang::tidy { - -class ClangTidyCheck; -class ClangTidyContext; - -/// A collection of \c ClangTidyCheckFactory instances. -/// -/// All clang-tidy modules register their check factories with an instance of -/// this object. -class ClangTidyCheckFactories { -public: - using CheckFactory = std::function( - llvm::StringRef Name, ClangTidyContext *Context)>; - - /// Registers check \p Factory with name \p Name. - /// - /// For all checks that have default constructors, use \c registerCheck. - void registerCheckFactory(llvm::StringRef Name, CheckFactory Factory); - - /// Registers the \c CheckType with the name \p Name. - /// - /// This method should be used for all \c ClangTidyChecks that don't require - /// constructor parameters. - /// - /// For example, if have a clang-tidy check like: - /// \code - /// class MyTidyCheck : public ClangTidyCheck { - /// void registerMatchers(ast_matchers::MatchFinder *Finder) override { - /// .. - /// } - /// }; - /// \endcode - /// you can register it with: - /// \code - /// class MyModule : public ClangTidyModule { - /// void addCheckFactories(ClangTidyCheckFactories &Factories) override { - /// Factories.registerCheck("myproject-my-check"); - /// } - /// }; - /// \endcode - template void registerCheck(llvm::StringRef CheckName) { - registerCheckFactory(CheckName, - [](llvm::StringRef Name, ClangTidyContext *Context) { - return std::make_unique(Name, Context); - }); - } - - /// Create instances of checks that are enabled. - std::vector> - createChecks(ClangTidyContext *Context) const; - - /// Create instances of checks that are enabled for the current Language. - std::vector> - createChecksForLanguage(ClangTidyContext *Context) const; - - using FactoryMap = llvm::StringMap; - FactoryMap::const_iterator begin() const { return Factories.begin(); } - FactoryMap::const_iterator end() const { return Factories.end(); } - bool empty() const { return Factories.empty(); } - -private: - FactoryMap Factories; -}; - -/// A clang-tidy module groups a number of \c ClangTidyChecks and gives -/// them a prefixed name. -class ClangTidyModule { -public: - virtual ~ClangTidyModule() {} - - /// Implement this function in order to register all \c CheckFactories - /// belonging to this module. - virtual void addCheckFactories(ClangTidyCheckFactories &CheckFactories) = 0; - - /// Gets default options for checks defined in this module. - virtual ClangTidyOptions getModuleOptions(); -}; - -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULE_H diff --git a/ClangTidyModuleRegistry.h b/ClangTidyModuleRegistry.h deleted file mode 100644 index 78d914b..0000000 --- a/ClangTidyModuleRegistry.h +++ /dev/null @@ -1,21 +0,0 @@ -//===--- ClangTidyModuleRegistry.h - clang-tidy -----------------*- 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_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H - -#include "ClangTidyModule.h" -#include "llvm/Support/Registry.h" - -namespace clang::tidy { - -using ClangTidyModuleRegistry = llvm::Registry; - -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H diff --git a/ClangTidyOptions.h b/ClangTidyOptions.h deleted file mode 100644 index e7636cb..0000000 --- a/ClangTidyOptions.h +++ /dev/null @@ -1,329 +0,0 @@ -//===--- ClangTidyOptions.h - clang-tidy ------------------------*- 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_CLANG_TIDY_CLANGTIDYOPTIONS_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H - -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/MemoryBufferRef.h" -#include "llvm/Support/VirtualFileSystem.h" -#include -#include -#include -#include -#include -#include - -namespace clang::tidy { - -/// Contains a list of line ranges in a single file. -struct FileFilter { - /// File name. - std::string Name; - - /// LineRange is a pair (inclusive). - using LineRange = std::pair; - - /// A list of line ranges in this file, for which we show warnings. - std::vector LineRanges; -}; - -/// Global options. These options are neither stored nor read from -/// configuration files. -struct ClangTidyGlobalOptions { - /// Output warnings from certain line ranges of certain files only. - /// If empty, no warnings will be filtered. - std::vector LineFilter; -}; - -/// Contains options for clang-tidy. These options may be read from -/// configuration files, and may be different for different translation units. -struct ClangTidyOptions { - /// These options are used for all settings that haven't been - /// overridden by the \c OptionsProvider. - /// - /// Allow no checks and no headers by default. This method initializes - /// check-specific options by calling \c ClangTidyModule::getModuleOptions() - /// of each registered \c ClangTidyModule. - static ClangTidyOptions getDefaults(); - - /// Overwrites all fields in here by the fields of \p Other that have a value. - /// \p Order specifies precedence of \p Other option. - ClangTidyOptions &mergeWith(const ClangTidyOptions &Other, unsigned Order); - - /// Creates a new \c ClangTidyOptions instance combined from all fields - /// of this instance overridden by the fields of \p Other that have a value. - /// \p Order specifies precedence of \p Other option. - [[nodiscard]] ClangTidyOptions merge(const ClangTidyOptions &Other, - unsigned Order) const; - - /// Checks filter. - std::optional Checks; - - /// WarningsAsErrors filter. - std::optional WarningsAsErrors; - - /// File extensions to consider to determine if a given diagnostic is located - /// in a header file. - std::optional> HeaderFileExtensions; - - /// File extensions to consider to determine if a given diagnostic is located - /// is located in an implementation file. - std::optional> ImplementationFileExtensions; - - /// Output warnings from headers matching this filter. Warnings from - /// main files will always be displayed. - std::optional HeaderFilterRegex; - - /// Output warnings from system headers matching \c HeaderFilterRegex. - std::optional SystemHeaders; - - /// Format code around applied fixes with clang-format using this - /// style. - /// - /// Can be one of: - /// * 'none' - don't format code around applied fixes; - /// * 'llvm', 'google', 'mozilla' or other predefined clang-format style - /// names; - /// * 'file' - use the .clang-format file in the closest parent directory of - /// each source file; - /// * '{inline-formatting-style-in-yaml-format}'. - /// - /// See clang-format documentation for more about configuring format style. - std::optional FormatStyle; - - /// Specifies the name or e-mail of the user running clang-tidy. - /// - /// This option is used, for example, to place the correct user name in TODO() - /// comments in the relevant check. - std::optional User; - - /// Helper structure for storing option value with priority of the value. - struct ClangTidyValue { - ClangTidyValue() = default; - ClangTidyValue(const char *Value) : Value(Value) {} - ClangTidyValue(llvm::StringRef Value, unsigned Priority = 0) - : Value(Value), Priority(Priority) {} - - std::string Value; - /// Priority stores relative precedence of the value loaded from config - /// files to disambiguate local vs global value from different levels. - unsigned Priority = 0; - }; - using StringPair = std::pair; - using OptionMap = llvm::StringMap; - - /// Key-value mapping used to store check-specific options. - OptionMap CheckOptions; - - using ArgList = std::vector; - - /// Add extra compilation arguments to the end of the list. - std::optional ExtraArgs; - - /// Add extra compilation arguments to the start of the list. - std::optional ExtraArgsBefore; - - /// Only used in the FileOptionsProvider and ConfigOptionsProvider. If true - /// 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 configuration file it finds in the directory using - /// the same logic as FileOptionsProvider. If false or missing, only this - /// configuration file will be used. - std::optional InheritParentConfig; - - /// Use colors in diagnostics. If missing, it will be auto detected. - std::optional UseColor; -}; - -/// Abstract interface for retrieving various ClangTidy options. -class ClangTidyOptionsProvider { -public: - static const char OptionsSourceTypeDefaultBinary[]; - static const char OptionsSourceTypeCheckCommandLineOption[]; - static const char OptionsSourceTypeConfigCommandLineOption[]; - - virtual ~ClangTidyOptionsProvider() {} - - /// Returns global options, which are independent of the file. - virtual const ClangTidyGlobalOptions &getGlobalOptions() = 0; - - /// ClangTidyOptions and its source. - // - /// clang-tidy has 3 types of the sources in order of increasing priority: - /// * clang-tidy binary. - /// * '-config' commandline option or a specific configuration file. If the - /// commandline option is specified, clang-tidy will ignore the - /// configuration file. - /// * '-checks' commandline option. - using OptionsSource = std::pair; - - /// Returns an ordered vector of OptionsSources, in order of increasing - /// priority. - virtual std::vector - getRawOptions(llvm::StringRef FileName) = 0; - - /// Returns options applying to a specific translation unit with the - /// specified \p FileName. - ClangTidyOptions getOptions(llvm::StringRef FileName); -}; - -/// Implementation of the \c ClangTidyOptionsProvider interface, which -/// returns the same options for all files. -class DefaultOptionsProvider : public ClangTidyOptionsProvider { -public: - DefaultOptionsProvider(ClangTidyGlobalOptions GlobalOptions, - ClangTidyOptions Options) - : GlobalOptions(std::move(GlobalOptions)), - DefaultOptions(std::move(Options)) {} - const ClangTidyGlobalOptions &getGlobalOptions() override { - return GlobalOptions; - } - std::vector getRawOptions(llvm::StringRef FileName) override; - -private: - ClangTidyGlobalOptions GlobalOptions; - ClangTidyOptions DefaultOptions; -}; - -class FileOptionsBaseProvider : public DefaultOptionsProvider { -protected: - // A pair of configuration file base name and a function parsing - // configuration from text in the corresponding format. - using ConfigFileHandler = std::pair (llvm::MemoryBufferRef)>>; - - /// Configuration file handlers listed in the order of priority. - /// - /// Custom configuration file formats can be supported by constructing the - /// list of handlers and passing it to the appropriate \c FileOptionsProvider - /// constructor. E.g. initialization of a \c FileOptionsProvider with support - /// of a custom configuration file format for files named ".my-tidy-config" - /// could look similar to this: - /// \code - /// FileOptionsProvider::ConfigFileHandlers ConfigHandlers; - /// ConfigHandlers.emplace_back(".my-tidy-config", parseMyConfigFormat); - /// ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration); - /// return std::make_unique( - /// GlobalOptions, DefaultOptions, OverrideOptions, ConfigHandlers); - /// \endcode - /// - /// With the order of handlers shown above, the ".my-tidy-config" file would - /// take precedence over ".clang-tidy" if both reside in the same directory. - using ConfigFileHandlers = std::vector; - - FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, - ClangTidyOptions DefaultOptions, - ClangTidyOptions OverrideOptions, - llvm::IntrusiveRefCntPtr FS); - - FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, - ClangTidyOptions DefaultOptions, - ClangTidyOptions OverrideOptions, - ConfigFileHandlers ConfigHandlers); - - void addRawFileOptions(llvm::StringRef AbsolutePath, - std::vector &CurOptions); - - /// Try to read configuration files from \p Directory using registered - /// \c ConfigHandlers. - std::optional tryReadConfigFile(llvm::StringRef Directory); - - llvm::StringMap CachedOptions; - ClangTidyOptions OverrideOptions; - ConfigFileHandlers ConfigHandlers; - llvm::IntrusiveRefCntPtr FS; -}; - -/// Implementation of ClangTidyOptions interface, which is used for -/// '-config' command-line option. -class ConfigOptionsProvider : public FileOptionsBaseProvider { -public: - ConfigOptionsProvider( - ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, - ClangTidyOptions ConfigOptions, ClangTidyOptions OverrideOptions, - llvm::IntrusiveRefCntPtr FS = nullptr); - std::vector getRawOptions(llvm::StringRef FileName) override; - -private: - ClangTidyOptions ConfigOptions; -}; - -/// Implementation of the \c ClangTidyOptionsProvider interface, which -/// tries to find a configuration file in the closest parent directory of each -/// source file. -/// -/// By default, files named ".clang-tidy" will be considered, and the -/// \c clang::tidy::parseConfiguration function will be used for parsing, but a -/// custom set of configuration file names and parsing functions can be -/// specified using the appropriate constructor. -class FileOptionsProvider : public FileOptionsBaseProvider { -public: - /// Initializes the \c FileOptionsProvider instance. - /// - /// \param GlobalOptions are just stored and returned to the caller of - /// \c getGlobalOptions. - /// - /// \param DefaultOptions are used for all settings not specified in a - /// configuration file. - /// - /// If any of the \param OverrideOptions fields are set, they will override - /// whatever options are read from the configuration file. - FileOptionsProvider( - ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, - ClangTidyOptions OverrideOptions, - llvm::IntrusiveRefCntPtr FS = nullptr); - - /// Initializes the \c FileOptionsProvider instance with a custom set - /// of configuration file handlers. - /// - /// \param GlobalOptions are just stored and returned to the caller of - /// \c getGlobalOptions. - /// - /// \param DefaultOptions are used for all settings not specified in a - /// configuration file. - /// - /// If any of the \param OverrideOptions fields are set, they will override - /// whatever options are read from the configuration file. - /// - /// \param ConfigHandlers specifies a custom set of configuration file - /// handlers. Each handler is a pair of configuration file name and a function - /// that can parse configuration from this file type. The configuration files - /// in each directory are searched for in the order of appearance in - /// \p ConfigHandlers. - FileOptionsProvider(ClangTidyGlobalOptions GlobalOptions, - ClangTidyOptions DefaultOptions, - ClangTidyOptions OverrideOptions, - ConfigFileHandlers ConfigHandlers); - - std::vector getRawOptions(llvm::StringRef FileName) override; -}; - -/// Parses LineFilter from JSON and stores it to the \p Options. -std::error_code parseLineFilter(llvm::StringRef LineFilter, - ClangTidyGlobalOptions &Options); - -/// Parses configuration from JSON and returns \c ClangTidyOptions or an -/// error. -llvm::ErrorOr -parseConfiguration(llvm::MemoryBufferRef Config); - -using DiagCallback = llvm::function_ref; - -llvm::ErrorOr -parseConfigurationWithDiags(llvm::MemoryBufferRef Config, DiagCallback Handler); - -/// Serializes configuration to a YAML-encoded string. -std::string configurationAsText(const ClangTidyOptions &Options); - -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H diff --git a/ClangTidyProfiling.h b/ClangTidyProfiling.h deleted file mode 100644 index b6f7d66..0000000 --- a/ClangTidyProfiling.h +++ /dev/null @@ -1,58 +0,0 @@ -//===--- ClangTidyProfiling.h - clang-tidy ----------------------*- 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_CLANG_TIDY_CLANGTIDYPROFILING_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H - -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/Chrono.h" -#include "llvm/Support/Timer.h" -#include -#include - -namespace llvm { -class raw_ostream; -} // namespace llvm - -namespace clang::tidy { - -class ClangTidyProfiling { -public: - struct StorageParams { - llvm::sys::TimePoint<> Timestamp; - std::string SourceFilename; - std::string StoreFilename; - - StorageParams() = default; - - StorageParams(llvm::StringRef ProfilePrefix, llvm::StringRef SourceFile); - }; - -private: - std::optional TG; - - std::optional Storage; - - void printUserFriendlyTable(llvm::raw_ostream &OS); - void printAsJSON(llvm::raw_ostream &OS); - - void storeProfileData(); - -public: - llvm::StringMap Records; - - ClangTidyProfiling() = default; - - ClangTidyProfiling(std::optional Storage); - - ~ClangTidyProfiling(); -}; - -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYPROFILING_H diff --git a/aliceO2/AliceO2TidyModule.cpp b/aliceO2/AliceO2TidyModule.cpp index a8d79da..71f5ac1 100644 --- a/aliceO2/AliceO2TidyModule.cpp +++ b/aliceO2/AliceO2TidyModule.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "../ClangTidy.h" -#include "../ClangTidyModule.h" -#include "../ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyModule.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" #include "MemberNamesCheck.h" #include "NamespaceNamingCheck.h" #include "SizeofCheck.h" diff --git a/aliceO2/MemberNamesCheck.h b/aliceO2/MemberNamesCheck.h index f61119e..1785110 100644 --- a/aliceO2/MemberNamesCheck.h +++ b/aliceO2/MemberNamesCheck.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_MEMBER_NAMES_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_MEMBER_NAMES_H -#include "../ClangTidy.h" -#include "../ClangTidyCheck.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyCheck.h" #include namespace clang { diff --git a/aliceO2/NamespaceNamingCheck.h b/aliceO2/NamespaceNamingCheck.h index 17cc9e9..b5c08fc 100644 --- a/aliceO2/NamespaceNamingCheck.h +++ b/aliceO2/NamespaceNamingCheck.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_NAMESPACE_NAMING_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_NAMESPACE_NAMING_H -#include "../ClangTidy.h" -#include "../ClangTidyCheck.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/aliceO2/SizeofCheck.h b/aliceO2/SizeofCheck.h index c291f5f..7a02883 100644 --- a/aliceO2/SizeofCheck.h +++ b/aliceO2/SizeofCheck.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_SIZEOF_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ALICEO2_SIZEOF_H -#include "../ClangTidy.h" -#include "../ClangTidyCheck.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/plugin/FooCheck.h b/plugin/FooCheck.h index 2039ccc..5d843bb 100644 --- a/plugin/FooCheck.h +++ b/plugin/FooCheck.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PLUGIN_FOO_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PLUGIN_FOO_H -#include "../ClangTidy.h" -#include "../ClangTidyCheck.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/plugin/PluginTidyModule.cpp b/plugin/PluginTidyModule.cpp index 20a726e..c8f4b10 100644 --- a/plugin/PluginTidyModule.cpp +++ b/plugin/PluginTidyModule.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "../ClangTidy.h" -#include "../ClangTidyModule.h" -#include "../ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyModule.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" #include "FooCheck.h" #include diff --git a/reporting/InterfaceLister.h b/reporting/InterfaceLister.h index f517be6..5a4c91a 100644 --- a/reporting/InterfaceLister.h +++ b/reporting/InterfaceLister.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INTERFACELISTER_NAMES_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INTERFACELISTER_NAMES_H -#include "../ClangTidy.h" -#include "../ClangTidyCheck.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/reporting/ReportingTidyModule.cpp b/reporting/ReportingTidyModule.cpp index adf1f7d..3674a70 100644 --- a/reporting/ReportingTidyModule.cpp +++ b/reporting/ReportingTidyModule.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "../ClangTidy.h" -#include "../ClangTidyModule.h" -#include "../ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyModule.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" #include "InterfaceLister.h" #include "VirtFuncLister.h" diff --git a/reporting/VirtFuncLister.h b/reporting/VirtFuncLister.h index 5f3a6b2..d8ccf21 100644 --- a/reporting/VirtFuncLister.h +++ b/reporting/VirtFuncLister.h @@ -10,8 +10,8 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_VIRTFUNCLISTER_NAMES_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_VIRTFUNCLISTER_NAMES_H -#include "../ClangTidy.h" -#include "../ClangTidyCheck.h" +#include "clang-tidy/ClangTidy.h" +#include "clang-tidy/ClangTidyCheck.h" namespace clang { namespace tidy { diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp index 6e9618d..48066ef 100644 --- a/tool/ClangTidyMain.cpp +++ b/tool/ClangTidyMain.cpp @@ -15,8 +15,8 @@ //===----------------------------------------------------------------------===// #include "ClangTidyMain.h" -#include "../ClangTidy.h" -#include "../ClangTidyForceLinker.h" +#include "clang-tidy/ClangTidy.h" +//#include "clang-tidy/ClangTidyForceLinker.h" #include "../GlobList.h" #include "clang/Tooling/CommonOptionsParser.h" #include "llvm/ADT/StringSet.h" @@ -415,7 +415,7 @@ static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob, if (Cur.empty()) continue; Cur.consume_front("-"); - if (Cur.startswith("clang-diagnostic")) + if (Cur.starts_with("clang-diagnostic")) continue; if (Cur.contains('*')) { SmallString<128> RegexText("^"); From 5ddf284a2bfccbbe6e58397197c1bebf000140bf Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:33:46 +0200 Subject: [PATCH 18/20] Update to the Clang v20.1.7 version of the main Also make sure we build only the plugin, since the upstream clang now supports loading clang-tidy plugins via the -load option. --- CMakeLists.txt | 56 +-- FileExtensionsSet.h | 19 - GlobList.h | 66 --- NoLintDirectiveHandler.h | 47 --- aliceO2/CMakeLists.txt | 31 +- clang-tidy-config.h | 10 - omp.h | 521 ----------------------- plugin/CMakeLists.txt | 17 - plugin/FooCheck.cpp | 34 -- plugin/FooCheck.h | 36 -- plugin/PluginTidyModule.cpp | 48 --- reporting/CMakeLists.txt | 16 - reporting/InterfaceLister.cpp | 46 -- reporting/InterfaceLister.h | 43 -- reporting/ReportingTidyModule.cpp | 40 -- reporting/VirtFuncLister.cpp | 85 ---- reporting/VirtFuncLister.h | 36 -- tool/CMakeLists.txt | 70 ---- tool/ClangTidyMain.cpp | 671 ------------------------------ tool/ClangTidyMain.h | 23 - tool/clang-tidy-diff.py | 121 ------ 21 files changed, 29 insertions(+), 2007 deletions(-) delete mode 100644 FileExtensionsSet.h delete mode 100644 GlobList.h delete mode 100644 NoLintDirectiveHandler.h delete mode 100644 clang-tidy-config.h delete mode 100644 omp.h delete mode 100644 plugin/CMakeLists.txt delete mode 100644 plugin/FooCheck.cpp delete mode 100644 plugin/FooCheck.h delete mode 100644 plugin/PluginTidyModule.cpp delete mode 100644 reporting/CMakeLists.txt delete mode 100644 reporting/InterfaceLister.cpp delete mode 100644 reporting/InterfaceLister.h delete mode 100644 reporting/ReportingTidyModule.cpp delete mode 100644 reporting/VirtFuncLister.cpp delete mode 100644 reporting/VirtFuncLister.h delete mode 100644 tool/ClangTidyMain.cpp delete mode 100644 tool/ClangTidyMain.h delete mode 100755 tool/clang-tidy-diff.py diff --git a/CMakeLists.txt b/CMakeLists.txt index ff3e144..7ebacb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,62 +1,34 @@ cmake_minimum_required(VERSION 3.4.3) enable_testing() -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # require at least gcc 12.0 !! - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) - message(FATAL_ERROR "GCC version must be at least 12.0!") - endif() -endif() - - -if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) - project(O2CodeChecker) - - - # find clang + llvm - find_package(Clang REQUIRED CONFIG) - - if( LLVM_FOUND ) - list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") - include(AddLLVM) +project(O2CodeChecker) - # set the compiler flags to match llvm - include(HandleLLVMOptions) - endif() +# find clang + llvm +find_package(Clang REQUIRED CONFIG) - # Make sure that our source directory is on the current cmake module path so that - # we can include cmake files from this directory. - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") +if( LLVM_FOUND ) + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") + include(AddLLVM) - # include Clang macros (unfortunately they are not part of the cmake installation) - include(AddClang) + # set the compiler flags to match llvm + include(HandleLLVMOptions) +endif() - # add include directories - include_directories(${LLVM_INCLUDE_DIRS}) +# Make sure that our source directory is on the current cmake module path so that +# we can include cmake files from this directory. +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") -set(LLVM_LINK_COMPONENTS - Support - ) +# include Clang macros (unfortunately they are not part of the cmake installation) +include(AddClang) # the main executable add_subdirectory(tool) # the specific aliceO2 checker code add_subdirectory(aliceO2) -# the specific reporting tools code -add_subdirectory(reporting) - -# plugin -add_subdirectory(plugin) # for testing add_subdirectory(test) # some extra utilities add_subdirectory(utility) - -string(REPLACE "." ";" LLVM_PACKAGE_VERSION_LIST ${LLVM_PACKAGE_VERSION}) -list(GET LLVM_PACKAGE_VERSION_LIST 0 LLVM_PACKAGE_VERSION_MAJOR) -install(FILES omp.h DESTINATION lib/clang/${LLVM_PACKAGE_VERSION_MAJOR}/include) - -endif() diff --git a/FileExtensionsSet.h b/FileExtensionsSet.h deleted file mode 100644 index 7ca4e6e..0000000 --- a/FileExtensionsSet.h +++ /dev/null @@ -1,19 +0,0 @@ -//===--- FileExtensionsSet.h - clang-tidy -----------------------*- 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_CLANG_TIDY_FILE_EXTENSIONS_SET_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FILE_EXTENSIONS_SET_H - -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringRef.h" - -namespace clang::tidy { -using FileExtensionsSet = llvm::SmallSet; -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FILE_EXTENSIONS_SET_H diff --git a/GlobList.h b/GlobList.h deleted file mode 100644 index 44af182..0000000 --- a/GlobList.h +++ /dev/null @@ -1,66 +0,0 @@ -//===--- GlobList.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_CLANG_TIDY_GLOBLIST_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Regex.h" - -namespace clang::tidy { - -/// Read-only set of strings represented as a list of positive and negative -/// globs. -/// -/// Positive globs add all matched strings to the set, negative globs remove -/// them in the order of appearance in the list. -class GlobList { -public: - virtual ~GlobList() = default; - - /// \p Globs is a comma-separated list of globs (only the '*' metacharacter is - /// supported) with an optional '-' prefix to denote exclusion. - /// - /// An empty \p Globs string is interpreted as one glob that matches an empty - /// string. - /// - /// \p KeepNegativeGlobs a bool flag indicating whether to keep negative - /// globs from \p Globs or not. When false, negative globs are simply ignored. - GlobList(StringRef Globs, bool KeepNegativeGlobs = true); - - /// Returns \c true if the pattern matches \p S. The result is the last - /// matching glob's Positive flag. - virtual bool contains(StringRef S) const; - -private: - struct GlobListItem { - bool IsPositive; - llvm::Regex Regex; - }; - SmallVector Items; -}; - -/// A \p GlobList that caches search results, so that search is performed only -/// once for the same query. -class CachedGlobList final : public GlobList { -public: - using GlobList::GlobList; - - /// \see GlobList::contains - bool contains(StringRef S) const override; - -private: - mutable llvm::StringMap Cache; -}; - -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H diff --git a/NoLintDirectiveHandler.h b/NoLintDirectiveHandler.h deleted file mode 100644 index e862195..0000000 --- a/NoLintDirectiveHandler.h +++ /dev/null @@ -1,47 +0,0 @@ -//===-- clang-tools-extra/clang-tidy/NoLintDirectiveHandler.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_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H - -#include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/StringRef.h" -#include - -namespace clang::tooling { -struct Diagnostic; -} // namespace clang::tooling - -namespace llvm { -template class SmallVectorImpl; -} // namespace llvm - -namespace clang::tidy { - -/// This class is used to locate NOLINT comments in the file being analyzed, to -/// decide whether a diagnostic should be suppressed. -/// This class keeps a cache of every NOLINT comment found so that files do not -/// have to be repeatedly parsed each time a new diagnostic is raised. -class NoLintDirectiveHandler { -public: - NoLintDirectiveHandler(); - ~NoLintDirectiveHandler(); - - bool shouldSuppress(DiagnosticsEngine::Level DiagLevel, - const Diagnostic &Diag, llvm::StringRef DiagName, - llvm::SmallVectorImpl &NoLintErrors, - bool AllowIO, bool EnableNoLintBlocks); - -private: - class Impl; - std::unique_ptr PImpl; -}; - -} // namespace clang::tidy - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_NOLINTDIRECTIVEHANDLER_H diff --git a/aliceO2/CMakeLists.txt b/aliceO2/CMakeLists.txt index 0c487da..e00c918 100644 --- a/aliceO2/CMakeLists.txt +++ b/aliceO2/CMakeLists.txt @@ -1,17 +1,16 @@ -set(LLVM_LINK_COMPONENTS support) +add_library(clangTidyAliceO2Module MODULE "") +target_compile_options(clangTidyAliceO2Module PRIVATE -fno-rtti) +target_include_directories(clangTidyAliceO2Module + PRIVATE + ${CLANG_INCLUDE_DIRS} + ${LLVM_INCLUDE_DIRS} +) -add_clang_library(clangTidyAliceO2Module - AliceO2TidyModule.cpp - MemberNamesCheck.cpp - NamespaceNamingCheck.cpp - SizeofCheck.cpp - - LINK_LIBS - clangAST - clangASTMatchers - clangBasic - clangLex - clangTidy - clangTidyUtils - clangTooling - ) +target_sources(clangTidyAliceO2Module + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/AliceO2TidyModule.cpp + ${CMAKE_CURRENT_LIST_DIR}/MemberNamesCheck.cpp + ${CMAKE_CURRENT_LIST_DIR}/NamespaceNamingCheck.cpp + ${CMAKE_CURRENT_LIST_DIR}/SizeofCheck.cpp +) +install(TARGETS clangTidyAliceO2Module LIBRARY DESTINATION lib) diff --git a/clang-tidy-config.h b/clang-tidy-config.h deleted file mode 100644 index c3847d4..0000000 --- a/clang-tidy-config.h +++ /dev/null @@ -1,10 +0,0 @@ -/* This generated file is for internal use. Do not include it from headers. */ - -#ifdef CLANG_TIDY_CONFIG_H -#error clang-tidy-config.h can only be included once -#else -#define CLANG_TIDY_CONFIG_H - -#define CLANG_TIDY_ENABLE_STATIC_ANALYZER 1 - -#endif diff --git a/omp.h b/omp.h deleted file mode 100644 index 94be362..0000000 --- a/omp.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * include/omp.h.var - */ - - -//===----------------------------------------------------------------------===// -// -// 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 __OMP_H -# define __OMP_H - -# include -# include -# include - -# define KMP_VERSION_MAJOR 5 -# define KMP_VERSION_MINOR 0 -# define KMP_VERSION_BUILD 20140926 -# define KMP_BUILD_DATE "No_Timestamp" - -# ifdef __cplusplus - extern "C" { -# endif - -# define omp_set_affinity_format ompc_set_affinity_format -# define omp_get_affinity_format ompc_get_affinity_format -# define omp_display_affinity ompc_display_affinity -# define omp_capture_affinity ompc_capture_affinity - -# if defined(_WIN32) -# define __KAI_KMPC_CONVENTION __cdecl -# ifndef __KMP_IMP -# define __KMP_IMP __declspec(dllimport) -# endif -# else -# define __KAI_KMPC_CONVENTION -# ifndef __KMP_IMP -# define __KMP_IMP -# endif -# endif - - /* schedule kind constants */ - typedef enum omp_sched_t { - omp_sched_static = 1, - omp_sched_dynamic = 2, - omp_sched_guided = 3, - omp_sched_auto = 4, - omp_sched_monotonic = 0x80000000 - } omp_sched_t; - - /* set API functions */ - extern void __KAI_KMPC_CONVENTION omp_set_num_threads (int); - extern void __KAI_KMPC_CONVENTION omp_set_dynamic (int); - extern void __KAI_KMPC_CONVENTION omp_set_nested (int); - extern void __KAI_KMPC_CONVENTION omp_set_max_active_levels (int); - extern void __KAI_KMPC_CONVENTION omp_set_schedule (omp_sched_t, int); - - /* query API functions */ - extern int __KAI_KMPC_CONVENTION omp_get_num_threads (void); - extern int __KAI_KMPC_CONVENTION omp_get_dynamic (void); - extern int __KAI_KMPC_CONVENTION omp_get_nested (void); - extern int __KAI_KMPC_CONVENTION omp_get_max_threads (void); - extern int __KAI_KMPC_CONVENTION omp_get_thread_num (void); - extern int __KAI_KMPC_CONVENTION omp_get_num_procs (void); - extern int __KAI_KMPC_CONVENTION omp_in_parallel (void); - extern int __KAI_KMPC_CONVENTION omp_in_final (void); - extern int __KAI_KMPC_CONVENTION omp_get_active_level (void); - extern int __KAI_KMPC_CONVENTION omp_get_level (void); - extern int __KAI_KMPC_CONVENTION omp_get_ancestor_thread_num (int); - extern int __KAI_KMPC_CONVENTION omp_get_team_size (int); - extern int __KAI_KMPC_CONVENTION omp_get_thread_limit (void); - extern int __KAI_KMPC_CONVENTION omp_get_max_active_levels (void); - extern void __KAI_KMPC_CONVENTION omp_get_schedule (omp_sched_t *, int *); - extern int __KAI_KMPC_CONVENTION omp_get_max_task_priority (void); - - /* lock API functions */ - typedef struct omp_lock_t { - void * _lk; - } omp_lock_t; - - extern void __KAI_KMPC_CONVENTION omp_init_lock (omp_lock_t *); - extern void __KAI_KMPC_CONVENTION omp_set_lock (omp_lock_t *); - extern void __KAI_KMPC_CONVENTION omp_unset_lock (omp_lock_t *); - extern void __KAI_KMPC_CONVENTION omp_destroy_lock (omp_lock_t *); - extern int __KAI_KMPC_CONVENTION omp_test_lock (omp_lock_t *); - - /* nested lock API functions */ - typedef struct omp_nest_lock_t { - void * _lk; - } omp_nest_lock_t; - - extern void __KAI_KMPC_CONVENTION omp_init_nest_lock (omp_nest_lock_t *); - extern void __KAI_KMPC_CONVENTION omp_set_nest_lock (omp_nest_lock_t *); - extern void __KAI_KMPC_CONVENTION omp_unset_nest_lock (omp_nest_lock_t *); - extern void __KAI_KMPC_CONVENTION omp_destroy_nest_lock (omp_nest_lock_t *); - extern int __KAI_KMPC_CONVENTION omp_test_nest_lock (omp_nest_lock_t *); - - /* OpenMP 5.0 Synchronization hints*/ - typedef enum omp_sync_hint_t { - omp_sync_hint_none = 0, - omp_lock_hint_none = omp_sync_hint_none, - omp_sync_hint_uncontended = 1, - omp_lock_hint_uncontended = omp_sync_hint_uncontended, - omp_sync_hint_contended = (1<<1), - omp_lock_hint_contended = omp_sync_hint_contended, - omp_sync_hint_nonspeculative = (1<<2), - omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, - omp_sync_hint_speculative = (1<<3), - omp_lock_hint_speculative = omp_sync_hint_speculative, - kmp_lock_hint_hle = (1<<16), - kmp_lock_hint_rtm = (1<<17), - kmp_lock_hint_adaptive = (1<<18) - } omp_sync_hint_t; - - /* lock hint type for dynamic user lock */ - typedef omp_sync_hint_t omp_lock_hint_t; - - /* hinted lock initializers */ - extern void __KAI_KMPC_CONVENTION omp_init_lock_with_hint(omp_lock_t *, omp_lock_hint_t); - extern void __KAI_KMPC_CONVENTION omp_init_nest_lock_with_hint(omp_nest_lock_t *, omp_lock_hint_t); - - /* time API functions */ - extern double __KAI_KMPC_CONVENTION omp_get_wtime (void); - extern double __KAI_KMPC_CONVENTION omp_get_wtick (void); - - /* OpenMP 4.0 */ - extern int __KAI_KMPC_CONVENTION omp_get_default_device (void); - extern void __KAI_KMPC_CONVENTION omp_set_default_device (int); - extern int __KAI_KMPC_CONVENTION omp_is_initial_device (void); - extern int __KAI_KMPC_CONVENTION omp_get_num_devices (void); - extern int __KAI_KMPC_CONVENTION omp_get_num_teams (void); - extern int __KAI_KMPC_CONVENTION omp_get_team_num (void); - extern int __KAI_KMPC_CONVENTION omp_get_cancellation (void); - - /* OpenMP 4.5 */ - extern int __KAI_KMPC_CONVENTION omp_get_initial_device (void); - extern void* __KAI_KMPC_CONVENTION omp_target_alloc(size_t, int); - extern void __KAI_KMPC_CONVENTION omp_target_free(void *, int); - extern int __KAI_KMPC_CONVENTION omp_target_is_present(const void *, int); - extern int __KAI_KMPC_CONVENTION omp_target_memcpy(void *, const void *, size_t, size_t, size_t, int, int); - extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect(void *, const void *, size_t, int, const size_t *, - const size_t *, const size_t *, const size_t *, const size_t *, int, int); - extern int __KAI_KMPC_CONVENTION omp_target_associate_ptr(const void *, const void *, size_t, size_t, int); - extern int __KAI_KMPC_CONVENTION omp_target_disassociate_ptr(const void *, int); - - /* OpenMP 5.0 */ - extern int __KAI_KMPC_CONVENTION omp_get_device_num (void); - typedef void * omp_depend_t; - - /* OpenMP 5.1 interop */ - typedef intptr_t omp_intptr_t; - - /* 0..omp_get_num_interop_properties()-1 are reserved for implementation-defined properties */ - typedef enum omp_interop_property { - omp_ipr_fr_id = -1, - omp_ipr_fr_name = -2, - omp_ipr_vendor = -3, - omp_ipr_vendor_name = -4, - omp_ipr_device_num = -5, - omp_ipr_platform = -6, - omp_ipr_device = -7, - omp_ipr_device_context = -8, - omp_ipr_targetsync = -9, - omp_ipr_first = -9 - } omp_interop_property_t; - - #define omp_interop_none 0 - - typedef enum omp_interop_rc { - omp_irc_no_value = 1, - omp_irc_success = 0, - omp_irc_empty = -1, - omp_irc_out_of_range = -2, - omp_irc_type_int = -3, - omp_irc_type_ptr = -4, - omp_irc_type_str = -5, - omp_irc_other = -6 - } omp_interop_rc_t; - - typedef enum omp_interop_fr { - omp_ifr_cuda = 1, - omp_ifr_cuda_driver = 2, - omp_ifr_opencl = 3, - omp_ifr_sycl = 4, - omp_ifr_hip = 5, - omp_ifr_level_zero = 6, - omp_ifr_last = 7 - } omp_interop_fr_t; - - typedef void * omp_interop_t; - - /*! - * The `omp_get_num_interop_properties` routine retrieves the number of implementation-defined properties available for an `omp_interop_t` object. - */ - extern int __KAI_KMPC_CONVENTION omp_get_num_interop_properties(const omp_interop_t); - /*! - * The `omp_get_interop_int` routine retrieves an integer property from an `omp_interop_t` object. - */ - extern omp_intptr_t __KAI_KMPC_CONVENTION omp_get_interop_int(const omp_interop_t, omp_interop_property_t, int *); - /*! - * The `omp_get_interop_ptr` routine retrieves a pointer property from an `omp_interop_t` object. - */ - extern void * __KAI_KMPC_CONVENTION omp_get_interop_ptr(const omp_interop_t, omp_interop_property_t, int *); - /*! - * The `omp_get_interop_str` routine retrieves a string property from an `omp_interop_t` object. - */ - extern const char * __KAI_KMPC_CONVENTION omp_get_interop_str(const omp_interop_t, omp_interop_property_t, int *); - /*! - * The `omp_get_interop_name` routine retrieves a property name from an `omp_interop_t` object. - */ - extern const char * __KAI_KMPC_CONVENTION omp_get_interop_name(const omp_interop_t, omp_interop_property_t); - /*! - * The `omp_get_interop_type_desc` routine retrieves a description of the type of a property associated with an `omp_interop_t` object. - */ - extern const char * __KAI_KMPC_CONVENTION omp_get_interop_type_desc(const omp_interop_t, omp_interop_property_t); - /*! - * The `omp_get_interop_rc_desc` routine retrieves a description of the return code associated with an `omp_interop_t` object. - */ - extern const char * __KAI_KMPC_CONVENTION omp_get_interop_rc_desc(const omp_interop_t, omp_interop_rc_t); - - /* OpenMP 5.1 device memory routines */ - - /*! - * The `omp_target_memcpy_async` routine asynchronously performs a copy between any combination of host and device pointers. - */ - extern int __KAI_KMPC_CONVENTION omp_target_memcpy_async(void *, const void *, size_t, size_t, size_t, int, - int, int, omp_depend_t *); - /*! - * The `omp_target_memcpy_rect_async` routine asynchronously performs a copy between any combination of host and device pointers. - */ - extern int __KAI_KMPC_CONVENTION omp_target_memcpy_rect_async(void *, const void *, size_t, int, const size_t *, - const size_t *, const size_t *, const size_t *, const size_t *, int, int, - int, omp_depend_t *); - - /* OpenMP 6.0 device memory routines */ - extern void * __KAI_KMPC_CONVENTION omp_target_memset(void *, int, size_t, int); - extern void * __KAI_KMPC_CONVENTION omp_target_memset_async(void *, int, size_t, int, int, omp_depend_t *); - - /*! - * The `omp_get_mapped_ptr` routine returns the device pointer that is associated with a host pointer for a given device. - */ - extern void * __KAI_KMPC_CONVENTION omp_get_mapped_ptr(const void *, int); - extern int __KAI_KMPC_CONVENTION omp_target_is_accessible(const void *, size_t, int); - - /* kmp API functions */ - extern int __KAI_KMPC_CONVENTION kmp_get_stacksize (void); - extern void __KAI_KMPC_CONVENTION kmp_set_stacksize (int); - extern size_t __KAI_KMPC_CONVENTION kmp_get_stacksize_s (void); - extern void __KAI_KMPC_CONVENTION kmp_set_stacksize_s (size_t); - extern int __KAI_KMPC_CONVENTION kmp_get_blocktime (void); - extern int __KAI_KMPC_CONVENTION kmp_get_library (void); - extern void __KAI_KMPC_CONVENTION kmp_set_blocktime (int); - extern void __KAI_KMPC_CONVENTION kmp_set_library (int); - extern void __KAI_KMPC_CONVENTION kmp_set_library_serial (void); - extern void __KAI_KMPC_CONVENTION kmp_set_library_turnaround (void); - extern void __KAI_KMPC_CONVENTION kmp_set_library_throughput (void); - extern void __KAI_KMPC_CONVENTION kmp_set_defaults (char const *); - extern void __KAI_KMPC_CONVENTION kmp_set_disp_num_buffers (int); - - /* Intel affinity API */ - typedef void * kmp_affinity_mask_t; - - extern int __KAI_KMPC_CONVENTION kmp_set_affinity (kmp_affinity_mask_t *); - extern int __KAI_KMPC_CONVENTION kmp_get_affinity (kmp_affinity_mask_t *); - extern int __KAI_KMPC_CONVENTION kmp_get_affinity_max_proc (void); - extern void __KAI_KMPC_CONVENTION kmp_create_affinity_mask (kmp_affinity_mask_t *); - extern void __KAI_KMPC_CONVENTION kmp_destroy_affinity_mask (kmp_affinity_mask_t *); - extern int __KAI_KMPC_CONVENTION kmp_set_affinity_mask_proc (int, kmp_affinity_mask_t *); - extern int __KAI_KMPC_CONVENTION kmp_unset_affinity_mask_proc (int, kmp_affinity_mask_t *); - extern int __KAI_KMPC_CONVENTION kmp_get_affinity_mask_proc (int, kmp_affinity_mask_t *); - - /* OpenMP 4.0 affinity API */ - typedef enum omp_proc_bind_t { - omp_proc_bind_false = 0, - omp_proc_bind_true = 1, - omp_proc_bind_master = 2, - omp_proc_bind_close = 3, - omp_proc_bind_spread = 4 - } omp_proc_bind_t; - - extern omp_proc_bind_t __KAI_KMPC_CONVENTION omp_get_proc_bind (void); - - /* OpenMP 4.5 affinity API */ - extern int __KAI_KMPC_CONVENTION omp_get_num_places (void); - extern int __KAI_KMPC_CONVENTION omp_get_place_num_procs (int); - extern void __KAI_KMPC_CONVENTION omp_get_place_proc_ids (int, int *); - extern int __KAI_KMPC_CONVENTION omp_get_place_num (void); - extern int __KAI_KMPC_CONVENTION omp_get_partition_num_places (void); - extern void __KAI_KMPC_CONVENTION omp_get_partition_place_nums (int *); - - extern void * __KAI_KMPC_CONVENTION kmp_malloc (size_t); - extern void * __KAI_KMPC_CONVENTION kmp_aligned_malloc (size_t, size_t); - extern void * __KAI_KMPC_CONVENTION kmp_calloc (size_t, size_t); - extern void * __KAI_KMPC_CONVENTION kmp_realloc (void *, size_t); - extern void __KAI_KMPC_CONVENTION kmp_free (void *); - - extern void __KAI_KMPC_CONVENTION kmp_set_warnings_on(void); - extern void __KAI_KMPC_CONVENTION kmp_set_warnings_off(void); - - /* OpenMP 5.0 Tool Control */ - typedef enum omp_control_tool_result_t { - omp_control_tool_notool = -2, - omp_control_tool_nocallback = -1, - omp_control_tool_success = 0, - omp_control_tool_ignored = 1 - } omp_control_tool_result_t; - - typedef enum omp_control_tool_t { - omp_control_tool_start = 1, - omp_control_tool_pause = 2, - omp_control_tool_flush = 3, - omp_control_tool_end = 4 - } omp_control_tool_t; - - extern int __KAI_KMPC_CONVENTION omp_control_tool(int, int, void*); - - /* OpenMP 5.0 Memory Management */ - typedef uintptr_t omp_uintptr_t; - - typedef enum { - omp_atk_sync_hint = 1, - omp_atk_alignment = 2, - omp_atk_access = 3, - omp_atk_pool_size = 4, - omp_atk_fallback = 5, - omp_atk_fb_data = 6, - omp_atk_pinned = 7, - omp_atk_partition = 8 - } omp_alloctrait_key_t; - - typedef enum { - omp_atv_false = 0, - omp_atv_true = 1, - omp_atv_contended = 3, - omp_atv_uncontended = 4, - omp_atv_serialized = 5, - omp_atv_sequential = omp_atv_serialized, // (deprecated) - omp_atv_private = 6, - omp_atv_all = 7, - omp_atv_thread = 8, - omp_atv_pteam = 9, - omp_atv_cgroup = 10, - omp_atv_default_mem_fb = 11, - omp_atv_null_fb = 12, - omp_atv_abort_fb = 13, - omp_atv_allocator_fb = 14, - omp_atv_environment = 15, - omp_atv_nearest = 16, - omp_atv_blocked = 17, - omp_atv_interleaved = 18 - } omp_alloctrait_value_t; - #define omp_atv_default ((omp_uintptr_t)-1) - - typedef struct { - omp_alloctrait_key_t key; - omp_uintptr_t value; - } omp_alloctrait_t; - -# if defined(_WIN32) - // On Windows cl and icl do not support 64-bit enum, let's use integer then. - typedef omp_uintptr_t omp_allocator_handle_t; - extern __KMP_IMP omp_allocator_handle_t const omp_null_allocator; - extern __KMP_IMP omp_allocator_handle_t const omp_default_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_large_cap_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_const_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_high_bw_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_low_lat_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_cgroup_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_pteam_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const omp_thread_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_host_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_shared_mem_alloc; - extern __KMP_IMP omp_allocator_handle_t const llvm_omp_target_device_mem_alloc; - - typedef omp_uintptr_t omp_memspace_handle_t; - extern __KMP_IMP omp_memspace_handle_t const omp_default_mem_space; - extern __KMP_IMP omp_memspace_handle_t const omp_large_cap_mem_space; - extern __KMP_IMP omp_memspace_handle_t const omp_const_mem_space; - extern __KMP_IMP omp_memspace_handle_t const omp_high_bw_mem_space; - extern __KMP_IMP omp_memspace_handle_t const omp_low_lat_mem_space; - extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_host_mem_space; - extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_shared_mem_space; - extern __KMP_IMP omp_memspace_handle_t const llvm_omp_target_device_mem_space; -# else -# if __cplusplus >= 201103 - typedef enum omp_allocator_handle_t : omp_uintptr_t -# else - typedef enum omp_allocator_handle_t -# endif - { - omp_null_allocator = 0, - omp_default_mem_alloc = 1, - omp_large_cap_mem_alloc = 2, - omp_const_mem_alloc = 3, - omp_high_bw_mem_alloc = 4, - omp_low_lat_mem_alloc = 5, - omp_cgroup_mem_alloc = 6, - omp_pteam_mem_alloc = 7, - omp_thread_mem_alloc = 8, - llvm_omp_target_host_mem_alloc = 100, - llvm_omp_target_shared_mem_alloc = 101, - llvm_omp_target_device_mem_alloc = 102, - KMP_ALLOCATOR_MAX_HANDLE = UINTPTR_MAX - } omp_allocator_handle_t; -# if __cplusplus >= 201103 - typedef enum omp_memspace_handle_t : omp_uintptr_t -# else - typedef enum omp_memspace_handle_t -# endif - { - omp_default_mem_space = 0, - omp_large_cap_mem_space = 1, - omp_const_mem_space = 2, - omp_high_bw_mem_space = 3, - omp_low_lat_mem_space = 4, - llvm_omp_target_host_mem_space = 100, - llvm_omp_target_shared_mem_space = 101, - llvm_omp_target_device_mem_space = 102, - KMP_MEMSPACE_MAX_HANDLE = UINTPTR_MAX - } omp_memspace_handle_t; -# endif - extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_init_allocator(omp_memspace_handle_t m, - int ntraits, omp_alloctrait_t traits[]); - extern void __KAI_KMPC_CONVENTION omp_destroy_allocator(omp_allocator_handle_t allocator); - - extern void __KAI_KMPC_CONVENTION omp_set_default_allocator(omp_allocator_handle_t a); - extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_get_default_allocator(void); -# ifdef __cplusplus - extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a = omp_null_allocator); - extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, size_t size, - omp_allocator_handle_t a = omp_null_allocator); - extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, - omp_allocator_handle_t a = omp_null_allocator); - extern void *__KAI_KMPC_CONVENTION omp_aligned_calloc(size_t align, size_t nmemb, size_t size, - omp_allocator_handle_t a = omp_null_allocator); - extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, - omp_allocator_handle_t allocator = omp_null_allocator, - omp_allocator_handle_t free_allocator = omp_null_allocator); - extern void __KAI_KMPC_CONVENTION omp_free(void * ptr, omp_allocator_handle_t a = omp_null_allocator); -# else - extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a); - extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, size_t size, - omp_allocator_handle_t a); - extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a); - extern void *__KAI_KMPC_CONVENTION omp_aligned_calloc(size_t align, size_t nmemb, size_t size, - omp_allocator_handle_t a); - extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator, - omp_allocator_handle_t free_allocator); - extern void __KAI_KMPC_CONVENTION omp_free(void *ptr, omp_allocator_handle_t a); -# endif - - /* OpenMP 5.0 Affinity Format */ - extern void __KAI_KMPC_CONVENTION omp_set_affinity_format(char const *); - extern size_t __KAI_KMPC_CONVENTION omp_get_affinity_format(char *, size_t); - extern void __KAI_KMPC_CONVENTION omp_display_affinity(char const *); - extern size_t __KAI_KMPC_CONVENTION omp_capture_affinity(char *, size_t, char const *); - - /* OpenMP 5.0 events */ -# if defined(_WIN32) - // On Windows cl and icl do not support 64-bit enum, let's use integer then. - typedef omp_uintptr_t omp_event_handle_t; -# else - typedef enum omp_event_handle_t { KMP_EVENT_MAX_HANDLE = UINTPTR_MAX } omp_event_handle_t; -# endif - extern void __KAI_KMPC_CONVENTION omp_fulfill_event ( omp_event_handle_t event ); - - /* OpenMP 5.0 Pause Resources */ - typedef enum omp_pause_resource_t { - omp_pause_resume = 0, - omp_pause_soft = 1, - omp_pause_hard = 2 - } omp_pause_resource_t; - extern int __KAI_KMPC_CONVENTION omp_pause_resource(omp_pause_resource_t, int); - extern int __KAI_KMPC_CONVENTION omp_pause_resource_all(omp_pause_resource_t); - - extern int __KAI_KMPC_CONVENTION omp_get_supported_active_levels(void); - - /* OpenMP 5.1 */ - extern void __KAI_KMPC_CONVENTION omp_set_num_teams(int num_teams); - extern int __KAI_KMPC_CONVENTION omp_get_max_teams(void); - extern void __KAI_KMPC_CONVENTION omp_set_teams_thread_limit(int limit); - extern int __KAI_KMPC_CONVENTION omp_get_teams_thread_limit(void); - - /* OpenMP 5.1 Display Environment */ - extern void omp_display_env(int verbose); - -# if defined(_OPENMP) && _OPENMP >= 201811 - #pragma omp begin declare variant match(device={kind(host)}) - static inline int omp_is_initial_device(void) { return 1; } - #pragma omp end declare variant - #pragma omp begin declare variant match(device={kind(nohost)}) - static inline int omp_is_initial_device(void) { return 0; } - #pragma omp end declare variant -# endif - - /* OpenMP 5.2 */ - extern int __KAI_KMPC_CONVENTION omp_in_explicit_task(void); - - /* LLVM Extensions */ - extern void *llvm_omp_target_dynamic_shared_alloc(void); - -# undef __KAI_KMPC_CONVENTION -# undef __KMP_IMP - - /* Warning: - The following typedefs are not standard, deprecated and will be removed in a future release. - */ - typedef int omp_int_t; - typedef double omp_wtime_t; - -# ifdef __cplusplus - } -# endif - -#endif /* __OMP_H */ diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt deleted file mode 100644 index 942142d..0000000 --- a/plugin/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(LLVM_LINK_COMPONENTS support) - -add_clang_library(clangTidyPluginModule - SHARED - - FooCheck.cpp - PluginTidyModule.cpp - - LINK_LIBS - clangAST - clangASTMatchers - clangBasic - clangLex - clangTidy - clangTidyUtils - clangTooling - ) diff --git a/plugin/FooCheck.cpp b/plugin/FooCheck.cpp deleted file mode 100644 index cd8cc9d..0000000 --- a/plugin/FooCheck.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===--- FooCheck.cpp - clang-tidy-----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "FooCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace plugin { - -void FooCheck::registerMatchers(MatchFinder *Finder) { - // FIXME: Add matchers. - Finder->addMatcher(functionDecl().bind("x"), this); -} - -void FooCheck::check(const MatchFinder::MatchResult &Result) { - // FIXME: Add callback implementation. - const auto *MatchedDecl = Result.Nodes.getNodeAs("x"); - diag(MatchedDecl->getLocation(), "you should not use functions") - << MatchedDecl; -} - -} // namespace plugin -} // namespace tidy -} // namespace clang diff --git a/plugin/FooCheck.h b/plugin/FooCheck.h deleted file mode 100644 index 5d843bb..0000000 --- a/plugin/FooCheck.h +++ /dev/null @@ -1,36 +0,0 @@ -//===--- FooCheck.h - clang-tidy---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PLUGIN_FOO_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PLUGIN_FOO_H - -#include "clang-tidy/ClangTidy.h" -#include "clang-tidy/ClangTidyCheck.h" - -namespace clang { -namespace tidy { -namespace plugin { - -/// FIXME: Write a short description. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/plugin-Foo.html -class FooCheck : public ClangTidyCheck { -public: - FooCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; -}; - -} // namespace plugin -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PLUGIN_FOO_H diff --git a/plugin/PluginTidyModule.cpp b/plugin/PluginTidyModule.cpp deleted file mode 100644 index c8f4b10..0000000 --- a/plugin/PluginTidyModule.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//===--- PluginTidyModule.cpp - clang-tidy ----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang-tidy/ClangTidy.h" -#include "clang-tidy/ClangTidyModule.h" -#include "clang-tidy/ClangTidyModuleRegistry.h" -#include "FooCheck.h" -#include - -namespace clang { -namespace tidy { -namespace plugin { - -class PluginModule : public ClangTidyModule { -public: - void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { - std::cerr << "side effect \n"; - CheckFactories.registerCheck( - "plugin-Foo"); - } -}; - -} // namespace plugin - -// Register the PluginTidyModule using this statically initialized variable. -static ClangTidyModuleRegistry::Add -X("pluginO2-module", "Adds Plugin specific checks"); - -// This anchor is used to force the linker to link in the generated object file -// and thus register the PluginModule. -volatile int PluginModuleAnchorSource = 0; - -} // namespace tidy -} // namespace clang - - -// A function to execute upon load of shared library -//__attribute__((constructor)) -static int huhuhuhuhu() { - static clang::tidy::plugin::PluginModule module; - return clang::tidy::PluginModuleAnchorSource; -} diff --git a/reporting/CMakeLists.txt b/reporting/CMakeLists.txt deleted file mode 100644 index e41a910..0000000 --- a/reporting/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(LLVM_LINK_COMPONENTS support) - -add_clang_library(clangTidyReportingModule - ReportingTidyModule.cpp - InterfaceLister.cpp - VirtFuncLister.cpp - - LINK_LIBS - clangAST - clangASTMatchers - clangBasic - clangLex - clangTidy - clangTidyUtils - clangTooling - ) diff --git a/reporting/InterfaceLister.cpp b/reporting/InterfaceLister.cpp deleted file mode 100644 index cfe0638..0000000 --- a/reporting/InterfaceLister.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===--- InterfaceLister.cpp - clang-tidy---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "InterfaceLister.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace reporting { - -void InterfaceLister::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(cxxMemberCallExpr().bind("member"), this); -} - -void InterfaceLister::check(const MatchFinder::MatchResult &Result) { - const auto *MatchedCallExpr = - Result.Nodes.getNodeAs("member"); - if (MatchedCallExpr) { - if (std::strcmp(MatchedCallExpr->getRecordDecl() - ->getDeclName() - .getAsString() - .c_str(), - ClassName.c_str()) != 0) - return; - - std::string sourceInfo(MatchedCallExpr->getExprLoc().printToString( - *Result.SourceManager)); - std::cerr << sourceInfo << " ; " << ClassName << " : " - << MatchedCallExpr->getMethodDecl()->getQualifiedNameAsString() - << "\n"; - } -} - -} // namespace reporting -} // namespace tidy -} // namespace clang diff --git a/reporting/InterfaceLister.h b/reporting/InterfaceLister.h deleted file mode 100644 index 5a4c91a..0000000 --- a/reporting/InterfaceLister.h +++ /dev/null @@ -1,43 +0,0 @@ -//===--- MemberNamesCheck.h - clang-tidy-------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INTERFACELISTER_NAMES_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INTERFACELISTER_NAMES_H - -#include "clang-tidy/ClangTidy.h" -#include "clang-tidy/ClangTidyCheck.h" - -namespace clang { -namespace tidy { -namespace reporting { - -/// A simple tool/check that given a ClassName reports the interfaces -/// used in the code base -/// -class InterfaceLister : public ClangTidyCheck { -private: - const std::string ClassName; // the class name for which we want to find - // used interfaces -public: - InterfaceLister(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), ClassName(Options.get("ClassName", "")) {} - - void storeOptions(ClangTidyOptions::OptionMap &Opts) override { - Options.store(Opts, "ClassName", ClassName); - } - - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; -}; - -} // namespace reporting -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INTERFACELISTER_NAMES_H diff --git a/reporting/ReportingTidyModule.cpp b/reporting/ReportingTidyModule.cpp deleted file mode 100644 index 3674a70..0000000 --- a/reporting/ReportingTidyModule.cpp +++ /dev/null @@ -1,40 +0,0 @@ -//===--- AliceO2TidyModule.cpp - clang-tidy ----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang-tidy/ClangTidy.h" -#include "clang-tidy/ClangTidyModule.h" -#include "clang-tidy/ClangTidyModuleRegistry.h" -#include "InterfaceLister.h" -#include "VirtFuncLister.h" - -namespace clang { -namespace tidy { -namespace reporting { - -class ReportingModule : public ClangTidyModule { -public: - void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { - CheckFactories.registerCheck("Reporting-interfaces-used"); - - CheckFactories.registerCheck("Reporting-unusedvirtfunc"); - } -}; - -} // namespace Reporting - -// Register the ReportingTidyModule using this statically initialized variable. -static ClangTidyModuleRegistry::Add -X("Reporting-module", "Adds Reporting tools (for simple analytics)"); - -// This anchor is used to force the linker to link in the generated object file -// and thus register the ReportingModule. -volatile int ReportingModuleAnchorSource = 0; - -} // namespace tidy -} // namespace clang diff --git a/reporting/VirtFuncLister.cpp b/reporting/VirtFuncLister.cpp deleted file mode 100644 index 9fdb102..0000000 --- a/reporting/VirtFuncLister.cpp +++ /dev/null @@ -1,85 +0,0 @@ -//===--- VirtFuncLister.cpp - clang-tidy---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "VirtFuncLister.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace reporting { - -void VirtFuncLister::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(cxxMethodDecl().bind("method"), this); -} - -void VirtFuncLister::check(const MatchFinder::MatchResult &Result) { - const auto &SM = *Result.SourceManager; - const auto *MatchedDecl = - Result.Nodes.getNodeAs("method"); - if (MatchedDecl) { - DeclarationNameInfo name_info = MatchedDecl->getNameInfo(); - std::string func_name = name_info.getAsString(); - - bool isvirtual = MatchedDecl->isVirtual(); - - llvm::errs() << "MEMBER FUNCTION DECL " << func_name << "("<isVirtualAsWritten() << " is virtual " - << isvirtual << "\n"; - - // get class declaration of this member function - // auto record = MatchedDecl->getCanonicalDecl()->getParent(); - - // we need to get source location the base node - // as well as overriding node - if (isvirtual) { - auto iter = MatchedDecl->begin_overridden_methods(); - auto enditer = MatchedDecl->end_overridden_methods(); - - if (iter == enditer) { - SourceLocation loc = MatchedDecl->getBeginLoc();//getLocation(); - loc.dump(SM); - llvm::errs() << "VIRTUAL-START-DECLARATION \n"; - } else { - // otherwise find the base this is referring to - decltype(iter) lastiter = iter; - while (iter != enditer) { - lastiter = iter; - // counter number of paths up; if there is more than one - // we have to give up for the moment - int counter = 0; - decltype(iter) countiter = iter; - for (; countiter != enditer; ++countiter) { - counter++; - } - if (counter > 1) { - llvm::errs() << " OVERRIDING MULTIPLE FUNCTIONS NOT TREATED YET\n"; - return; - } - enditer = (*iter)->end_overridden_methods(); - iter = (*iter)->begin_overridden_methods(); - } - SourceLocation loc = (*lastiter)->getBeginLoc();//getLocation(); - loc.dump(SM); - llvm::errs() << " OVERRIDEN-AT "; - loc = MatchedDecl->getBeginLoc();//getLocation(); - loc.dump(SM); - llvm::errs() << "\n"; - } - } - } -} - -} // namespace reporting -} // namespace tidy -} // namespace clang diff --git a/reporting/VirtFuncLister.h b/reporting/VirtFuncLister.h deleted file mode 100644 index d8ccf21..0000000 --- a/reporting/VirtFuncLister.h +++ /dev/null @@ -1,36 +0,0 @@ -//===--- MemberNamesCheck.h - clang-tidy-------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_VIRTFUNCLISTER_NAMES_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_VIRTFUNCLISTER_NAMES_H - -#include "clang-tidy/ClangTidy.h" -#include "clang-tidy/ClangTidyCheck.h" - -namespace clang { -namespace tidy { -namespace reporting { - -/// A simple tool/check that given a ClassName reports the interfaces -/// used in the code base -/// -class VirtFuncLister : public ClangTidyCheck { -public: - VirtFuncLister(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; -}; - -} // namespace reporting -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_VIRTFUNCLISTER_NAMES_H diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt index 5d9de7e..ae6622f 100644 --- a/tool/CMakeLists.txt +++ b/tool/CMakeLists.txt @@ -1,71 +1 @@ -set(LLVM_LINK_COMPONENTS - AllTargetsAsmParsers - AllTargetsDescs - AllTargetsInfos - support - ) - -add_clang_executable(O2codecheck - ClangTidyMain.cpp - ) - -target_link_libraries(O2codecheck - PRIVATE - clangAST - clangASTMatchers - clangBasic - clangTidy - - # link our own checks - clangTidyAliceO2Module - clangTidyReportingModule - - # include checkers available from main clang-tidy - clangTidyAlteraModule - clangTidyAndroidModule - clangTidyAbseilModule - clangTidyBoostModule - clangTidyBugproneModule - clangTidyCERTModule - clangTidyConcurrencyModule - clangTidyCppCoreGuidelinesModule - clangTidyDarwinModule - clangTidyFuchsiaModule - clangTidyGoogleModule - clangTidyHICPPModule - clangTidyLinuxKernelModule - clangTidyLLVMModule - clangTidyLLVMLibcModule - clangTidyMiscModule - clangTidyModernizeModule - clangTidyMPIModule - clangTidyObjCModule - clangTidyOpenMPModule - clangTidyPerformanceModule - clangTidyPortabilityModule - clangTidyReadabilityModule - clangTidyZirconModule - clangTooling - clangToolingCore - ) - -install(TARGETS O2codecheck - RUNTIME DESTINATION bin) - -#install(PROGRAMS clang-tidy-diff.py DESTINATION share/clang) install(PROGRAMS run_O2CodeChecker.py DESTINATION bin) - -# we need to install the builtin headers in a path which is searched by the tool -# FIXME: a soft link would be better -string(REPLACE "." ";" LLVM_PACKAGE_VERSION_LIST ${LLVM_PACKAGE_VERSION}) -list(GET LLVM_PACKAGE_VERSION_LIST 0 LLVM_PACKAGE_VERSION_MAJOR) -install(DIRECTORY ${LLVM_LIBRARY_DIR}/clang/${LLVM_PACKAGE_VERSION_MAJOR}/include DESTINATION lib/clang/${LLVM_PACKAGE_VERSION_MAJOR}) - -IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # On MacOS we need to do the same with C++ headers since they are in a non-standard location - # (alternative would be to set the CPATH environment variable) - INSTALL(CODE "execute_process(COMMAND mkdir ${CMAKE_INSTALL_PREFIX}/include)") - INSTALL(CODE "execute_process(COMMAND ln -sf \ - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++ \ - ${CMAKE_INSTALL_PREFIX}/include/c++)") -ENDIF() diff --git a/tool/ClangTidyMain.cpp b/tool/ClangTidyMain.cpp deleted file mode 100644 index 48066ef..0000000 --- a/tool/ClangTidyMain.cpp +++ /dev/null @@ -1,671 +0,0 @@ -//===--- tools/extra/clang-tidy/ClangTidyMain.cpp - Clang tidy tool -------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -/// -/// \file This file implements a clang-tidy tool. -/// -/// This tool uses the Clang Tooling infrastructure, see -/// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html -/// for details on setting it up with LLVM source tree. -/// -//===----------------------------------------------------------------------===// - -#include "ClangTidyMain.h" -#include "clang-tidy/ClangTidy.h" -//#include "clang-tidy/ClangTidyForceLinker.h" -#include "../GlobList.h" -#include "clang/Tooling/CommonOptionsParser.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/Support/InitLLVM.h" -#include "llvm/Support/PluginLoader.h" -#include "llvm/Support/Process.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/WithColor.h" - -using namespace clang::tooling; -using namespace llvm; - -static cl::OptionCategory ClangTidyCategory("clang-tidy options"); - -static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); -static cl::extrahelp ClangTidyHelp(R"( -Configuration files: - clang-tidy attempts to read configuration for each source file from a - .clang-tidy file located in the closest parent directory of the source - file. If InheritParentConfig is true in a config file, the configuration file - in the parent directory (if any exists) will be taken and current config file - will be applied on top of the parent one. If any configuration options have - a corresponding command-line option, command-line option takes precedence. - The effective configuration can be inspected using -dump-config: - - $ clang-tidy -dump-config - --- - Checks: '-*,some-check' - WarningsAsErrors: '' - HeaderFilterRegex: '' - FormatStyle: none - InheritParentConfig: true - User: user - CheckOptions: - some-check.SomeOption: 'some value' - ... - -)"); - -const char DefaultChecks[] = // Enable these checks by default: - "clang-diagnostic-*," // * compiler diagnostics - "clang-analyzer-*"; // * Static Analyzer checks - -static cl::opt Checks("checks", cl::desc(R"( -Comma-separated list of globs with optional '-' -prefix. Globs are processed in order of -appearance in the list. Globs without '-' -prefix add checks with matching names to the -set, globs with the '-' prefix remove checks -with matching names from the set of enabled -checks. This option's value is appended to the -value of the 'Checks' option in .clang-tidy -file, if any. -)"), - cl::init(""), cl::cat(ClangTidyCategory)); - -static cl::opt WarningsAsErrors("warnings-as-errors", cl::desc(R"( -Upgrades warnings to errors. Same format as -'-checks'. -This option's value is appended to the value of -the 'WarningsAsErrors' option in .clang-tidy -file, if any. -)"), - cl::init(""), - cl::cat(ClangTidyCategory)); - -static cl::opt HeaderFilter("header-filter", cl::desc(R"( -Regular expression matching the names of the -headers to output diagnostics from. Diagnostics -from the main file of each translation unit are -always displayed. -Can be used together with -line-filter. -This option overrides the 'HeaderFilterRegex' -option in .clang-tidy file, if any. -)"), - cl::init(""), - cl::cat(ClangTidyCategory)); - -static cl::opt - SystemHeaders("system-headers", - cl::desc("Display the errors from system headers."), - cl::init(false), cl::cat(ClangTidyCategory)); -static cl::opt LineFilter("line-filter", cl::desc(R"( -List of files with line ranges to filter the -warnings. Can be used together with --header-filter. The format of the list is a -JSON array of objects: - [ - {"name":"file1.cpp","lines":[[1,3],[5,7]]}, - {"name":"file2.h"} - ] -)"), - cl::init(""), - cl::cat(ClangTidyCategory)); - -static cl::opt Fix("fix", cl::desc(R"( -Apply suggested fixes. Without -fix-errors -clang-tidy will bail out if any compilation -errors were found. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt FixErrors("fix-errors", cl::desc(R"( -Apply suggested fixes even if compilation -errors were found. If compiler errors have -attached fix-its, clang-tidy will apply them as -well. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt FixNotes("fix-notes", cl::desc(R"( -If a warning has no fix, but a single fix can -be found through an associated diagnostic note, -apply the fix. -Specifying this flag will implicitly enable the -'--fix' flag. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt FormatStyle("format-style", cl::desc(R"( -Style for formatting code around applied fixes: - - 'none' (default) turns off formatting - - 'file' (literally 'file', not a placeholder) - uses .clang-format file in the closest parent - directory - - '{ }' specifies options inline, e.g. - -format-style='{BasedOnStyle: llvm, IndentWidth: 8}' - - 'llvm', 'google', 'webkit', 'mozilla' -See clang-format documentation for the up-to-date -information about formatting styles and options. -This option overrides the 'FormatStyle` option in -.clang-tidy file, if any. -)"), - cl::init("none"), - cl::cat(ClangTidyCategory)); - -static cl::opt ListChecks("list-checks", cl::desc(R"( -List all enabled checks and exit. Use with --checks=* to list all available checks. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt ExplainConfig("explain-config", cl::desc(R"( -For each enabled check explains, where it is -enabled, i.e. in clang-tidy binary, command -line or a specific configuration file. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt Config("config", cl::desc(R"( -Specifies a configuration in YAML/JSON format: - -config="{Checks: '*', - CheckOptions: {x: y}}" -When the value is empty, clang-tidy will -attempt to find a file named .clang-tidy for -each source file in its parent directories. -)"), - cl::init(""), cl::cat(ClangTidyCategory)); - -static cl::opt ConfigFile("config-file", cl::desc(R"( -Specify the path of .clang-tidy or custom config file: - e.g. --config-file=/some/path/myTidyConfigFile -This option internally works exactly the same way as - --config option after reading specified config file. -Use either --config-file or --config, not both. -)"), - cl::init(""), - cl::cat(ClangTidyCategory)); - -static cl::opt DumpConfig("dump-config", cl::desc(R"( -Dumps configuration in the YAML format to -stdout. This option can be used along with a -file name (and '--' if the file is outside of a -project with configured compilation database). -The configuration used for this file will be -printed. -Use along with -checks=* to include -configuration of all checks. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt EnableCheckProfile("enable-check-profile", cl::desc(R"( -Enable per-check timing profiles, and print a -report to stderr. -)"), - cl::init(false), - cl::cat(ClangTidyCategory)); - -static cl::opt StoreCheckProfile("store-check-profile", - cl::desc(R"( -By default reports are printed in tabulated -format to stderr. When this option is passed, -these per-TU profiles are instead stored as JSON. -)"), - cl::value_desc("prefix"), - cl::cat(ClangTidyCategory)); - -/// This option allows enabling the experimental alpha checkers from the static -/// analyzer. This option is set to false and not visible in help, because it is -/// highly not recommended for users. -static cl::opt - AllowEnablingAnalyzerAlphaCheckers("allow-enabling-analyzer-alpha-checkers", - cl::init(false), cl::Hidden, - cl::cat(ClangTidyCategory)); - -static cl::opt ExportFixes("export-fixes", cl::desc(R"( -YAML file to store suggested fixes in. The -stored fixes can be applied to the input source -code with clang-apply-replacements. -)"), - cl::value_desc("filename"), - cl::cat(ClangTidyCategory)); - -static cl::opt Quiet("quiet", cl::desc(R"( -Run clang-tidy in quiet mode. This suppresses -printing statistics about ignored warnings and -warnings treated as errors if the respective -options are specified. -)"), - cl::init(false), - cl::cat(ClangTidyCategory)); - -static cl::opt VfsOverlay("vfsoverlay", cl::desc(R"( -Overlay the virtual filesystem described by file -over the real file system. -)"), - cl::value_desc("filename"), - cl::cat(ClangTidyCategory)); - -static cl::opt UseColor("use-color", cl::desc(R"( -Use colors in diagnostics. If not set, colors -will be used if the terminal connected to -standard output supports colors. -This option overrides the 'UseColor' option in -.clang-tidy file, if any. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -static cl::opt VerifyConfig("verify-config", cl::desc(R"( -Check the config files to ensure each check and -option is recognized. -)"), - cl::init(false), cl::cat(ClangTidyCategory)); - -namespace clang { -namespace tidy { - -static void printStats(const ClangTidyStats &Stats) { - if (Stats.errorsIgnored()) { - llvm::errs() << "Suppressed " << Stats.errorsIgnored() << " warnings ("; - StringRef Separator = ""; - if (Stats.ErrorsIgnoredNonUserCode) { - llvm::errs() << Stats.ErrorsIgnoredNonUserCode << " in non-user code"; - Separator = ", "; - } - if (Stats.ErrorsIgnoredLineFilter) { - llvm::errs() << Separator << Stats.ErrorsIgnoredLineFilter - << " due to line filter"; - Separator = ", "; - } - if (Stats.ErrorsIgnoredNOLINT) { - llvm::errs() << Separator << Stats.ErrorsIgnoredNOLINT << " NOLINT"; - Separator = ", "; - } - if (Stats.ErrorsIgnoredCheckFilter) - llvm::errs() << Separator << Stats.ErrorsIgnoredCheckFilter - << " with check filters"; - llvm::errs() << ").\n"; - if (Stats.ErrorsIgnoredNonUserCode) - llvm::errs() << "Use -header-filter=.* to display errors from all " - "non-system headers. Use -system-headers to display " - "errors from system headers as well.\n"; - } -} - -static std::unique_ptr createOptionsProvider( - llvm::IntrusiveRefCntPtr FS) { - ClangTidyGlobalOptions GlobalOptions; - if (std::error_code Err = parseLineFilter(LineFilter, GlobalOptions)) { - llvm::errs() << "Invalid LineFilter: " << Err.message() << "\n\nUsage:\n"; - llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); - return nullptr; - } - - ClangTidyOptions DefaultOptions; - DefaultOptions.Checks = DefaultChecks; - DefaultOptions.WarningsAsErrors = ""; - DefaultOptions.HeaderFilterRegex = HeaderFilter; - DefaultOptions.SystemHeaders = SystemHeaders; - DefaultOptions.FormatStyle = FormatStyle; - DefaultOptions.User = llvm::sys::Process::GetEnv("USER"); - // USERNAME is used on Windows. - if (!DefaultOptions.User) - DefaultOptions.User = llvm::sys::Process::GetEnv("USERNAME"); - - ClangTidyOptions OverrideOptions; - if (Checks.getNumOccurrences() > 0) - OverrideOptions.Checks = Checks; - if (WarningsAsErrors.getNumOccurrences() > 0) - OverrideOptions.WarningsAsErrors = WarningsAsErrors; - if (HeaderFilter.getNumOccurrences() > 0) - OverrideOptions.HeaderFilterRegex = HeaderFilter; - if (SystemHeaders.getNumOccurrences() > 0) - OverrideOptions.SystemHeaders = SystemHeaders; - if (FormatStyle.getNumOccurrences() > 0) - OverrideOptions.FormatStyle = FormatStyle; - if (UseColor.getNumOccurrences() > 0) - OverrideOptions.UseColor = UseColor; - - auto LoadConfig = - [&](StringRef Configuration, - StringRef Source) -> std::unique_ptr { - llvm::ErrorOr ParsedConfig = - parseConfiguration(MemoryBufferRef(Configuration, Source)); - if (ParsedConfig) - return std::make_unique( - std::move(GlobalOptions), - ClangTidyOptions::getDefaults().merge(DefaultOptions, 0), - std::move(*ParsedConfig), std::move(OverrideOptions), std::move(FS)); - llvm::errs() << "Error: invalid configuration specified.\n" - << ParsedConfig.getError().message() << "\n"; - return nullptr; - }; - - if (ConfigFile.getNumOccurrences() > 0) { - if (Config.getNumOccurrences() > 0) { - llvm::errs() << "Error: --config-file and --config are " - "mutually exclusive. Specify only one.\n"; - return nullptr; - } - - llvm::ErrorOr> Text = - llvm::MemoryBuffer::getFile(ConfigFile); - if (std::error_code EC = Text.getError()) { - llvm::errs() << "Error: can't read config-file '" << ConfigFile - << "': " << EC.message() << "\n"; - return nullptr; - } - - return LoadConfig((*Text)->getBuffer(), ConfigFile); - } - - if (Config.getNumOccurrences() > 0) - return LoadConfig(Config, ""); - - return std::make_unique( - std::move(GlobalOptions), std::move(DefaultOptions), - std::move(OverrideOptions), std::move(FS)); -} - -llvm::IntrusiveRefCntPtr -getVfsFromFile(const std::string &OverlayFile, - llvm::IntrusiveRefCntPtr BaseFS) { - llvm::ErrorOr> Buffer = - BaseFS->getBufferForFile(OverlayFile); - if (!Buffer) { - llvm::errs() << "Can't load virtual filesystem overlay file '" - << OverlayFile << "': " << Buffer.getError().message() - << ".\n"; - return nullptr; - } - - IntrusiveRefCntPtr FS = vfs::getVFSFromYAML( - std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile); - if (!FS) { - llvm::errs() << "Error: invalid virtual filesystem overlay file '" - << OverlayFile << "'.\n"; - return nullptr; - } - return FS; -} - -static StringRef closest(StringRef Value, const StringSet<> &Allowed) { - unsigned MaxEdit = 5U; - StringRef Closest; - for (auto Item : Allowed.keys()) { - unsigned Cur = Value.edit_distance_insensitive(Item, true, MaxEdit); - if (Cur < MaxEdit) { - Closest = Item; - MaxEdit = Cur; - } - } - return Closest; -} - -static constexpr StringLiteral VerifyConfigWarningEnd = " [-verify-config]\n"; - -static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob, - StringRef Source) { - llvm::StringRef Cur, Rest; - bool AnyInvalid = false; - for (std::tie(Cur, Rest) = CheckGlob.split(','); - !(Cur.empty() && Rest.empty()); std::tie(Cur, Rest) = Rest.split(',')) { - Cur = Cur.trim(); - if (Cur.empty()) - continue; - Cur.consume_front("-"); - if (Cur.starts_with("clang-diagnostic")) - continue; - if (Cur.contains('*')) { - SmallString<128> RegexText("^"); - StringRef MetaChars("()^$|*+?.[]\\{}"); - for (char C : Cur) { - if (C == '*') - RegexText.push_back('.'); - else if (MetaChars.contains(C)) - RegexText.push_back('\\'); - RegexText.push_back(C); - } - RegexText.push_back('$'); - llvm::Regex Glob(RegexText); - std::string Error; - if (!Glob.isValid(Error)) { - AnyInvalid = true; - llvm::WithColor::error(llvm::errs(), Source) - << "building check glob '" << Cur << "' " << Error << "'\n"; - continue; - } - if (llvm::none_of(AllChecks.keys(), - [&Glob](StringRef S) { return Glob.match(S); })) { - AnyInvalid = true; - llvm::WithColor::warning(llvm::errs(), Source) - << "check glob '" << Cur << "' doesn't match any known check" - << VerifyConfigWarningEnd; - } - } else { - if (AllChecks.contains(Cur)) - continue; - AnyInvalid = true; - llvm::raw_ostream &Output = llvm::WithColor::warning(llvm::errs(), Source) - << "unknown check '" << Cur << '\''; - llvm::StringRef Closest = closest(Cur, AllChecks); - if (!Closest.empty()) - Output << "; did you mean '" << Closest << '\''; - Output << VerifyConfigWarningEnd; - } - } - return AnyInvalid; -} - -int clangTidyMain(int argc, const char **argv) { - llvm::InitLLVM X(argc, argv); - - // Enable help for -load option, if plugins are enabled. - if (cl::Option *LoadOpt = cl::getRegisteredOptions().lookup("load")) - LoadOpt->addCategory(ClangTidyCategory); - - llvm::Expected OptionsParser = - CommonOptionsParser::create(argc, argv, ClangTidyCategory, - cl::ZeroOrMore); - if (!OptionsParser) { - llvm::WithColor::error() << llvm::toString(OptionsParser.takeError()); - return 1; - } - - llvm::IntrusiveRefCntPtr BaseFS( - new vfs::OverlayFileSystem(vfs::getRealFileSystem())); - - if (!VfsOverlay.empty()) { - IntrusiveRefCntPtr VfsFromFile = - getVfsFromFile(VfsOverlay, BaseFS); - if (!VfsFromFile) - return 1; - BaseFS->pushOverlay(std::move(VfsFromFile)); - } - - auto OwningOptionsProvider = createOptionsProvider(BaseFS); - auto *OptionsProvider = OwningOptionsProvider.get(); - if (!OptionsProvider) - return 1; - - auto MakeAbsolute = [](const std::string &Input) -> SmallString<256> { - if (Input.empty()) - return {}; - SmallString<256> AbsolutePath(Input); - if (std::error_code EC = llvm::sys::fs::make_absolute(AbsolutePath)) { - llvm::errs() << "Can't make absolute path from " << Input << ": " - << EC.message() << "\n"; - } - return AbsolutePath; - }; - - SmallString<256> ProfilePrefix = MakeAbsolute(StoreCheckProfile); - - StringRef FileName("dummy"); - auto PathList = OptionsParser->getSourcePathList(); - if (!PathList.empty()) { - FileName = PathList.front(); - } - - SmallString<256> FilePath = MakeAbsolute(std::string(FileName)); - - ClangTidyOptions EffectiveOptions = OptionsProvider->getOptions(FilePath); - std::vector EnabledChecks = - getCheckNames(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers); - - if (ExplainConfig) { - // FIXME: Show other ClangTidyOptions' fields, like ExtraArg. - std::vector - RawOptions = OptionsProvider->getRawOptions(FilePath); - for (const std::string &Check : EnabledChecks) { - for (auto It = RawOptions.rbegin(); It != RawOptions.rend(); ++It) { - if (It->first.Checks && GlobList(*It->first.Checks).contains(Check)) { - llvm::outs() << "'" << Check << "' is enabled in the " << It->second - << ".\n"; - break; - } - } - } - return 0; - } - - if (ListChecks) { - if (EnabledChecks.empty()) { - llvm::errs() << "No checks enabled.\n"; - return 1; - } - llvm::outs() << "Enabled checks:"; - for (const auto &CheckName : EnabledChecks) - llvm::outs() << "\n " << CheckName; - llvm::outs() << "\n\n"; - return 0; - } - - if (DumpConfig) { - EffectiveOptions.CheckOptions = - getCheckOptions(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers); - llvm::outs() << configurationAsText(ClangTidyOptions::getDefaults().merge( - EffectiveOptions, 0)) - << "\n"; - return 0; - } - - if (VerifyConfig) { - std::vector RawOptions = - OptionsProvider->getRawOptions(FileName); - NamesAndOptions Valid = - getAllChecksAndOptions(AllowEnablingAnalyzerAlphaCheckers); - bool AnyInvalid = false; - for (const std::pair &OptionWithSource : - RawOptions) { - const ClangTidyOptions &Opts = OptionWithSource.first; - if (Opts.Checks) - AnyInvalid |= - verifyChecks(Valid.Names, *Opts.Checks, OptionWithSource.second); - - for (auto Key : Opts.CheckOptions.keys()) { - if (Valid.Options.contains(Key)) - continue; - AnyInvalid = true; - auto &Output = - llvm::WithColor::warning(llvm::errs(), OptionWithSource.second) - << "unknown check option '" << Key << '\''; - llvm::StringRef Closest = closest(Key, Valid.Options); - if (!Closest.empty()) - Output << "; did you mean '" << Closest << '\''; - Output << VerifyConfigWarningEnd; - } - } - if (AnyInvalid) - return 1; - llvm::outs() << "No config errors detected.\n"; - return 0; - } - - if (EnabledChecks.empty()) { - llvm::errs() << "Error: no checks enabled.\n"; - llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); - return 1; - } - - if (PathList.empty()) { - llvm::errs() << "Error: no input files specified.\n"; - llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); - return 1; - } - - llvm::InitializeAllTargetInfos(); - llvm::InitializeAllTargetMCs(); - llvm::InitializeAllAsmParsers(); - - ClangTidyContext Context(std::move(OwningOptionsProvider), - AllowEnablingAnalyzerAlphaCheckers); - std::vector Errors = - runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS, - FixNotes, EnableCheckProfile, ProfilePrefix); - bool FoundErrors = llvm::any_of(Errors, [](const ClangTidyError &E) { - return E.DiagLevel == ClangTidyError::Error; - }); - - // --fix-errors and --fix-notes imply --fix. - FixBehaviour Behaviour = FixNotes ? FB_FixNotes - : (Fix || FixErrors) ? FB_Fix - : FB_NoFix; - - const bool DisableFixes = FoundErrors && !FixErrors; - - unsigned WErrorCount = 0; - - handleErrors(Errors, Context, DisableFixes ? FB_NoFix : Behaviour, - WErrorCount, BaseFS); - - if (!ExportFixes.empty() && !Errors.empty()) { - std::error_code EC; - llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::OF_None); - if (EC) { - llvm::errs() << "Error opening output file: " << EC.message() << '\n'; - return 1; - } - exportReplacements(FilePath.str(), Errors, OS); - } - - if (!Quiet) { - printStats(Context.getStats()); - if (DisableFixes && Behaviour != FB_NoFix) - llvm::errs() - << "Found compiler errors, but -fix-errors was not specified.\n" - "Fixes have NOT been applied.\n\n"; - } - - if (WErrorCount) { - if (!Quiet) { - StringRef Plural = WErrorCount == 1 ? "" : "s"; - llvm::errs() << WErrorCount << " warning" << Plural << " treated as error" - << Plural << "\n"; - } - return 1; - } - - if (FoundErrors) { - // TODO: Figure out when zero exit code should be used with -fix-errors: - // a. when a fix has been applied for an error - // b. when a fix has been applied for all errors - // c. some other condition. - // For now always returning zero when -fix-errors is used. - if (FixErrors) - return 0; - if (!Quiet) - llvm::errs() << "Found compiler error(s).\n"; - return 1; - } - - return 0; -} - -} // namespace tidy -} // namespace clang - -int main(int argc, const char **argv) { - return clang::tidy::clangTidyMain(argc, argv); -} diff --git a/tool/ClangTidyMain.h b/tool/ClangTidyMain.h deleted file mode 100644 index f87f84b..0000000 --- a/tool/ClangTidyMain.h +++ /dev/null @@ -1,23 +0,0 @@ -//===--- tools/extra/clang-tidy/ClangTidyMain.h - Clang tidy tool -------===// -// -// 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 -// -//===----------------------------------------------------------------------===// -/// -/// \file This file declares the main function for the clang-tidy tool. -/// -/// This tool uses the Clang Tooling infrastructure, see -/// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html -/// for details on setting it up with LLVM source tree. -/// -//===----------------------------------------------------------------------===// - -namespace clang { -namespace tidy { - -int clangTidyMain(int argc, const char **argv); - -} // namespace tidy -} // namespace clang diff --git a/tool/clang-tidy-diff.py b/tool/clang-tidy-diff.py deleted file mode 100755 index e3dcbe7..0000000 --- a/tool/clang-tidy-diff.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python -# -#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -r""" -ClangTidy Diff Checker -====================== - -This script reads input from a unified diff, runs clang-tidy on all changed -files and outputs clang-tidy warnings in changed lines only. This is useful to -detect clang-tidy regressions in the lines touched by a specific patch. -Example usage for git/svn users: - - git diff -U0 HEAD^ | clang-tidy-diff.py -p1 - svn diff --diff-cmd=diff -x-U0 | \ - clang-tidy-diff.py -fix -checks=-*,modernize-use-override - -""" - -import argparse -import json -import re -import subprocess -import sys - - -def main(): - parser = argparse.ArgumentParser(description= - 'Run clang-tidy against changed files, and ' - 'output diagnostics only for modified ' - 'lines.') - parser.add_argument('-clang-tidy-binary', metavar='PATH', - default='clang-tidy', - help='path to clang-tidy binary') - parser.add_argument('-p', metavar='NUM', default=0, - help='strip the smallest prefix containing P slashes') - parser.add_argument('-regex', metavar='PATTERN', default=None, - help='custom pattern selecting file paths to check ' - '(case sensitive, overrides -iregex)') - parser.add_argument('-iregex', metavar='PATTERN', default= - r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)', - help='custom pattern selecting file paths to check ' - '(case insensitive, overridden by -regex)') - - parser.add_argument('-fix', action='store_true', default=False, - help='apply suggested fixes') - parser.add_argument('-checks', - help='checks filter, when not specified, use clang-tidy ' - 'default', - default='') - clang_tidy_args = [] - argv = sys.argv[1:] - if '--' in argv: - clang_tidy_args.extend(argv[argv.index('--'):]) - argv = argv[:argv.index('--')] - - args = parser.parse_args(argv) - - # Extract changed lines for each file. - filename = None - lines_by_file = {} - for line in sys.stdin: - match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line) - if match: - filename = match.group(2) - if filename == None: - continue - - if args.regex is not None: - if not re.match('^%s$' % args.regex, filename): - continue - else: - if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE): - continue - - match = re.search('^@@.*\+(\d+)(,(\d+))?', line) - if match: - start_line = int(match.group(1)) - line_count = 1 - if match.group(3): - line_count = int(match.group(3)) - if line_count == 0: - continue - end_line = start_line + line_count - 1; - lines_by_file.setdefault(filename, []).append([start_line, end_line]) - - if len(lines_by_file) == 0: - print("No relevant changes found.") - sys.exit(0) - - line_filter_json = json.dumps( - [{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file], - separators = (',', ':')) - - quote = ""; - if sys.platform == 'win32': - line_filter_json=re.sub(r'"', r'"""', line_filter_json) - else: - quote = "'"; - - # Run clang-tidy on files containing changes. - command = [args.clang_tidy_binary] - command.append('-line-filter=' + quote + line_filter_json + quote) - if args.fix: - command.append('-fix') - if args.checks != '': - command.append('-checks=' + quote + args.checks + quote) - command.extend(lines_by_file.keys()) - command.extend(clang_tidy_args) - - sys.exit(subprocess.call(' '.join(command), shell=True)) - -if __name__ == '__main__': - main() From 0f50c77864f5c8bf115a17d1b5dff898d907efa9 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 15 Sep 2025 18:17:15 +0200 Subject: [PATCH 19/20] Handle case in which -extra-args has more than one extra arg. --- tool/run_O2CodeChecker.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tool/run_O2CodeChecker.py b/tool/run_O2CodeChecker.py index 97c50a2..8952871 100755 --- a/tool/run_O2CodeChecker.py +++ b/tool/run_O2CodeChecker.py @@ -77,8 +77,8 @@ def get_tidy_invocation(f, clang_tidy_binary, checks, warningsAsErrors, tmpdir, start.append('-warnings-as-errors=' + warningsAsErrors) if config: start.append('-config=' + config) - if extra_args is not None: - start.append(extra_args) + for extra in extra_args: + start.append(extra) if tmpdir is not None: start.append('-export-fixes') # Get a temporary file. We immediately close the handle so clang-tidy can @@ -152,6 +152,8 @@ def main(): args = parser.parse_args() db_path = 'compile_commands.json' + if args.extra_args: + args.extra_args = args.extra_args.split(" ") if args.build_path is not None: build_path = args.build_path From 44fea3623cb4acfc7b5e9e890c2eca604e4d51b1 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 5 Jan 2026 10:20:51 +0100 Subject: [PATCH 20/20] Make compatible to CMake 4 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ebacb4..a54379c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.4.3) +cmake_minimum_required(VERSION 3.16) enable_testing() project(O2CodeChecker)