[clang-tools-extra] r222878 - [clang-tidy] Support initializer_list in google-explicit-constructor check
Alexander Kornienko
alexfh at google.com
Thu Nov 27 03:11:47 PST 2014
Author: alexfh
Date: Thu Nov 27 05:11:47 2014
New Revision: 222878
URL: http://llvm.org/viewvc/llvm-project?rev=222878&view=rev
Log:
[clang-tidy] Support initializer_list in google-explicit-constructor check
Summary:
According to the Google C++ Style Guide, constructors taking a single
std::initializer_list<> should not be marked explicit.
This change also changes the messages according to conventions used in Clang
diagnostics: no capitalization of the first letter, no trailing dot.
Reviewers: djasper
Reviewed By: djasper
Subscribers: curdeius, cfe-commits
Differential Revision: http://reviews.llvm.org/D6427
Added:
clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/deduplication.cpp
clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp
clang-tools-extra/trunk/test/clang-tidy/file-filter.cpp
clang-tools-extra/trunk/test/clang-tidy/line-filter.cpp
clang-tools-extra/trunk/test/clang-tidy/macros.cpp
clang-tools-extra/trunk/test/clang-tidy/nolint.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=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/google/ExplicitConstructorCheck.cpp Thu Nov 27 05:11:47 2014
@@ -47,15 +47,33 @@ SourceRange FindToken(const SourceManage
return SourceRange();
}
+bool isStdInitializerList(QualType Type) {
+ if (const RecordType *RT = Type.getCanonicalType()->getAs<RecordType>()) {
+ if (ClassTemplateSpecializationDecl *Specialization =
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl())) {
+ ClassTemplateDecl *Template = Specialization->getSpecializedTemplate();
+ // First use the fast getName() method to avoid unnecessary calls to the
+ // slow getQualifiedNameAsString().
+ return Template->getName() == "initializer_list" &&
+ Template->getQualifiedNameAsString() == "std::initializer_list";
+ }
+ }
+ return false;
+}
+
void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
const CXXConstructorDecl *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.
- if (Ctor->isOutOfLine() || Ctor->isImplicit() || Ctor->isDeleted())
+ if (Ctor->isOutOfLine() || Ctor->isImplicit() || Ctor->isDeleted() ||
+ Ctor->getNumParams() == 0 || Ctor->getMinRequiredArguments() > 1)
return;
- if (Ctor->isExplicit() && Ctor->isCopyOrMoveConstructor()) {
+ bool takesInitializerList = isStdInitializerList(
+ Ctor->getParamDecl(0)->getType().getNonReferenceType());
+ if (Ctor->isExplicit() &&
+ (Ctor->isCopyOrMoveConstructor() || takesInitializerList)) {
auto isKWExplicit = [](const Token &Tok) {
return Tok.is(tok::raw_identifier) &&
Tok.getRawIdentifier() == "explicit";
@@ -63,21 +81,31 @@ void ExplicitConstructorCheck::check(con
SourceRange ExplicitTokenRange =
FindToken(*Result.SourceManager, Result.Context->getLangOpts(),
Ctor->getOuterLocStart(), Ctor->getLocEnd(), isKWExplicit);
+ StringRef ConstructorDescription;
+ if (Ctor->isMoveConstructor())
+ ConstructorDescription = "move";
+ else if (Ctor->isCopyConstructor())
+ ConstructorDescription = "copy";
+ else
+ ConstructorDescription = "initializer-list";
+
DiagnosticBuilder Diag =
- diag(Ctor->getLocation(), "%0 constructor declared explicit.")
- << (Ctor->isMoveConstructor() ? "Move" : "Copy");
+ diag(Ctor->getLocation(),
+ "%0 constructor should not be declared explicit")
+ << ConstructorDescription;
if (ExplicitTokenRange.isValid()) {
Diag << FixItHint::CreateRemoval(
CharSourceRange::getCharRange(ExplicitTokenRange));
}
+ return;
}
if (Ctor->isExplicit() || Ctor->isCopyOrMoveConstructor() ||
- Ctor->getNumParams() == 0 || Ctor->getMinRequiredArguments() > 1)
+ takesInitializerList)
return;
SourceLocation Loc = Ctor->getLocation();
- diag(Loc, "Single-argument constructors must be explicit")
+ diag(Loc, "single-argument constructors must be explicit")
<< FixItHint::CreateInsertion(Loc, "explicit ");
}
Modified: clang-tools-extra/trunk/test/clang-tidy/deduplication.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/deduplication.cpp?rev=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/deduplication.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/deduplication.cpp Thu Nov 27 05:11:47 2014
@@ -2,7 +2,7 @@
template<typename T>
struct A { A(T); };
-// CHECK: :[[@LINE-1]]:12: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK: :[[@LINE-1]]:12: warning: single-argument constructors must be explicit [google-explicit-constructor]
// CHECK-NOT: warning:
Modified: clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp?rev=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp Thu Nov 27 05:11:47 2014
@@ -14,8 +14,8 @@
// CHECK3: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value
int a = 1.5;
-// CHECK2: :[[@LINE+2]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
-// CHECK3: :[[@LINE+1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK2: :[[@LINE+2]]:11: warning: single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK3: :[[@LINE+1]]:11: warning: single-argument constructors must be explicit [google-explicit-constructor]
class A { A(int) {} };
// CHECK2-NOT: warning:
Modified: clang-tools-extra/trunk/test/clang-tidy/file-filter.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/file-filter.cpp?rev=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/file-filter.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/file-filter.cpp Thu Nov 27 05:11:47 2014
@@ -5,27 +5,27 @@
#include "header1.h"
// CHECK-NOT: warning:
-// CHECK2: header1.h:1:12: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK2: header1.h:1:12: warning: single-argument constructors must be explicit [google-explicit-constructor]
// CHECK3-NOT: warning:
-// CHECK4: header1.h:1:12: warning: Single-argument constructors
+// CHECK4: header1.h:1:12: warning: single-argument constructors
#include "header2.h"
// CHECK-NOT: warning:
-// CHECK2: header2.h:1:12: warning: Single-argument constructors
-// CHECK3: header2.h:1:12: warning: Single-argument constructors
-// CHECK4: header2.h:1:12: warning: Single-argument constructors
+// CHECK2: header2.h:1:12: warning: single-argument constructors
+// CHECK3: header2.h:1:12: warning: single-argument constructors
+// CHECK4: header2.h:1:12: warning: single-argument constructors
#include <system-header.h>
// CHECK-NOT: warning:
// CHECK2-NOT: warning:
// CHECK3-NOT: warning:
-// CHECK4: system-header.h:1:12: warning: Single-argument constructors
+// CHECK4: system-header.h:1:12: warning: single-argument constructors
class A { A(int); };
-// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors
-// CHECK2: :[[@LINE-2]]:11: warning: Single-argument constructors
-// CHECK3: :[[@LINE-3]]:11: warning: Single-argument constructors
-// CHECK4: :[[@LINE-4]]:11: warning: Single-argument constructors
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors
+// CHECK2: :[[@LINE-2]]:11: warning: single-argument constructors
+// CHECK3: :[[@LINE-3]]:11: warning: single-argument constructors
+// CHECK4: :[[@LINE-4]]:11: warning: single-argument constructors
// CHECK-NOT: warning:
// CHECK2-NOT: warning:
Added: 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=222878&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/google-explicit-constructor.cpp Thu Nov 27 05:11:47 2014
@@ -0,0 +1,59 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s google-explicit-constructor %t
+// REQUIRES: shell
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
+struct A {
+ A() {}
+ A(int x, int y) {}
+ A(std::initializer_list<int> list1) {}
+
+ explicit A(void *x) {}
+ explicit A(void *x, void *y) {}
+
+ explicit A(const A& a) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: copy constructor should not be declared explicit [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}A(const A& a) {}
+
+ explicit A(std::initializer_list<double> list2) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: initializer-list constructor should not be declared explicit [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}A(std::initializer_list<double> list2) {}
+
+ A(int x1) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be explicit [google-explicit-constructor]
+ // CHECK-FIXES: {{^ }}explicit A(int x1) {}
+
+ A(double x2, double y = 3.14) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: single-argument constructors must be explicit
+ // CHECK-FIXES: {{^ }}explicit A(double x2, double y = 3.14) {}
+};
Modified: clang-tools-extra/trunk/test/clang-tidy/line-filter.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/line-filter.cpp?rev=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/line-filter.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/line-filter.cpp Thu Nov 27 05:11:47 2014
@@ -2,25 +2,25 @@
#include "header1.h"
// CHECK-NOT: header1.h:{{.*}} warning
-// CHECK: header1.h:1:12: warning: Single-argument constructors must be explicit [google-explicit-constructor]
-// CHECK: header1.h:2:12: warning: Single-argument constructors {{.*}}
+// CHECK: header1.h:1:12: warning: single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK: header1.h:2:12: warning: single-argument constructors {{.*}}
// CHECK-NOT: header1.h:{{.*}} warning
#include "header2.h"
-// CHECK: header2.h:1:12: warning: Single-argument constructors {{.*}}
-// CHECK: header2.h:2:12: warning: Single-argument constructors {{.*}}
-// CHECK: header2.h:3:12: warning: Single-argument constructors {{.*}}
+// CHECK: header2.h:1:12: warning: single-argument constructors {{.*}}
+// CHECK: header2.h:2:12: warning: single-argument constructors {{.*}}
+// CHECK: header2.h:3:12: warning: single-argument constructors {{.*}}
// CHECK-NOT: header2.h:{{.*}} warning
#include "header3.h"
// CHECK-NOT: header3.h:{{.*}} warning
class A { A(int); };
-// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors {{.*}}
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors {{.*}}
class B { B(int); };
// CHECK-NOT: :[[@LINE-1]]:{{.*}} warning
class C { C(int); };
-// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors {{.*}}
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors {{.*}}
// CHECK-NOT: warning:
Modified: clang-tools-extra/trunk/test/clang-tidy/macros.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/macros.cpp?rev=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/macros.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/macros.cpp Thu Nov 27 05:11:47 2014
@@ -3,5 +3,5 @@
#define Q(name) class name { name(int i); }
Q(A);
-// CHECK: :[[@LINE-1]]:3: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK: :[[@LINE-1]]:3: warning: single-argument constructors must be explicit [google-explicit-constructor]
// CHECK: :3:30: note: expanded from macro 'Q'
Modified: clang-tools-extra/trunk/test/clang-tidy/nolint.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/nolint.cpp?rev=222878&r1=222877&r2=222878&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/nolint.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/nolint.cpp Thu Nov 27 05:11:47 2014
@@ -1,11 +1,11 @@
// RUN: clang-tidy -checks='-*,google-explicit-constructor' %s -- 2>&1 | FileCheck %s
class A { A(int i); };
-// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors must be explicit [google-explicit-constructor]
class B { B(int i); }; // NOLINT
-// CHECK-NOT: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK-NOT: :[[@LINE-1]]:11: warning: single-argument constructors must be explicit [google-explicit-constructor]
class C { C(int i); }; // NOLINT(we-dont-care-about-categories-yet)
-// CHECK-NOT: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK-NOT: :[[@LINE-1]]:11: warning: single-argument constructors must be explicit [google-explicit-constructor]
// CHECK: Suppressed 2 warnings (2 NOLINT)
More information about the cfe-commits
mailing list