forked from OSchip/llvm-project
[clang-tidy] modernize-loop-convert: impl const cast iter
Summary: modernize-loop-convert was not detecting implicit casts to const_iterator as convertible to range-based loops: std::vector<int> vec{1,2,3,4} for(std::vector<int>::const_iterator i = vec.begin(); i != vec.end(); ++i) { } Thanks to Don Hinton for advice. As well, this change adds a note for this check's applicability to code targeting OpenMP prior to version 5 as this check will continue breaking compilation with `-fopenmp`. Thanks to Roman Lebedev for pointing this out. Fixes PR#35082 Reviewed By: hintonda Tags: #clang-tools-extra, #clang Differential Revision: https://reviews.llvm.org/D61827 llvm-svn: 360785
This commit is contained in:
parent
6ebb785bb1
commit
42d28be802
|
@ -791,11 +791,6 @@ bool LoopConvertCheck::isConvertible(ASTContext *Context,
|
||||||
CanonicalBeginType->getPointeeType(),
|
CanonicalBeginType->getPointeeType(),
|
||||||
CanonicalInitVarType->getPointeeType()))
|
CanonicalInitVarType->getPointeeType()))
|
||||||
return false;
|
return false;
|
||||||
} else if (!Context->hasSameType(CanonicalInitVarType,
|
|
||||||
CanonicalBeginType)) {
|
|
||||||
// Check for qualified types to avoid conversions from non-const to const
|
|
||||||
// iterator types.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} else if (FixerKind == LFK_PseudoArray) {
|
} else if (FixerKind == LFK_PseudoArray) {
|
||||||
// This call is required to obtain the container.
|
// This call is required to obtain the container.
|
||||||
|
|
|
@ -253,3 +253,15 @@ below ends up being performed at the `safe` level.
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpenMP
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
As range-based for loops are only available since OpenMP 5, this check should
|
||||||
|
not been used on code with a compatibility requirements of OpenMP prior to
|
||||||
|
version 5. It is **intentional** that this check does not make any attempts to
|
||||||
|
exclude incorrect diagnostics on OpenMP for loops prior to OpenMP 5.
|
||||||
|
|
||||||
|
To prevent this check to be applied (and to break) OpenMP for loops but still be
|
||||||
|
applied to non-OpenMP for loops the usage of ``NOLINT`` (see
|
||||||
|
:ref:`clang-tidy-nolint`) on the specific for loops is recommended.
|
||||||
|
|
|
@ -258,6 +258,8 @@ An overview of all the command-line options:
|
||||||
value: 'some value'
|
value: 'some value'
|
||||||
...
|
...
|
||||||
|
|
||||||
|
.. _clang-tidy-nolint:
|
||||||
|
|
||||||
Suppressing Undesired Diagnostics
|
Suppressing Undesired Diagnostics
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ void f() {
|
||||||
// CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
|
// CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This container uses an iterator where the derefence type is a typedef of
|
// This container uses an iterator where the dereference type is a typedef of
|
||||||
// a reference type. Make sure non-const auto & is still used. A failure here
|
// a reference type. Make sure non-const auto & is still used. A failure here
|
||||||
// means canonical types aren't being tested.
|
// means canonical types aren't being tested.
|
||||||
{
|
{
|
||||||
|
@ -431,19 +431,22 @@ void different_type() {
|
||||||
// CHECK-FIXES: for (auto P : *Ps)
|
// CHECK-FIXES: for (auto P : *Ps)
|
||||||
// CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
|
// CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
|
||||||
|
|
||||||
// V.begin() returns a user-defined type 'iterator' which, since it's
|
|
||||||
// different from const_iterator, disqualifies these loops from
|
|
||||||
// transformation.
|
|
||||||
dependent<int> V;
|
dependent<int> V;
|
||||||
for (dependent<int>::const_iterator It = V.begin(), E = V.end();
|
for (dependent<int>::const_iterator It = V.begin(), E = V.end();
|
||||||
It != E; ++It) {
|
It != E; ++It) {
|
||||||
printf("Fibonacci number is %d\n", *It);
|
printf("Fibonacci number is %d\n", *It);
|
||||||
}
|
}
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int It : V)
|
||||||
|
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
|
||||||
|
|
||||||
for (dependent<int>::const_iterator It(V.begin()), E = V.end();
|
for (dependent<int>::const_iterator It(V.begin()), E = V.end();
|
||||||
It != E; ++It) {
|
It != E; ++It) {
|
||||||
printf("Fibonacci number is %d\n", *It);
|
printf("Fibonacci number is %d\n", *It);
|
||||||
}
|
}
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int It : V)
|
||||||
|
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests to ensure that an implicit 'this' is picked up as the container.
|
// Tests to ensure that an implicit 'this' is picked up as the container.
|
||||||
|
|
|
@ -776,17 +776,20 @@ void different_type() {
|
||||||
// CHECK-FIXES: for (auto P : *Ps)
|
// CHECK-FIXES: for (auto P : *Ps)
|
||||||
// CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
|
// CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
|
||||||
|
|
||||||
// V.begin() returns a user-defined type 'iterator' which, since it's
|
|
||||||
// different from const_iterator, disqualifies these loops from
|
|
||||||
// transformation.
|
|
||||||
dependent<int> V;
|
dependent<int> V;
|
||||||
for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {
|
for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {
|
||||||
printf("Fibonacci number is %d\n", *It);
|
printf("Fibonacci number is %d\n", *It);
|
||||||
}
|
}
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int It : V)
|
||||||
|
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
|
||||||
|
|
||||||
for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {
|
for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {
|
||||||
printf("Fibonacci number is %d\n", *It);
|
printf("Fibonacci number is %d\n", *It);
|
||||||
}
|
}
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int It : V)
|
||||||
|
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SingleIterator
|
} // namespace SingleIterator
|
||||||
|
@ -991,18 +994,26 @@ void iterators() {
|
||||||
// CHECK-FIXES: for (int & I : Dep)
|
// CHECK-FIXES: for (int & I : Dep)
|
||||||
// CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
|
// CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
|
||||||
|
|
||||||
// FIXME: It doesn't work with const iterators.
|
|
||||||
for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
|
for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
auto H3 = [I]() { int R = *I; };
|
auto H3 = [I]() { int R = *I; };
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int I : Dep)
|
||||||
|
// CHECK-FIXES-NEXT: auto H3 = [&I]() { int R = I; };
|
||||||
|
|
||||||
for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
|
for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
auto H4 = [&]() { int R = *I + 1; };
|
auto H4 = [&]() { int R = *I + 1; };
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int I : Dep)
|
||||||
|
// CHECK-FIXES-NEXT: auto H4 = [&]() { int R = I + 1; };
|
||||||
|
|
||||||
for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
|
for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
auto H5 = [=]() { int R = *I; };
|
auto H5 = [=]() { int R = *I; };
|
||||||
|
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
|
||||||
|
// CHECK-FIXES: for (int R : Dep)
|
||||||
|
// CHECK-FIXES-NEXT: auto H5 = [=]() { };
|
||||||
}
|
}
|
||||||
|
|
||||||
void captureByValue() {
|
void captureByValue() {
|
||||||
|
|
Loading…
Reference in New Issue