Skip to content

Commit

Permalink
[clang-tidy] Recommit r360785 "modernize-loop-convert: impl const cas…
Browse files Browse the repository at this point in the history
…t iter" with correct attribution

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 version 5 as this check will continue breaking
compilation with `-fopenmp`. Thanks to Roman Lebedev for pointing this
out.

Fixes PR#35082

Patch by Torbjörn Klatt!

Reviewed By: hintonda

Tags: #clang-tools-extra, #clang

Differential Revision: https://reviews.llvm.org/D61827

llvm-svn: 360788
  • Loading branch information
donhinton committed May 15, 2019
1 parent 4ecb581 commit 4c50e64
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 13 deletions.
5 changes: 0 additions & 5 deletions clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -791,11 +791,6 @@ bool LoopConvertCheck::isConvertible(ASTContext *Context,
CanonicalBeginType->getPointeeType(),
CanonicalInitVarType->getPointeeType()))
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) {
// This call is required to obtain the container.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,15 @@ below ends up being performed at the `safe` level.
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.
2 changes: 2 additions & 0 deletions clang-tools-extra/docs/clang-tidy/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ An overview of all the command-line options:
value: 'some value'
...
.. _clang-tidy-nolint:

Suppressing Undesired Diagnostics
=================================

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ void f() {
// 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
// means canonical types aren't being tested.
{
Expand Down Expand Up @@ -431,19 +431,22 @@ void different_type() {
// CHECK-FIXES: for (auto P : *Ps)
// 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;
for (dependent<int>::const_iterator It = V.begin(), E = V.end();
It != E; ++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();
It != E; ++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.
Expand Down
19 changes: 15 additions & 4 deletions clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -776,17 +776,20 @@ void different_type() {
// CHECK-FIXES: for (auto P : *Ps)
// 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;
for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++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) {
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
Expand Down Expand Up @@ -991,18 +994,26 @@ void iterators() {
// CHECK-FIXES: for (int & I : Dep)
// 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();
I != E; ++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();
I != E; ++I)
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();
I != E; ++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() {
Expand Down

0 comments on commit 4c50e64

Please sign in to comment.