[clang-tools-extra] r334400 - Add support for arrays in performance-implicit-conversion-in-loop
Alexander Kornienko via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 11 05:46:48 PDT 2018
Author: alexfh
Date: Mon Jun 11 05:46:48 2018
New Revision: 334400
URL: http://llvm.org/viewvc/llvm-project?rev=334400&view=rev
Log:
Add support for arrays in performance-implicit-conversion-in-loop
Summary:
Add support for arrays (and structure that use naked pointers for their iterator, like std::array) in performance-implicit-conversion-in-loop
Reviewers: alexfh
Reviewed By: alexfh
Subscribers: cfe-commits
Patch by Alex Pilkiewicz.
Differential Revision: https://reviews.llvm.org/D47945
Modified:
clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.h
clang-tools-extra/trunk/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
Modified: clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp?rev=334400&r1=334399&r2=334400&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp Mon Jun 11 05:46:48 2018
@@ -28,7 +28,7 @@ namespace performance {
static bool IsNonTrivialImplicitCast(const Stmt *ST) {
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(ST)) {
return (ICE->getCastKind() != CK_NoOp) ||
- IsNonTrivialImplicitCast(ICE->getSubExpr());
+ IsNonTrivialImplicitCast(ICE->getSubExpr());
}
return false;
}
@@ -39,7 +39,9 @@ void ImplicitConversionInLoopCheck::regi
// conversion. The check on the implicit conversion is done in check() because
// we can't access implicit conversion subnode via matchers: has() skips casts
// and materialize! We also bind on the call to operator* to get the proper
- // type in the diagnostic message.
+ // type in the diagnostic message. We use both cxxOperatorCallExpr for user
+ // defined operator and unaryOperator when the iterator is a pointer, like
+ // for arrays or std::array.
//
// Note that when the implicit conversion is done through a user defined
// conversion operator, the node is a CXXMemberCallExpr, not a
@@ -47,10 +49,14 @@ void ImplicitConversionInLoopCheck::regi
// cxxOperatorCallExpr() matcher.
Finder->addMatcher(
cxxForRangeStmt(hasLoopVariable(
- varDecl(hasType(qualType(references(qualType(isConstQualified())))),
- hasInitializer(expr(hasDescendant(cxxOperatorCallExpr().bind(
- "operator-call")))
- .bind("init")))
+ varDecl(
+ hasType(qualType(references(qualType(isConstQualified())))),
+ hasInitializer(
+ expr(anyOf(hasDescendant(
+ cxxOperatorCallExpr().bind("operator-call")),
+ hasDescendant(unaryOperator(hasOperatorName("*"))
+ .bind("operator-call"))))
+ .bind("init")))
.bind("faulty-var"))),
this);
}
@@ -60,7 +66,7 @@ void ImplicitConversionInLoopCheck::chec
const auto *VD = Result.Nodes.getNodeAs<VarDecl>("faulty-var");
const auto *Init = Result.Nodes.getNodeAs<Expr>("init");
const auto *OperatorCall =
- Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator-call");
+ Result.Nodes.getNodeAs<Expr>("operator-call");
if (const auto *Cleanup = dyn_cast<ExprWithCleanups>(Init))
Init = Cleanup->getSubExpr();
@@ -79,7 +85,7 @@ void ImplicitConversionInLoopCheck::chec
void ImplicitConversionInLoopCheck::ReportAndFix(
const ASTContext *Context, const VarDecl *VD,
- const CXXOperatorCallExpr *OperatorCall) {
+ const Expr *OperatorCall) {
// We only match on const ref, so we should print a const ref version of the
// type.
QualType ConstType = OperatorCall->getType().withConst();
Modified: clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.h?rev=334400&r1=334399&r2=334400&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.h (original)
+++ clang-tools-extra/trunk/clang-tidy/performance/ImplicitConversionInLoopCheck.h Mon Jun 11 05:46:48 2018
@@ -28,7 +28,7 @@ public:
private:
void ReportAndFix(const ASTContext *Context, const VarDecl *VD,
- const CXXOperatorCallExpr *OperatorCall);
+ const Expr *OperatorCall);
};
} // namespace performance
Modified: clang-tools-extra/trunk/test/clang-tidy/performance-implicit-conversion-in-loop.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-implicit-conversion-in-loop.cpp?rev=334400&r1=334399&r2=334400&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/performance-implicit-conversion-in-loop.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/performance-implicit-conversion-in-loop.cpp Mon Jun 11 05:46:48 2018
@@ -40,7 +40,7 @@ class ImplicitWrapper {
template <typename T>
class OperatorWrapper {
public:
- explicit OperatorWrapper(const T& t);
+ OperatorWrapper() = delete;
};
struct SimpleClass {
@@ -101,7 +101,7 @@ void ImplicitSimpleClassIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the loop variable 'foo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const SimpleClass &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop]
// for (ImplicitWrapper<SimpleClass>& foo : SimpleView()) {}
for (const ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
- for (ImplicitWrapper<SimpleClass>foo : SimpleView()) {}
+ for (ImplicitWrapper<SimpleClass> foo : SimpleView()) {}
}
void ImplicitSimpleClassRefIterator() {
@@ -109,7 +109,16 @@ void ImplicitSimpleClassRefIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (ImplicitWrapper<SimpleClass>& foo : SimpleRefView()) {}
for (const ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
- for (ImplicitWrapper<SimpleClass>foo : SimpleRefView()) {}
+ for (ImplicitWrapper<SimpleClass> foo : SimpleRefView()) {}
+}
+
+void ImplicitSimpleClassArray() {
+ SimpleClass array[5];
+ for (const ImplicitWrapper<SimpleClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (ImplicitWrapper<SimpleClass>& foo : array) {}
+ for (const ImplicitWrapper<SimpleClass> foo : array) {}
+ for (ImplicitWrapper<SimpleClass> foo : array) {}
}
void ImplicitComplexClassIterator() {
@@ -117,15 +126,24 @@ void ImplicitComplexClassIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (ImplicitWrapper<ComplexClass>& foo : ComplexView()) {}
for (const ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
- for (ImplicitWrapper<ComplexClass>foo : ComplexView()) {}
+ for (ImplicitWrapper<ComplexClass> foo : ComplexView()) {}
}
void ImplicitComplexClassRefIterator() {
+ ComplexClass array[5];
+ for (const ImplicitWrapper<ComplexClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (ImplicitWrapper<ComplexClass>& foo : array) {}
+ for (const ImplicitWrapper<ComplexClass> foo : array) {}
+ for (ImplicitWrapper<ComplexClass> foo : array) {}
+}
+
+void ImplicitComplexClassArray() {
for (const ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (ImplicitWrapper<ComplexClass>& foo : ComplexRefView()) {}
for (const ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
- for (ImplicitWrapper<ComplexClass>foo : ComplexRefView()) {}
+ for (ImplicitWrapper<ComplexClass> foo : ComplexRefView()) {}
}
void OperatorSimpleClassIterator() {
@@ -133,7 +151,7 @@ void OperatorSimpleClassIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (OperatorWrapper<SimpleClass>& foo : SimpleView()) {}
for (const OperatorWrapper<SimpleClass> foo : SimpleView()) {}
- for (OperatorWrapper<SimpleClass>foo : SimpleView()) {}
+ for (OperatorWrapper<SimpleClass> foo : SimpleView()) {}
}
void OperatorSimpleClassRefIterator() {
@@ -141,7 +159,16 @@ void OperatorSimpleClassRefIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
// for (OperatorWrapper<SimpleClass>& foo : SimpleRefView()) {}
for (const OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
- for (OperatorWrapper<SimpleClass>foo : SimpleRefView()) {}
+ for (OperatorWrapper<SimpleClass> foo : SimpleRefView()) {}
+}
+
+void OperatorSimpleClassArray() {
+ SimpleClass array[5];
+ for (const OperatorWrapper<SimpleClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const SimpleClass &'.*}}
+ // for (OperatorWrapper<SimpleClass>& foo : array) {}
+ for (const OperatorWrapper<SimpleClass> foo : array) {}
+ for (OperatorWrapper<SimpleClass> foo : array) {}
}
void OperatorComplexClassIterator() {
@@ -149,7 +176,7 @@ void OperatorComplexClassIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (OperatorWrapper<ComplexClass>& foo : ComplexView()) {}
for (const OperatorWrapper<ComplexClass> foo : ComplexView()) {}
- for (OperatorWrapper<ComplexClass>foo : ComplexView()) {}
+ for (OperatorWrapper<ComplexClass> foo : ComplexView()) {}
}
void OperatorComplexClassRefIterator() {
@@ -157,5 +184,14 @@ void OperatorComplexClassRefIterator() {
// CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
// for (OperatorWrapper<ComplexClass>& foo : ComplexRefView()) {}
for (const OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
- for (OperatorWrapper<ComplexClass>foo : ComplexRefView()) {}
+ for (OperatorWrapper<ComplexClass> foo : ComplexRefView()) {}
+}
+
+void OperatorComplexClassArray() {
+ ComplexClass array[5];
+ for (const OperatorWrapper<ComplexClass>& foo : array) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:{{[0-9]*}}: warning: the type of the{{.*'const ComplexClass &'.*}}
+ // for (OperatorWrapper<ComplexClass>& foo : array) {}
+ for (const OperatorWrapper<ComplexClass> foo : array) {}
+ for (OperatorWrapper<ComplexClass> foo : array) {}
}
More information about the cfe-commits
mailing list