Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -16,7 +16,10 @@ #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 { @@ -28,6 +31,55 @@ namespace tidy { +/// \brief Provides access to the \c 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 \c Context. + /// + /// Reads the option with the check-local name \p LocalName from the + /// \c CheckOptions. If the corresponding key is not present, returns + /// \p Default. + std::string get(StringRef LocalName, std::string Default) const; + + /// \brief Read a named option from the \c Context and parse it as an integral + /// type \c T. + /// + /// Reads the option with the check-local name \p LocalName from the + /// \c 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 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 + /// \c 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 \c ClangTidyCheck, write a subclass and overwrite some of the @@ -49,6 +101,18 @@ /// 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()); + } + virtual ~ClangTidyCheck() {} /// \brief Overwrite this to register \c PPCallbacks with \c Compiler. @@ -75,21 +139,24 @@ /// work in here. virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} - /// \brief The infrastructure sets the context to \p Ctx with this function. - void setContext(ClangTidyContext *Ctx) { Context = Ctx; } - /// \brief Add a diagnostic with the check's name. DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); - /// \brief Sets the check name. Intended to be used by the clang-tidy - /// framework. Can be called only once. - void setName(StringRef Name); + /// \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 \c 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; - ClangTidyContext *Context; std::string CheckName; + ClangTidyContext *Context; + +protected: + OptionsView Options; }; class ClangTidyCheckFactories; @@ -103,10 +170,13 @@ CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef File); /// \brief Get the list of enabled checks. - std::vector getCheckNames(GlobList &Filter); + std::vector getCheckNames(); + + /// \brief Get the union of options from all checks. + ClangTidyOptions::OptionMap getCheckOptions(); private: - typedef std::vector > CheckersList; + typedef std::vector> CheckersList; CheckersList getCheckersControlList(GlobList &Filter); ClangTidyContext &Context; @@ -117,6 +187,14 @@ /// filters are applied. std::vector getCheckNames(const ClangTidyOptions &Options); +/// \brief 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); + /// \brief Run a set of clang-tidy checks on a set of files. ClangTidyStats runClangTidy(std::unique_ptr OptionsProvider, Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -214,13 +214,11 @@ Context.setASTContext(&Compiler.getASTContext()); std::vector> Checks; - GlobList &Filter = Context.getChecksFilter(); - CheckFactories->createChecks(Filter, Checks); + CheckFactories->createChecks(&Context, Checks); std::unique_ptr Finder( new ast_matchers::MatchFinder); for (auto &Check : Checks) { - Check->setContext(&Context); Check->registerMatchers(&*Finder); Check->registerPPCallbacks(Compiler); } @@ -235,6 +233,7 @@ AnalyzerOptions->Config["cfg-temporary-dtors"] = Context.getOptions().AnalyzeTemporaryDtors ? "true" : "false"; + GlobList &Filter = Context.getChecksFilter(); AnalyzerOptions->CheckersControlList = getCheckersControlList(Filter); if (!AnalyzerOptions->CheckersControlList.empty()) { AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel; @@ -251,9 +250,9 @@ std::move(Consumers), std::move(Finder), std::move(Checks)); } -std::vector -ClangTidyASTConsumerFactory::getCheckNames(GlobList &Filter) { +std::vector ClangTidyASTConsumerFactory::getCheckNames() { std::vector CheckNames; + GlobList &Filter = Context.getChecksFilter(); for (const auto &CheckFactory : *CheckFactories) { if (Filter.contains(CheckFactory.first)) CheckNames.push_back(CheckFactory.first); @@ -266,6 +265,15 @@ return CheckNames; } +ClangTidyOptions::OptionMap ClangTidyASTConsumerFactory::getCheckOptions() { + ClangTidyOptions::OptionMap Options; + std::vector> Checks; + CheckFactories->createChecks(&Context, Checks); + for (const auto &Check : Checks) + Check->storeOptions(Options); + return Options; +} + ClangTidyASTConsumerFactory::CheckersList ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) { CheckersList List; @@ -307,9 +315,25 @@ check(Result); } -void ClangTidyCheck::setName(StringRef Name) { - assert(CheckName.empty()); - CheckName = Name.str(); +OptionsView::OptionsView(StringRef CheckName, + const ClangTidyOptions::OptionMap &CheckOptions) + : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {} + +std::string OptionsView::get(StringRef LocalName, std::string Default) const { + const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str()); + if (Iter != CheckOptions.end()) + return Iter->second; + return Default; +} + +void OptionsView::store(ClangTidyOptions::OptionMap &Options, + StringRef LocalName, StringRef Value) const { + Options[NamePrefix + LocalName.str()] = Value; +} + +void OptionsView::store(ClangTidyOptions::OptionMap &Options, + StringRef LocalName, int64_t Value) const { + store(Options, LocalName, llvm::itostr(Value)); } std::vector getCheckNames(const ClangTidyOptions &Options) { @@ -317,7 +341,15 @@ llvm::make_unique(ClangTidyGlobalOptions(), Options)); ClangTidyASTConsumerFactory Factory(Context); - return Factory.getCheckNames(Context.getChecksFilter()); + return Factory.getCheckNames(); +} + +ClangTidyOptions::OptionMap getCheckOptions(const ClangTidyOptions &Options) { + clang::tidy::ClangTidyContext Context( + llvm::make_unique(ClangTidyGlobalOptions(), + Options)); + ClangTidyASTConsumerFactory Factory(Context); + return Factory.getCheckOptions(); } ClangTidyStats Index: clang-tidy/ClangTidyModule.h =================================================================== --- clang-tidy/ClangTidyModule.h +++ clang-tidy/ClangTidyModule.h @@ -26,11 +26,13 @@ /// this object. class ClangTidyCheckFactories { public: + typedef std::function CheckFactory; + /// \brief Registers check \p Factory with name \p Name. /// /// For all checks that have default constructors, use \c registerCheck. - void registerCheckFactory(StringRef Name, - std::function Factory); + void registerCheckFactory(StringRef Name, CheckFactory Factory); /// \brief Registers the \c CheckType with the name \p Name. /// @@ -53,19 +55,21 @@ /// } /// }; /// \endcode - template - void registerCheck(StringRef Name) { - registerCheckFactory(Name, []() { return new CheckType(); }); + template void registerCheck(StringRef CheckName) { + registerCheckFactory(CheckName, + [](StringRef Name, ClangTidyContext *Context) { + return new CheckType(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(GlobList &Filter, + void createChecks(ClangTidyContext *Context, std::vector> &Checks); - typedef std::map> FactoryMap; + typedef std::map FactoryMap; FactoryMap::const_iterator begin() const { return Factories.begin(); } FactoryMap::const_iterator end() const { return Factories.end(); } bool empty() const { return Factories.empty(); } Index: clang-tidy/ClangTidyModule.cpp =================================================================== --- clang-tidy/ClangTidyModule.cpp +++ clang-tidy/ClangTidyModule.cpp @@ -16,19 +16,18 @@ namespace clang { namespace tidy { -void ClangTidyCheckFactories::registerCheckFactory( - StringRef Name, std::function Factory) { +void ClangTidyCheckFactories::registerCheckFactory(StringRef Name, + CheckFactory Factory) { Factories[Name] = Factory; } void ClangTidyCheckFactories::createChecks( - GlobList &Filter, std::vector> &Checks) { + ClangTidyContext *Context, + std::vector> &Checks) { + GlobList &Filter = Context->getChecksFilter(); for (const auto &Factory : Factories) { - if (Filter.contains(Factory.first)) { - ClangTidyCheck *Check = Factory.second(); - Check->setName(Factory.first); - Checks.emplace_back(Check); - } + if (Filter.contains(Factory.first)) + Checks.emplace_back(Factory.second(Factory.first, Context)); } } Index: clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tidy/ClangTidyOptions.h +++ clang-tidy/ClangTidyOptions.h @@ -14,6 +14,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorOr.h" +#include #include #include #include @@ -70,6 +71,12 @@ /// \brief Turns on temporary destructor-based analysis. llvm::Optional AnalyzeTemporaryDtors; + + typedef std::pair StringPair; + typedef std::map OptionMap; + + /// \brief Key-value mapping used to store check-specific options. + OptionMap CheckOptions; }; /// \brief Abstract interface for retrieving various ClangTidy options. Index: clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tidy/ClangTidyOptions.cpp +++ clang-tidy/ClangTidyOptions.cpp @@ -25,6 +25,7 @@ LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter) LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange) +LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair); namespace llvm { namespace yaml { @@ -57,11 +58,34 @@ } }; +template <> struct MappingTraits { + static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue) { + IO.mapRequired("key", KeyValue.first); + IO.mapRequired("value", KeyValue.second); + } +}; + +struct NOptionMap { + NOptionMap(IO &) {} + NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap) + : Options(OptionMap.begin(), OptionMap.end()) {} + ClangTidyOptions::OptionMap denormalize(IO &) { + ClangTidyOptions::OptionMap Map; + for (const auto &KeyValue : Options) + Map[KeyValue.first] = KeyValue.second; + return Map; + } + std::vector Options; +}; + template <> struct MappingTraits { static void mapping(IO &IO, ClangTidyOptions &Options) { + MappingNormalization NOpts( + IO, Options.CheckOptions); IO.mapOptional("Checks", Options.Checks); IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex); IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors); + IO.mapOptional("CheckOptions", NOpts->Options); } }; @@ -85,6 +109,10 @@ Result.HeaderFilterRegex = Other.HeaderFilterRegex; if (Other.AnalyzeTemporaryDtors) Result.AnalyzeTemporaryDtors = Other.AnalyzeTemporaryDtors; + + for (const auto &KeyValue : Other.CheckOptions) + Result.CheckOptions[KeyValue.first] = KeyValue.second; + return Result; } @@ -169,6 +197,10 @@ llvm::MemoryBuffer::getFile(ConfigFile.c_str()); if (std::error_code EC = Text.getError()) return EC; + // Skip empty files, e.g. files opened for writing via shell output + // redirection. + if ((*Text)->getBuffer().empty()) + return make_error_code(llvm::errc::no_such_file_or_directory); if (std::error_code EC = parseConfiguration((*Text)->getBuffer(), Options)) return EC; return Options.mergeWith(OverrideOptions); Index: clang-tidy/google/AvoidCStyleCastsCheck.h =================================================================== --- clang-tidy/google/AvoidCStyleCastsCheck.h +++ clang-tidy/google/AvoidCStyleCastsCheck.h @@ -26,6 +26,8 @@ /// ones generated by -Wold-style-cast. class AvoidCStyleCastsCheck : public ClangTidyCheck { public: + AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/ExplicitConstructorCheck.h =================================================================== --- clang-tidy/google/ExplicitConstructorCheck.h +++ clang-tidy/google/ExplicitConstructorCheck.h @@ -21,6 +21,8 @@ /// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Explicit_Constructors class ExplicitConstructorCheck : public ClangTidyCheck { public: + ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/ExplicitMakePairCheck.h =================================================================== --- clang-tidy/google/ExplicitMakePairCheck.h +++ clang-tidy/google/ExplicitMakePairCheck.h @@ -24,6 +24,8 @@ /// Corresponding cpplint.py check name: 'build/explicit_make_pair'. class ExplicitMakePairCheck : public ClangTidyCheck { public: + ExplicitMakePairCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/IntegerTypesCheck.h =================================================================== --- clang-tidy/google/IntegerTypesCheck.h +++ clang-tidy/google/IntegerTypesCheck.h @@ -21,9 +21,9 @@ /// Correspondig cpplint.py check: runtime/int. class IntegerTypesCheck : public ClangTidyCheck { public: - IntegerTypesCheck() - : UnsignedTypePrefix("uint"), SignedTypePrefix("int"), - AddUnderscoreT(false) {} + IntegerTypesCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), UnsignedTypePrefix("uint"), + SignedTypePrefix("int"), AddUnderscoreT(false) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; Index: clang-tidy/google/MemsetZeroLengthCheck.h =================================================================== --- clang-tidy/google/MemsetZeroLengthCheck.h +++ clang-tidy/google/MemsetZeroLengthCheck.h @@ -24,6 +24,8 @@ /// Corresponding cpplint.py check name: 'runtime/memset'. class MemsetZeroLengthCheck : public ClangTidyCheck { public: + MemsetZeroLengthCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/NamedParameterCheck.h =================================================================== --- clang-tidy/google/NamedParameterCheck.h +++ clang-tidy/google/NamedParameterCheck.h @@ -22,6 +22,8 @@ /// Corresponding cpplint.py check name: 'readability/function'. class NamedParameterCheck : public ClangTidyCheck { public: + NamedParameterCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/OverloadedUnaryAndCheck.h =================================================================== --- clang-tidy/google/OverloadedUnaryAndCheck.h +++ clang-tidy/google/OverloadedUnaryAndCheck.h @@ -22,6 +22,8 @@ /// Corresponding cpplint.py check name: 'runtime/operator'. class OverloadedUnaryAndCheck : public ClangTidyCheck { public: + OverloadedUnaryAndCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/StringReferenceMemberCheck.h =================================================================== --- clang-tidy/google/StringReferenceMemberCheck.h +++ clang-tidy/google/StringReferenceMemberCheck.h @@ -39,6 +39,8 @@ /// Corresponding cpplint.py check name: 'runtime/member_string_reference'. class StringReferenceMemberCheck : public ClangTidyCheck { public: + StringReferenceMemberCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/UnnamedNamespaceInHeaderCheck.h =================================================================== --- clang-tidy/google/UnnamedNamespaceInHeaderCheck.h +++ clang-tidy/google/UnnamedNamespaceInHeaderCheck.h @@ -22,6 +22,8 @@ /// Corresponding cpplint.py check name: 'build/namespaces'. class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck { public: + UnnamedNamespaceInHeaderCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/google/UsingNamespaceDirectiveCheck.h =================================================================== --- clang-tidy/google/UsingNamespaceDirectiveCheck.h +++ clang-tidy/google/UsingNamespaceDirectiveCheck.h @@ -22,6 +22,8 @@ /// Corresponding cpplint.py check name: 'build/namespaces'. class UsingNamespaceDirectiveCheck : public ClangTidyCheck { public: + UsingNamespaceDirectiveCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/llvm/HeaderGuardCheck.h =================================================================== --- clang-tidy/llvm/HeaderGuardCheck.h +++ clang-tidy/llvm/HeaderGuardCheck.h @@ -18,6 +18,8 @@ /// Finds and fixes header guards that do not adhere to LLVM style. class LLVMHeaderGuardCheck : public HeaderGuardCheck { public: + LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context) + : HeaderGuardCheck(Name, Context) {} bool shouldSuggestEndifComment(StringRef Filename) override { return false; } bool shouldFixHeaderGuard(StringRef Filename) override; std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override; Index: clang-tidy/llvm/IncludeOrderCheck.h =================================================================== --- clang-tidy/llvm/IncludeOrderCheck.h +++ clang-tidy/llvm/IncludeOrderCheck.h @@ -20,6 +20,8 @@ /// see: http://llvm.org/docs/CodingStandards.html#include-style class IncludeOrderCheck : public ClangTidyCheck { public: + IncludeOrderCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerPPCallbacks(CompilerInstance &Compiler) override; }; Index: clang-tidy/llvm/NamespaceCommentCheck.h =================================================================== --- clang-tidy/llvm/NamespaceCommentCheck.h +++ clang-tidy/llvm/NamespaceCommentCheck.h @@ -21,13 +21,16 @@ /// see: http://llvm.org/docs/CodingStandards.html#namespace-indentation class NamespaceCommentCheck : public ClangTidyCheck { public: - NamespaceCommentCheck(); + NamespaceCommentCheck(StringRef Name, ClangTidyContext *Context); void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; private: + void storeOptions(ClangTidyOptions::OptionMap &Options) override; + llvm::Regex NamespaceCommentPattern; const unsigned ShortNamespaceLines; + const unsigned SpacesBeforeComments; }; } // namespace tidy Index: clang-tidy/llvm/NamespaceCommentCheck.cpp =================================================================== --- clang-tidy/llvm/NamespaceCommentCheck.cpp +++ clang-tidy/llvm/NamespaceCommentCheck.cpp @@ -11,20 +11,26 @@ #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Lex/Lexer.h" - - -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" using namespace clang::ast_matchers; namespace clang { namespace tidy { -NamespaceCommentCheck::NamespaceCommentCheck() - : NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *" +NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + NamespaceCommentPattern("^/[/*] *(end (of )?)? *(anonymous|unnamed)? *" "namespace( +([a-zA-Z0-9_]+))? *(\\*/)?$", llvm::Regex::IgnoreCase), - ShortNamespaceLines(1) {} + ShortNamespaceLines(Options.get("ShortNamespaceLines", 1u)), + SpacesBeforeComments(Options.get("SpacesBeforeComments", 1u)) {} + +void NamespaceCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "ShortNamespaceLines", ShortNamespaceLines); + Options.store(Opts, "SpacesBeforeComments", SpacesBeforeComments); +} void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(namespaceDecl().bind("namespace"), this); @@ -36,10 +42,12 @@ Sources.getFileID(Loc1) == Sources.getFileID(Loc2); } -std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak) { +std::string getNamespaceComment(const NamespaceDecl *ND, bool InsertLineBreak, + unsigned SpacesBeforeComments) { std::string Fix = "// namespace"; if (!ND->isAnonymousNamespace()) - Fix.append(" ").append(ND->getNameAsString()); + Fix.append(std::string(SpacesBeforeComments, ' ')) + .append(ND->getNameAsString()); if (InsertLineBreak) Fix.append("\n"); return Fix; @@ -97,7 +105,8 @@ diag(Loc, "namespace closing comment refers to a wrong namespace '%0'") << NamespaceNameInComment << FixItHint::CreateReplacement( - OldCommentRange, getNamespaceComment(ND, NeedLineBreak)); + OldCommentRange, + getNamespaceComment(ND, NeedLineBreak, SpacesBeforeComments)); return; } @@ -110,7 +119,8 @@ diag(ND->getLocation(), "namespace not terminated with a closing comment") << FixItHint::CreateInsertion( - AfterRBrace, " " + getNamespaceComment(ND, NeedLineBreak)); + AfterRBrace, + " " + getNamespaceComment(ND, NeedLineBreak, SpacesBeforeComments)); } } // namespace tidy Index: clang-tidy/llvm/TwineLocalCheck.h =================================================================== --- clang-tidy/llvm/TwineLocalCheck.h +++ clang-tidy/llvm/TwineLocalCheck.h @@ -19,7 +19,8 @@ /// and should be generally avoided. class TwineLocalCheck : public ClangTidyCheck { public: - TwineLocalCheck(); + TwineLocalCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/llvm/TwineLocalCheck.cpp =================================================================== --- clang-tidy/llvm/TwineLocalCheck.cpp +++ clang-tidy/llvm/TwineLocalCheck.cpp @@ -17,8 +17,6 @@ namespace clang { namespace tidy { -TwineLocalCheck::TwineLocalCheck() {} - void TwineLocalCheck::registerMatchers(MatchFinder *Finder) { auto TwineType = qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine")))); Index: clang-tidy/misc/ArgumentCommentCheck.h =================================================================== --- clang-tidy/misc/ArgumentCommentCheck.h +++ clang-tidy/misc/ArgumentCommentCheck.h @@ -19,7 +19,7 @@ /// \brief Checks that argument comments match parameter names. class ArgumentCommentCheck : public ClangTidyCheck { public: - ArgumentCommentCheck(); + ArgumentCommentCheck(StringRef Name, ClangTidyContext *Context); void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; Index: clang-tidy/misc/ArgumentCommentCheck.cpp =================================================================== --- clang-tidy/misc/ArgumentCommentCheck.cpp +++ clang-tidy/misc/ArgumentCommentCheck.cpp @@ -18,8 +18,10 @@ namespace clang { namespace tidy { -ArgumentCommentCheck::ArgumentCommentCheck() - : IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {} +ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {} void ArgumentCommentCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( Index: clang-tidy/misc/BoolPointerImplicitConversion.h =================================================================== --- clang-tidy/misc/BoolPointerImplicitConversion.h +++ clang-tidy/misc/BoolPointerImplicitConversion.h @@ -23,6 +23,8 @@ /// } class BoolPointerImplicitConversion : public ClangTidyCheck { public: + BoolPointerImplicitConversion(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/misc/RedundantSmartptrGet.h =================================================================== --- clang-tidy/misc/RedundantSmartptrGet.h +++ clang-tidy/misc/RedundantSmartptrGet.h @@ -23,6 +23,8 @@ /// *ptr->get() ==> **ptr class RedundantSmartptrGet : public ClangTidyCheck { public: + RedundantSmartptrGet(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/misc/SwappedArgumentsCheck.h =================================================================== --- clang-tidy/misc/SwappedArgumentsCheck.h +++ clang-tidy/misc/SwappedArgumentsCheck.h @@ -19,6 +19,8 @@ /// conversions. class SwappedArgumentsCheck : public ClangTidyCheck { public: + SwappedArgumentsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/misc/UndelegatedConstructor.h =================================================================== --- clang-tidy/misc/UndelegatedConstructor.h +++ clang-tidy/misc/UndelegatedConstructor.h @@ -20,6 +20,8 @@ /// meant to use a delegating constructor or base class initializer. class UndelegatedConstructorCheck : public ClangTidyCheck { public: + UndelegatedConstructorCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/misc/UnusedRAII.h =================================================================== --- clang-tidy/misc/UnusedRAII.h +++ clang-tidy/misc/UnusedRAII.h @@ -37,6 +37,8 @@ /// - Ignore objects returned from a call. class UnusedRAIICheck : public ClangTidyCheck { public: + UnusedRAIICheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/misc/UseOverride.h =================================================================== --- clang-tidy/misc/UseOverride.h +++ clang-tidy/misc/UseOverride.h @@ -18,6 +18,8 @@ /// \brief Use C++11's 'override' and remove 'virtual' where applicable. class UseOverride : public ClangTidyCheck { public: + UseOverride(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -173,6 +173,7 @@ } if (DumpConfig) { + EffectiveOptions.CheckOptions = getCheckOptions(EffectiveOptions); llvm::outs() << configurationAsText(ClangTidyOptions::getDefaults() .mergeWith(EffectiveOptions)) << "\n"; Index: clang-tidy/utils/HeaderGuard.h =================================================================== --- clang-tidy/utils/HeaderGuard.h +++ clang-tidy/utils/HeaderGuard.h @@ -18,6 +18,8 @@ /// \brief Finds and fixes header guards. class HeaderGuardCheck : public ClangTidyCheck { public: + HeaderGuardCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerPPCallbacks(CompilerInstance &Compiler) override; /// \brief Returns true if the checker should suggest inserting a trailing Index: unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp =================================================================== --- unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp +++ unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp @@ -8,6 +8,8 @@ class TestCheck : public ClangTidyCheck { public: + TestCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override { Finder->addMatcher(ast_matchers::varDecl().bind("var"), this); } @@ -23,9 +25,8 @@ std::vector Errors; runCheckOnCode("int a;", &Errors); EXPECT_EQ(2ul, Errors.size()); - // FIXME: Remove " []" once the check name is removed from the message text. - EXPECT_EQ("type specifier []", Errors[0].Message.Message); - EXPECT_EQ("variable []", Errors[1].Message.Message); + EXPECT_EQ("type specifier", Errors[0].Message.Message); + EXPECT_EQ("variable", Errors[1].Message.Message); } TEST(GlobList, Empty) { Index: unittests/clang-tidy/ClangTidyTest.h =================================================================== --- unittests/clang-tidy/ClangTidyTest.h +++ unittests/clang-tidy/ClangTidyTest.h @@ -44,13 +44,12 @@ std::vector *Errors = nullptr, const Twine &Filename = "input.cc", ArrayRef ExtraArgs = None) { - T Check; ClangTidyOptions Options; Options.Checks = "*"; ClangTidyContext Context(llvm::make_unique( ClangTidyGlobalOptions(), Options)); ClangTidyDiagnosticConsumer DiagConsumer(Context); - Check.setContext(&Context); + T Check("test-check", &Context); std::vector ArgCXX11(1, "-std=c++11"); ArgCXX11.insert(ArgCXX11.end(), ExtraArgs.begin(), ExtraArgs.end()); Index: unittests/clang-tidy/LLVMModuleTest.cpp =================================================================== --- unittests/clang-tidy/LLVMModuleTest.cpp +++ unittests/clang-tidy/LLVMModuleTest.cpp @@ -95,6 +95,8 @@ namespace { struct WithEndifComment : public LLVMHeaderGuardCheck { + WithEndifComment(StringRef Name, ClangTidyContext *Context) + : LLVMHeaderGuardCheck(Name, Context) {} bool shouldSuggestEndifComment(StringRef Filename) override { return true; } }; } // namespace