From: Don Hinton Date: Wed, 15 May 2019 17:47:51 +0000 (+0000) Subject: [clang-tidy] Recommit r360785 "modernize-loop-convert: impl const cast iter" with... X-Git-Tag: llvmorg-10-init~5478 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4c50e64fc5cf945c77dd0396bd969fdbdab83e4e;p=platform%2Fupstream%2Fllvm.git [clang-tidy] Recommit r360785 "modernize-loop-convert: impl const cast iter" with correct attribution Summary: modernize-loop-convert was not detecting implicit casts to const_iterator as convertible to range-based loops: std::vector vec{1,2,3,4} for(std::vector::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 --- diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index f9e941c..0e59a88 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -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. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst index bad574f..82b27bb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-loop-convert.rst @@ -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. diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst index 1b5af60..dc186b6 100644 --- a/clang-tools-extra/docs/clang-tidy/index.rst +++ b/clang-tools-extra/docs/clang-tidy/index.rst @@ -258,6 +258,8 @@ An overview of all the command-line options: value: 'some value' ... +.. _clang-tidy-nolint: + Suppressing Undesired Diagnostics ================================= diff --git a/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp b/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp index def7c4b..0cd1087 100644 --- a/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp +++ b/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp @@ -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. { @@ -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 V; for (dependent::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::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. diff --git a/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp b/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp index b46ff25..d7011f7 100644 --- a/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp +++ b/clang-tools-extra/test/clang-tidy/modernize-loop-convert-extra.cpp @@ -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 V; for (dependent::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::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 @@ -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::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::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::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() {