[clang-tidy] Migrate explicit-constructor check from google to misc and add relative aliases (#194807)

Fixes #126032
This commit is contained in:
Mao Chuanjun 2026-05-09 18:32:48 +08:00 committed by GitHub
parent ebf6a41a18
commit 5022a168a7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 112 additions and 81 deletions

View file

@ -9,6 +9,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../bugprone/NarrowingConversionsCheck.h"
#include "../misc/ExplicitConstructorCheck.h"
#include "../misc/NonPrivateMemberVariablesInClassesCheck.h"
#include "../misc/UnconventionalAssignOperatorCheck.h"
#include "../modernize/AvoidCArraysCheck.h"
@ -75,6 +76,8 @@ public:
"cppcoreguidelines-avoid-non-const-global-variables");
CheckFactories.registerCheck<AvoidReferenceCoroutineParametersCheck>(
"cppcoreguidelines-avoid-reference-coroutine-parameters");
CheckFactories.registerCheck<misc::ExplicitConstructorCheck>(
"cppcoreguidelines-explicit-constructor");
CheckFactories.registerCheck<modernize::UseOverrideCheck>(
"cppcoreguidelines-explicit-virtual-functions");
CheckFactories.registerCheck<InitVariablesCheck>(

View file

@ -8,7 +8,6 @@ add_clang_library(clangTidyGoogleModule STATIC
AvoidThrowingObjCExceptionCheck.cpp
AvoidUnderscoreInGoogletestNameCheck.cpp
DefaultArgumentsCheck.cpp
ExplicitConstructorCheck.cpp
ExplicitMakePairCheck.cpp
FloatTypesCheck.cpp
FunctionNamingCheck.cpp

View file

@ -9,6 +9,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../misc/AnonymousNamespaceInHeaderCheck.h"
#include "../misc/ExplicitConstructorCheck.h"
#include "../modernize/AvoidCStyleCastCheck.h"
#include "../readability/BracesAroundStatementsCheck.h"
#include "../readability/FunctionSizeCheck.h"
@ -17,7 +18,6 @@
#include "AvoidThrowingObjCExceptionCheck.h"
#include "AvoidUnderscoreInGoogletestNameCheck.h"
#include "DefaultArgumentsCheck.h"
#include "ExplicitConstructorCheck.h"
#include "ExplicitMakePairCheck.h"
#include "FloatTypesCheck.h"
#include "FunctionNamingCheck.h"
@ -46,7 +46,7 @@ public:
"google-build-using-namespace");
CheckFactories.registerCheck<DefaultArgumentsCheck>(
"google-default-arguments");
CheckFactories.registerCheck<ExplicitConstructorCheck>(
CheckFactories.registerCheck<misc::ExplicitConstructorCheck>(
"google-explicit-constructor");
CheckFactories.registerCheck<readability::GlobalNamesInHeadersCheck>(
"google-global-names-in-headers");

View file

@ -19,7 +19,7 @@
#include "../cppcoreguidelines/ProTypeMemberInitCheck.h"
#include "../cppcoreguidelines/ProTypeVarargCheck.h"
#include "../cppcoreguidelines/SpecialMemberFunctionsCheck.h"
#include "../google/ExplicitConstructorCheck.h"
#include "../misc/ExplicitConstructorCheck.h"
#include "../misc/NewDeleteOverloadsCheck.h"
#include "../misc/StaticAssertCheck.h"
#include "../modernize/AvoidCArraysCheck.h"
@ -63,7 +63,7 @@ public:
"hicpp-multiway-paths-covered");
CheckFactories.registerCheck<bugprone::SignedBitwiseCheck>(
"hicpp-signed-bitwise");
CheckFactories.registerCheck<google::ExplicitConstructorCheck>(
CheckFactories.registerCheck<misc::ExplicitConstructorCheck>(
"hicpp-explicit-conversions");
CheckFactories.registerCheck<readability::FunctionSizeCheck>(
"hicpp-function-size");

View file

@ -19,10 +19,11 @@ set_target_properties(genconfusable PROPERTIES FOLDER "Clang Tools Extra/Sourceg
add_clang_library(clangTidyMiscModule STATIC
AnonymousNamespaceInHeaderCheck.cpp
ConfusableIdentifierCheck.cpp
ConstCorrectnessCheck.cpp
CoroutineHostileRAIICheck.cpp
DefinitionsInHeadersCheck.cpp
ConfusableIdentifierCheck.cpp
ExplicitConstructorCheck.cpp
HeaderIncludeCycleCheck.cpp
IncludeCleanerCheck.cpp
MiscTidyModule.cpp

View file

@ -14,7 +14,7 @@
using namespace clang::ast_matchers;
namespace clang::tidy::google {
namespace clang::tidy::misc {
void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
@ -136,4 +136,4 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
Diag << FixItHint::CreateInsertion(Loc, "explicit ");
}
} // namespace clang::tidy::google
} // namespace clang::tidy::misc

View file

@ -6,19 +6,17 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_EXPLICITCONSTRUCTORCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_EXPLICITCONSTRUCTORCHECK_H
#include "../ClangTidyCheck.h"
namespace clang::tidy::google {
namespace clang::tidy::misc {
/// Checks that all single-argument constructors are explicit.
///
/// See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors
///
/// For the user-facing documentation see:
/// https://clang.llvm.org/extra/clang-tidy/checks/google/explicit-constructor.html
/// https://clang.llvm.org/extra/clang-tidy/checks/misc/explicit-constructor.html
class ExplicitConstructorCheck : public ClangTidyCheck {
public:
ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context)
@ -30,6 +28,6 @@ public:
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace clang::tidy::google
} // namespace clang::tidy::misc
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_EXPLICITCONSTRUCTORCHECK_H
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_EXPLICITCONSTRUCTORCHECK_H

View file

@ -13,6 +13,7 @@
#include "ConstCorrectnessCheck.h"
#include "CoroutineHostileRAIICheck.h"
#include "DefinitionsInHeadersCheck.h"
#include "ExplicitConstructorCheck.h"
#include "HeaderIncludeCycleCheck.h"
#include "IncludeCleanerCheck.h"
#include "MisleadingBidirectionalCheck.h"
@ -53,6 +54,8 @@ public:
"misc-coroutine-hostile-raii");
CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
"misc-definitions-in-headers");
CheckFactories.registerCheck<ExplicitConstructorCheck>(
"misc-explicit-constructor");
CheckFactories.registerCheck<HeaderIncludeCycleCheck>(
"misc-header-include-cycle");
CheckFactories.registerCheck<IncludeCleanerCheck>("misc-include-cleaner");

View file

@ -207,6 +207,18 @@ New check aliases
to :doc:`bugprone-assignment-in-selection-statement
<clang-tidy/checks/bugprone/assignment-in-selection-statement>`.
- Renamed :doc:`cppcoreguidelines-explicit-constructor
<clang-tidy/checks/cppcoreguidelines/explicit-constructor>`
to :doc:`misc-explicit-constructor
<clang-tidy/checks/misc/explicit-constructor>`. The
`cppcoreguidelines-explicit-constructor` name is kept as an alias.
- Renamed :doc:`google-explicit-constructor
<clang-tidy/checks/google/explicit-constructor>`
to :doc:`misc-explicit-constructor
<clang-tidy/checks/misc/explicit-constructor>`. The
`google-explicit-constructor` name is kept as an alias.
- Renamed :doc:`hicpp-exception-baseclass
<clang-tidy/checks/hicpp/exception-baseclass>`
to :doc:`bugprone-std-exception-baseclass

View file

@ -0,0 +1,7 @@
.. title:: clang-tidy - cppcoreguidelines-explicit-constructor
cppcoreguidelines-explicit-constructor
======================================
This check is an alias for
:doc:`misc-explicit-constructor <../misc/explicit-constructor>`.

View file

@ -3,54 +3,7 @@
google-explicit-constructor
===========================
Checks that constructors callable with a single argument and conversion
operators are marked explicit to avoid the risk of unintentional implicit
conversions.
Consider this example:
.. code-block:: c++
struct S {
int x;
operator bool() const { return true; }
};
bool f() {
S a{1};
S b{2};
return a == b;
}
The function will return ``true``, since the objects are implicitly converted
to ``bool`` before comparison, which is unlikely to be the intent.
The check will suggest inserting ``explicit`` before the constructor or
conversion operator declaration. However, copy and move constructors should not
be explicit, as well as constructors taking a single ``initializer_list``
argument.
This code:
.. code-block:: c++
struct S {
S(int a);
explicit S(const S&);
operator bool() const;
...
will become
.. code-block:: c++
struct S {
explicit S(int a);
S(const S&);
explicit operator bool() const;
...
This check is an alias for
:doc:`misc-explicit-constructor <../misc/explicit-constructor>`.
See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors

View file

@ -4,7 +4,7 @@ hicpp-explicit-conversions
==========================
This check is an alias for
:doc:`google-explicit-constructor <../google/explicit-constructor>`.
:doc:`misc-explicit-constructor <../misc/explicit-constructor>`.
Used to enforce parts of `rule 5.4.1
<https://www.perforce.com/resources/qac/high-integrity-cpp-coding-rules>`_.

View file

@ -230,7 +230,6 @@ Clang-Tidy Checks
:doc:`google-build-explicit-make-pair <google/build-explicit-make-pair>`,
:doc:`google-build-using-namespace <google/build-using-namespace>`,
:doc:`google-default-arguments <google/default-arguments>`,
:doc:`google-explicit-constructor <google/explicit-constructor>`, "Yes"
:doc:`google-global-names-in-headers <google/global-names-in-headers>`,
:doc:`google-objc-avoid-nsobject-new <google/objc-avoid-nsobject-new>`,
:doc:`google-objc-avoid-throwing-exception <google/objc-avoid-throwing-exception>`,
@ -265,6 +264,7 @@ Clang-Tidy Checks
:doc:`misc-const-correctness <misc/const-correctness>`, "Yes"
:doc:`misc-coroutine-hostile-raii <misc/coroutine-hostile-raii>`,
:doc:`misc-definitions-in-headers <misc/definitions-in-headers>`, "Yes"
:doc:`misc-explicit-constructor <misc/explicit-constructor>`, "Yes"
:doc:`misc-header-include-cycle <misc/header-include-cycle>`,
:doc:`misc-include-cleaner <misc/include-cleaner>`, "Yes"
:doc:`misc-misleading-bidirectional <misc/misleading-bidirectional>`,
@ -586,6 +586,7 @@ Check aliases
:doc:`cppcoreguidelines-avoid-c-arrays <cppcoreguidelines/avoid-c-arrays>`, :doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`,
:doc:`cppcoreguidelines-avoid-magic-numbers <cppcoreguidelines/avoid-magic-numbers>`, :doc:`readability-magic-numbers <readability/magic-numbers>`,
:doc:`cppcoreguidelines-c-copy-assignment-signature <cppcoreguidelines/c-copy-assignment-signature>`, :doc:`misc-unconventional-assign-operator <misc/unconventional-assign-operator>`,
:doc:`cppcoreguidelines-explicit-constructor <cppcoreguidelines/explicit-constructor>`, :doc:`misc-explicit-constructor <misc/explicit-constructor>`, "Yes"
:doc:`cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines/explicit-virtual-functions>`, :doc:`modernize-use-override <modernize/use-override>`, "Yes"
:doc:`cppcoreguidelines-macro-to-enum <cppcoreguidelines/macro-to-enum>`, :doc:`modernize-macro-to-enum <modernize/macro-to-enum>`, "Yes"
:doc:`cppcoreguidelines-narrowing-conversions <cppcoreguidelines/narrowing-conversions>`, :doc:`bugprone-narrowing-conversions <bugprone/narrowing-conversions>`,
@ -597,6 +598,7 @@ Check aliases
:doc:`fuchsia-header-anon-namespaces <fuchsia/header-anon-namespaces>`, :doc:`misc-anonymous-namespace-in-header <misc/anonymous-namespace-in-header>`,
:doc:`fuchsia-multiple-inheritance <fuchsia/multiple-inheritance>`, :doc:`misc-multiple-inheritance <misc/multiple-inheritance>`,
:doc:`google-build-namespaces <google/build-namespaces>`, :doc:`misc-anonymous-namespace-in-header <misc/anonymous-namespace-in-header>`,
:doc:`google-explicit-constructor <google/explicit-constructor>`, :doc:`misc-explicit-constructor <misc/explicit-constructor>`, "Yes"
:doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`google-readability-casting <google/readability-casting>`, :doc:`modernize-avoid-c-style-cast <modernize/avoid-c-style-cast>`, "Yes"
:doc:`google-readability-function-size <google/readability-function-size>`, :doc:`readability-function-size <readability/function-size>`,
@ -606,7 +608,7 @@ Check aliases
:doc:`hicpp-braces-around-statements <hicpp/braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes"
:doc:`hicpp-deprecated-headers <hicpp/deprecated-headers>`, :doc:`modernize-deprecated-headers <modernize/deprecated-headers>`, "Yes"
:doc:`hicpp-exception-baseclass <hicpp/exception-baseclass>`, :doc:`bugprone-std-exception-baseclass <bugprone/std-exception-baseclass>`,
:doc:`hicpp-explicit-conversions <hicpp/explicit-conversions>`, :doc:`google-explicit-constructor <google/explicit-constructor>`, "Yes"
:doc:`hicpp-explicit-conversions <hicpp/explicit-conversions>`, :doc:`misc-explicit-constructor <misc/explicit-constructor>`, "Yes"
:doc:`hicpp-function-size <hicpp/function-size>`, :doc:`readability-function-size <readability/function-size>`,
:doc:`hicpp-ignored-remove-result <hicpp/ignored-remove-result>`, :doc:`bugprone-unused-return-value <bugprone/unused-return-value>`,
:doc:`hicpp-invalid-access-moved <hicpp/invalid-access-moved>`, :doc:`bugprone-use-after-move <bugprone/use-after-move>`,

View file

@ -0,0 +1,51 @@
.. title:: clang-tidy - misc-explicit-constructor
misc-explicit-constructor
=========================
Checks that constructors callable with a single argument and conversion
operators are marked explicit to avoid the risk of unintentional implicit
conversions.
Consider this example:
.. code-block:: c++
struct S {
int x;
operator bool() const { return true; }
};
bool f() {
S a{1};
S b{2};
return a == b;
}
The function will return ``true``, since the objects are implicitly converted
to ``bool`` before comparison, which is unlikely to be the intent.
The check will suggest inserting ``explicit`` before the constructor or
conversion operator declaration. However, copy and move constructors should not
be explicit, as well as constructors taking a single ``initializer_list``
argument.
This code:
.. code-block:: c++
struct S {
S(int a);
explicit S(const S&);
operator bool() const;
...
will become
.. code-block:: c++
struct S {
explicit S(int a);
S(const S&);
explicit operator bool() const;
...

View file

@ -1,4 +1,4 @@
// RUN: %check_clang_tidy %s google-explicit-constructor %t -std=c++20-or-later
// RUN: %check_clang_tidy %s misc-explicit-constructor %t -std=c++20-or-later
namespace issue_81121
{
@ -20,7 +20,7 @@ struct C {
struct D {
explicit(ConstFalse) D(int);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false'
};
template <typename>
@ -41,7 +41,7 @@ struct G {
template <typename>
struct H {
explicit(ConstFalse) H(int);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false'
};
template <int Val>

View file

@ -1,4 +1,4 @@
// RUN: %check_clang_tidy %s google-explicit-constructor %t
// RUN: %check_clang_tidy %s misc-explicit-constructor %t
namespace std {
typedef decltype(sizeof(int)) size_t;
@ -43,15 +43,15 @@ struct A {
operator double() const = delete;
explicit A(const A& a) {}
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit
// CHECK-FIXES: A(const A& a) {}
A(int x1);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions
// CHECK-FIXES: explicit A(int x1);
A(double x2, double y = 3.14) {}
// CHECK-MESSAGES: :[[@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: :[[@LINE-1]]:3: warning: constructors that are callable with a single argument must be marked explicit to avoid unintentional implicit conversions
// CHECK-FIXES: explicit A(double x2, double y = 3.14) {}
template <typename... T>
@ -68,15 +68,15 @@ struct B {
B(std::initializer_list<unsigned> &&list3) {}
operator bool() const { return true; }
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator bool' must be marked explicit to avoid unintentional implicit conversions
// CHECK-FIXES: explicit operator bool() const { return true; }
operator double() const;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'operator double' must be marked explicit to avoid unintentional implicit conversions
// CHECK-FIXES: explicit operator double() const;
explicit B(::std::initializer_list<double> list4) {}
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor should not be declared explicit [google-explicit-constructor]
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor should not be declared explicit
// CHECK-FIXES: B(::std::initializer_list<double> list4) {}
explicit B(const ::std::initializer_list<char> &list5) {}

View file

@ -1,9 +1,12 @@
#include "ClangTidyTest.h"
#include "google/ExplicitConstructorCheck.h"
#include "google/GlobalNamesInHeadersCheck.h"
#include "misc/ExplicitConstructorCheck.h"
#include "gtest/gtest.h"
using namespace clang::tidy::google;
using namespace clang::tidy::misc;
// TODO: Deprecate this test file in favor of typical lit-tests to avoid
// cross-module dependencies.
namespace clang {
namespace tidy {
@ -16,8 +19,7 @@ TEST(ExplicitConstructorCheckTest, SingleArgumentConstructorsOnly) {
EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(C&&); };");
EXPECT_NO_CHANGES(ExplicitConstructorCheck,
"class C { C(const C&) = delete; };");
EXPECT_NO_CHANGES(ExplicitConstructorCheck,
"class C { C(int) = delete; };");
EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(int) = delete; };");
}
TEST(ExplicitConstructorCheckTest, Basic) {