mgartmann updated this revision to Diff 351838. mgartmann marked 5 inline comments as done. mgartmann added a comment.
- removed empty configs from tests - moved documentation to Google's check - extended matchers so that namespaces for classes and conversion operators can be specified - adjusted documentation and tests Unfortunately, I was not able to implement functionality to ignore constructors and operates by using Regex in the given time. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D102779/new/ https://reviews.llvm.org/D102779 Files: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-explicit-constructor-and-conversion.rst clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/google-explicit-constructor-ignoredconstructors-option.cpp clang-tools-extra/test/clang-tidy/checkers/google-explicit-constructor-ignoredconversionoperators-option.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/google-explicit-constructor-ignoredconversionoperators-option.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/google-explicit-constructor-ignoredconversionoperators-option.cpp @@ -0,0 +1,95 @@ +// RUN: %check_clang_tidy -check-suffix=DEFAULT %s google-explicit-constructor %t + +// RUN: %check_clang_tidy -check-suffix=IGNORED %s \ +// RUN: google-explicit-constructor %t -- \ +// RUN: -config='{CheckOptions: [ \ +// RUN: {key: google-explicit-constructor.IgnoredConversionOperators, value: "Foo::A::operator bool;Foo::A::operator type-parameter-0-0;B::operator double;B::operator A"} \ +// RUN: ]}' + +namespace Foo { +struct A { + A() {} + A(int x, int y) {} + + explicit A(void *x) {} + explicit A(void *x, void *y) {} + + A(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit A(int x1); + + operator bool() const { return true; } + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit operator bool() const { return true; } + + operator double() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator double() const; + + template <typename Ty> + operator Ty() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator type-parameter-0-0' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit operator Ty() const; +}; + +inline A::A(int x1) {} +} // namespace Foo + +using Foo::A; +struct B { + B() {} + B(int x, int y) {} + + explicit B(void *x) {} + explicit B(void *x, void *y) {} + + B(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit B(int x1); + + operator bool() const { return true; } + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; } + + operator double() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit operator double() const; + + operator A() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator A' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit operator A() const; +}; + +struct C { + C() {} + C(int x, int y) {} + + explicit C(void *x) {} + explicit C(void *x, void *y) {} + + C(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit C(int x1); + + operator bool() const { return true; } + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; } + + operator double() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator double() const; + + operator A() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator A' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator A' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator A() const; + + explicit operator B() const; +}; Index: clang-tools-extra/test/clang-tidy/checkers/google-explicit-constructor-ignoredconstructors-option.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/google-explicit-constructor-ignoredconstructors-option.cpp @@ -0,0 +1,159 @@ +// RUN: %check_clang_tidy -check-suffix=DEFAULT %s google-explicit-constructor %t + +// RUN: %check_clang_tidy -check-suffix=IGNORED %s \ +// RUN: google-explicit-constructor %t -- \ +// RUN: -config='{CheckOptions: [ \ +// RUN: {key: google-explicit-constructor.IgnoredConstructors, value: "Foo::A::A;B::B"} \ +// RUN: ]}' + +namespace Foo { +struct A { + A() {} + A(int x, int y) {} + + explicit A(void *x) {} + explicit A(void *x, void *y) {} + + explicit A(const A &a) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}A(const A &a) {} + // IGNORED: Warning disabled with ConstructorWhitelist=A + + A(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit A(int x1); + // IGNORED: Warning disabled with ConstructorWhitelist=A + + A(double x2, double y = 3.14) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit A(double x2, double y = 3.14) {} + // IGNORED: Warning disabled with ConstructorWhitelist=A + + template <typename... T> + A(T &&...args); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument + // CHECK-FIXES-DEFAULT: {{^ }}explicit A(T &&...args); + // IGNORED: Warning disabled with ConstructorWhitelist=A + + operator bool() const { return true; } + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; } + + operator double() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator double() const; +}; + +inline A::A(int x1) {} +} // namespace Foo + +namespace Bar { +struct A { + A() {} + A(int x, int y) {} + + explicit A(void *x) {} + explicit A(void *x, void *y) {} + + explicit A(const A &a) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] + // CHECK-FIXES: {{^ }}A(const A &a) {} + + A(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit A(int x1); + + A(double x2, double y = 3.14) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit A(double x2, double y = 3.14) {} + + template <typename... T> + A(T &&...args); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: constructors that are callable with a single argument + // CHECK-FIXES: {{^ }}explicit A(T &&...args); +}; +} // namespace Bar + +struct B { + B() {} + B(int x, int y) {} + + explicit B(void *x) {} + explicit B(void *x, void *y) {} + + explicit B(const B &b) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}B(const B &b) {} + // IGNORED: Warning disabled with ConstructorWhitelist=B + + B(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit B(int x1); + // IGNORED: Warning disabled with ConstructorWhitelist=B + + B(double x2, double y = 3.14) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES-DEFAULT: {{^ }}explicit B(double x2, double y = 3.14) {} + // IGNORED: Warning disabled with ConstructorWhitelist=B + + template <typename... T> + B(T &&...args); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument + // CHECK-FIXES-DEFAULT: {{^ }}explicit B(T &&...args); + // IGNORED: Warning disabled with ConstructorWhitelist=B + + operator bool() const { return true; } + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; } + + operator double() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator double() const; +}; + +struct C { + C() {} + C(int x, int y) {} + + explicit C(void *x) {} + explicit C(void *x, void *y) {} + + explicit C(const C &c) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor] + // CHECK-FIXES: {{^ }}C(const C &c) {} + + C(int x1); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit C(int x1); + + C(double x2, double y = 3.14) {} + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit C(double x2, double y = 3.14) {} + + template <typename... T> + C(T &&...args); + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: constructors that are callable with a single argument + // CHECK-FIXES: {{^ }}explicit C(T &&...args); + + operator bool() const { return true; } + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator bool() const { return true; } + + operator double() const; + // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-MESSAGES-IGNORED: :[[@LINE-2]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor] + // CHECK-FIXES: {{^ }}explicit operator double() const; +}; Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -407,6 +407,7 @@ `cppcoreguidelines-avoid-c-arrays <cppcoreguidelines-avoid-c-arrays.html>`_, `modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_, `cppcoreguidelines-avoid-magic-numbers <cppcoreguidelines-avoid-magic-numbers.html>`_, `readability-magic-numbers <readability-magic-numbers.html>`_, `cppcoreguidelines-c-copy-assignment-signature <cppcoreguidelines-c-copy-assignment-signature.html>`_, `misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_, + `cppcoreguidelines-explicit-constructor-and-conversion <cppcoreguidelines-explicit-constructor-and-conversion.html>`_, `google-explicit-constructor <google-explicit-constructor.html>`_, "Yes" `cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines-explicit-virtual-functions.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes" `cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines-non-private-member-variables-in-classes.html>`_, `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_, `fuchsia-header-anon-namespaces <fuchsia-header-anon-namespaces.html>`_, `google-build-namespaces <google-build-namespaces.html>`_, Index: clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst +++ clang-tools-extra/docs/clang-tidy/checks/google-explicit-constructor.rst @@ -54,3 +54,43 @@ See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors + +Options +------- + +.. option:: IgnoredConstructors + + Non-explicit single-argument constructors in this semicolon-separated list + will be ignored and will not trigger a warning. To ignore constructors of a + class ``A``, the list would look as follows: ``A::A``. If class ``A`` + resided in a namespace ``Foo``, its constructors have to be ignored as + follows: ``Foo::A::A``. The default list is empty. This option is used by + this check's + `cppcoreguidelines-explicit-constructor-and-conversion <cppcoreguidelines-explicit-constructor-and-conversion.html>`_ + alias to comply with the CppCoreGuidelines. + +.. option:: IgnoredConversionOperators + + Non-explicit conversion operators in this semicolon-separated list will be + ignored and will not trigger a warning. The list to ignore a conversion + operator `operator B()` in class ``A`` would look as follows: + ``A::operator B``. If an operator's class resides in any namespace, + its namespace has to be specified as well. If class ``A`` resides in a + namespace ``Foo``, its ``operator B()`` would be ignored as follows: + ``Foo::A::operator B()``. Templated operators have to be ignored by their + template parameter name displayed in this check's warning: + +.. code-block:: c++ + + struct A { + template <typename Ty> + operator Ty() const; + // warning: 'operator type-parameter-0-1' must be marked explicit ... + ... + + In the above example, ``operator Ty`` is ignored as follows: + ``Foo::A::operator type-parameter-0-0``. The default list is empty. + +This check implements `C.46 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c46-by-default-declare-single-argument-constructors-explicit>`_ +and `C.164 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c164-avoid-implicit-conversion-operators>`_ +from the CppCoreGuidelines. Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-explicit-constructor-and-conversion.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-explicit-constructor-and-conversion.rst @@ -0,0 +1,10 @@ +.. title:: clang-tidy - cppcoreguidelines-explicit-constructor-and-conversion +.. meta:: + :http-equiv=refresh: 5;URL=google-explicit-constructor.html + +cppcoreguidelines-explicit-constructor +====================================== + +The cppcoreguidelines-explicit-constructor-and-conversion check is an alias, +please see `google-explicit-constructor <google-explicit-constructor.html>`_ +for more information. Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -127,6 +127,11 @@ :doc:`concurrency-thread-canceltype-asynchronous <clang-tidy/checks/concurrency-thread-canceltype-asynchronous>` was added. +- New alias :doc:`cppcoreguidelines-explicit-constructor-and-conversion + <clang-tidy/checks/cppcoreguidelines-explicit-constructor-and-conversion>` to + :doc:`google-explicit-constructor + <clang-tidy/checks/google-explicit-constructor>` was added. + Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,6 +147,12 @@ function or assignment to ``nullptr``. Added support for pointers to ``std::unique_ptr``. +- Improved :doc:`google-explicit-constructor + <clang-tidy/checks/google-explicit-constructor>` check. + + Added options to disable warnings for constructors and conversion operators + contained in a ignore-list. + Removed checks ^^^^^^^^^^^^^^ Index: clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h =================================================================== --- clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h +++ clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H #include "../ClangTidyCheck.h" +#include "../utils/OptionsUtils.h" namespace clang { namespace tidy { @@ -24,12 +25,21 @@ class ExplicitConstructorCheck : public ClangTidyCheck { public: ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + : ClangTidyCheck(Name, Context), + IgnoredConstructors(utils::options::parseStringList( + Options.get("IgnoredConstructors", ""))), + IgnoredConversionOperators(utils::options::parseStringList( + Options.get("IgnoredConversionOperators", ""))) {} + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + const std::vector<std::string> IgnoredConstructors; + const std::vector<std::string> IgnoredConversionOperators; }; } // namespace google Index: clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp +++ clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ExplicitConstructorCheck.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -17,17 +18,42 @@ namespace clang { namespace tidy { namespace google { +namespace { + +AST_MATCHER_P(NamedDecl, isIgnored, std::vector<std::string>, + IgnoredCtorsOrOps) { + std::string QualifiedName; + llvm::raw_string_ostream FQNStream(QualifiedName); + Node.printQualifiedName(FQNStream); + + return llvm::any_of(IgnoredCtorsOrOps, + [QualifiedName](const std::string &NameInOptions) { + return NameInOptions == QualifiedName; + }); +} + +} // namespace + +void ExplicitConstructorCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IgnoredConstructors", + utils::options::serializeStringList(IgnoredConstructors)); + Options.store( + Opts, "IgnoredConversionOperators", + utils::options::serializeStringList(IgnoredConversionOperators)); +} void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( cxxConstructorDecl(unless(anyOf(isImplicit(), // Compiler-generated. - isDeleted(), isInstantiated()))) + isDeleted(), isInstantiated(), + isIgnored(IgnoredConstructors)))) .bind("ctor"), this); Finder->addMatcher( cxxConversionDecl(unless(anyOf(isExplicit(), // Already marked explicit. isImplicit(), // Compiler-generated. - isDeleted(), isInstantiated()))) + isDeleted(), isInstantiated(), + isIgnored(IgnoredConversionOperators)))) .bind("conversion"), this); Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -9,6 +9,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "../google/ExplicitConstructorCheck.h" #include "../misc/NonPrivateMemberVariablesInClassesCheck.h" #include "../misc/UnconventionalAssignOperatorCheck.h" #include "../modernize/AvoidCArraysCheck.h" @@ -52,6 +53,8 @@ "cppcoreguidelines-avoid-magic-numbers"); CheckFactories.registerCheck<AvoidNonConstGlobalVariablesCheck>( "cppcoreguidelines-avoid-non-const-global-variables"); + CheckFactories.registerCheck<google::ExplicitConstructorCheck>( + "cppcoreguidelines-explicit-constructor-and-conversion"); CheckFactories.registerCheck<modernize::UseOverrideCheck>( "cppcoreguidelines-explicit-virtual-functions"); CheckFactories.registerCheck<InitVariablesCheck>(
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits