[clang-tools-extra] r290434 - [clang-tidy] Flag implicit conversion operators.
Alexander Kornienko via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 23 07:03:12 PST 2016
Author: alexfh
Date: Fri Dec 23 09:03:12 2016
New Revision: 290434
URL: http://llvm.org/viewvc/llvm-project?rev=290434&view=rev
Log:
[clang-tidy] Flag implicit conversion operators.
Modified:
clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/google-explicit-constructor.rst
clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp
Modified: clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp?rev=290434&r1=290433&r2=290434&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp Fri Dec 23 09:03:12 2016
@@ -22,9 +22,12 @@ namespace google {
void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) {
// Only register the matchers for C++; the functionality currently does not
// provide any benefit to other languages, despite being benign.
- if (getLangOpts().CPlusPlus)
- Finder->addMatcher(
- cxxConstructorDecl(unless(isInstantiated())).bind("ctor"), this);
+ if (!getLangOpts().CPlusPlus)
+ return;
+ Finder->addMatcher(cxxConstructorDecl(unless(isInstantiated())).bind("ctor"),
+ this);
+ Finder->addMatcher(cxxConversionDecl(unless(isExplicit())).bind("conversion"),
+ this);
}
// Looks for the token matching the predicate and returns the range of the found
@@ -75,6 +78,17 @@ static bool isStdInitializerList(QualTyp
}
void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
+ constexpr char WarningMessage[] =
+ "%0 must be marked explicit to avoid unintentional implicit conversions";
+
+ if (const auto *Conversion =
+ Result.Nodes.getNodeAs<CXXConversionDecl>("conversion")) {
+ SourceLocation Loc = Conversion->getLocation();
+ diag(Loc, WarningMessage)
+ << Conversion << FixItHint::CreateInsertion(Loc, "explicit ");
+ return;
+ }
+
const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
// Do not be confused: isExplicit means 'explicit' keyword is present,
// isImplicit means that it's a compiler-generated constructor.
@@ -101,10 +115,9 @@ void ExplicitConstructorCheck::check(con
else
ConstructorDescription = "initializer-list";
- DiagnosticBuilder Diag =
- diag(Ctor->getLocation(),
- "%0 constructor should not be declared explicit")
- << ConstructorDescription;
+ auto Diag = diag(Ctor->getLocation(),
+ "%0 constructor should not be declared explicit")
+ << ConstructorDescription;
if (ExplicitTokenRange.isValid()) {
Diag << FixItHint::CreateRemoval(
CharSourceRange::getCharRange(ExplicitTokenRange));
@@ -119,8 +132,7 @@ void ExplicitConstructorCheck::check(con
bool SingleArgument =
Ctor->getNumParams() == 1 && !Ctor->getParamDecl(0)->isParameterPack();
SourceLocation Loc = Ctor->getLocation();
- diag(Loc,
- "%0 must be marked explicit to avoid unintentional implicit conversions")
+ diag(Loc, WarningMessage)
<< (SingleArgument
? "single-argument constructors"
: "constructors that are callable with a single argument")
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=290434&r1=290433&r2=290434&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Fri Dec 23 09:03:12 2016
@@ -183,6 +183,10 @@ Improvements to clang-tidy
<http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-string-cstr.html>`_ check
now warns about redundant calls to data() too.
+- The `google-explicit-constructor
+ <http://clang.llvm.org/extra/clang-tidy/checks/google-explicit-constructor.html>`_ check
+ now warns about conversion operators not marked explicit.
+
Fixed bugs:
- `modernize-make-unique
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/google-explicit-constructor.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/google-explicit-constructor.rst?rev=290434&r1=290433&r2=290434&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/google-explicit-constructor.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/google-explicit-constructor.rst Fri Dec 23 09:03:12 2016
@@ -4,6 +4,53 @@ google-explicit-constructor
===========================
-Checks that all single-argument constructors are explicit.
+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;
+ ...
+
+
See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors
Modified: clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp?rev=290434&r1=290433&r2=290434&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp Fri Dec 23 09:03:12 2016
@@ -38,6 +38,7 @@ struct A {
explicit A(void *x) {}
explicit A(void *x, void *y) {}
+ explicit operator bool() const { return true; }
explicit A(const A& a) {}
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor]
@@ -62,6 +63,10 @@ struct B {
B(const std::initializer_list<unsigned> &list2) {}
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-FIXES: {{^ }}explicit operator bool() const { return true; }
+
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-FIXES: {{^ }}B(::std::initializer_list<double> list4) {}
More information about the cfe-commits
mailing list