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