Files
acceptance-tests
data
debian
docs
external
Newtonsoft.Json
api-doc-tools
api-snapshot
aspnetwebstack
bdwgc
binary-reference-assemblies
bockbuild
boringssl
cecil
cecil-legacy
corefx
corert
helix-binaries
ikdasm
ikvm
illinker-test-assets
linker
llvm-project
clang
clang-tools-extra
change-namespace
clang-apply-replacements
clang-move
clang-query
clang-reorder-fields
clang-tidy
clang-tidy-vs
clangd
docs
include-fixer
modularize
pp-trace
test
Unit
change-namespace
clang-apply-replacements
clang-move
clang-query
clang-reorder-fields
clang-tidy
Inputs
android-cloexec-accept.cpp
android-cloexec-accept4.cpp
android-cloexec-creat.cpp
android-cloexec-dup.cpp
android-cloexec-epoll-create.cpp
android-cloexec-epoll-create1.cpp
android-cloexec-fopen.cpp
android-cloexec-inotify-init.cpp
android-cloexec-inotify-init1.cpp
android-cloexec-memfd-create.cpp
android-cloexec-open.cpp
android-cloexec-socket.cpp
basic.cpp
boost-use-to-string.cpp
bugprone-argument-comment-gmock.cpp
bugprone-argument-comment-strict.cpp
bugprone-argument-comment.cpp
bugprone-assert-side-effect.cpp
bugprone-bool-pointer-implicit-conversion.cpp
bugprone-copy-constructor-init.cpp
bugprone-dangling-handle.cpp
bugprone-fold-init-type.cpp
bugprone-forward-declaration-namespace.cpp
bugprone-inaccurate-erase.cpp
bugprone-integer-division.cpp
bugprone-misplaced-operator-in-strlen-in-alloc.c
bugprone-misplaced-operator-in-strlen-in-alloc.cpp
bugprone-move-forwarding-reference.cpp
bugprone-multiple-statement-macro.cpp
bugprone-string-constructor.cpp
bugprone-suspicious-memset-usage.cpp
bugprone-undefined-memory-manipulation.cpp
bugprone-use-after-move.cpp
bugprone-virtual-near-miss.cpp
cert-dcl21-cpp.cpp
cert-dcl58-cpp.cpp
cert-env33-c.c
cert-err34-c.c
cert-err34-c.cpp
cert-flp30-c.c
cert-limited-randomness.c
cert-limited-randomness.cpp
cert-oop11-cpp.cpp
cert-setlongjmp.cpp
cert-static-object-exception.cpp
cert-throw-exception-type.cpp
cert-variadic-function-def.cpp
check_clang_tidy.py
clang-tidy-diff.cpp
clang-tidy-run-with-database.cpp
clean-up-code.cpp
config-files.cpp
cppcoreguidelines-interfaces-global-init.cpp
cppcoreguidelines-no-malloc-custom.cpp
cppcoreguidelines-no-malloc-no-functions.cpp
cppcoreguidelines-no-malloc.cpp
cppcoreguidelines-owning-memory-containers.cpp
cppcoreguidelines-owning-memory-legacy-functions.cpp
cppcoreguidelines-owning-memory.cpp
cppcoreguidelines-pro-bounds-array-to-pointer-decay.cpp
cppcoreguidelines-pro-bounds-constant-array-index-c++03.cpp
cppcoreguidelines-pro-bounds-constant-array-index-gslheader.cpp
cppcoreguidelines-pro-bounds-constant-array-index.cpp
cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp
cppcoreguidelines-pro-type-const-cast.cpp
cppcoreguidelines-pro-type-cstyle-cast.cpp
cppcoreguidelines-pro-type-member-init-cxx98.cpp
cppcoreguidelines-pro-type-member-init-delayed.cpp
cppcoreguidelines-pro-type-member-init.cpp
cppcoreguidelines-pro-type-reinterpret-cast.cpp
cppcoreguidelines-pro-type-static-cast-downcast.cpp
cppcoreguidelines-pro-type-union-access.cpp
cppcoreguidelines-pro-type-vararg.cpp
cppcoreguidelines-slicing.cpp
cppcoreguidelines-special-member-functions-cxx-03.cpp
cppcoreguidelines-special-member-functions-relaxed.cpp
cppcoreguidelines-special-member-functions.cpp
custom-diagnostics.cpp
deduplication.cpp
diagnostic.cpp
explain-checks.cpp
extra-args.cpp
file-filter.cpp
fix-errors.cpp
fix.cpp
fuchsia-default-arguments.cpp
fuchsia-overloaded-operator.cpp
fuchsia-virtual-inheritance.cpp
google-build-explicit-make-pair.cpp
google-default-arguments.cpp
google-explicit-constructor.cpp
google-module.cpp
google-namespaces.cpp
google-objc-avoid-throwing-exception.m
google-objc-global-variable-declaration.m
google-overloaded-unary-and.cpp
google-readability-casting.c
google-readability-casting.cpp
google-readability-namespace-comments.cpp
google-readability-todo.cpp
google-runtime-int-std.cpp
google-runtime-int.c
google-runtime-int.cpp
google-runtime-member-string-references.cpp
google-runtime-references.cpp
hicpp-exception-baseclass.cpp
hicpp-no-assembler-msvc.cpp
hicpp-no-assembler.cpp
hicpp-signed-bitwise-bug34747.cpp
hicpp-signed-bitwise-standard-types.cpp
hicpp-signed-bitwise-standard-types.h
hicpp-signed-bitwise.cpp
line-filter.cpp
list-checks.cpp
llvm-include-order.cpp
llvm-twine-local.cpp
macros.cpp
misc-definitions-in-headers-1z.hpp
misc-definitions-in-headers.hpp
misc-forwarding-reference-overload.cpp
misc-incorrect-roundings.cpp
misc-lambda-function-name.cpp
misc-macro-parentheses-cmdline.cpp
misc-macro-parentheses.cpp
misc-macro-repeated-side-effects.c
misc-misplaced-const.c
misc-misplaced-const.cpp
misc-misplaced-widening-cast-explicit-only.cpp
misc-misplaced-widening-cast-implicit-enabled.cpp
misc-new-delete-overloads-sized-dealloc.cpp
misc-new-delete-overloads.cpp
misc-non-copyable-objects.c
misc-non-copyable-objects.cpp
misc-redundant-expression.cpp
misc-sizeof-container.cpp
misc-sizeof-expression.cpp
misc-static-assert.c
misc-static-assert.cpp
misc-string-compare.cpp
misc-string-integer-assignment.cpp
misc-string-literal-with-embedded-nul.cpp
misc-suspicious-enum-usage-strict.cpp
misc-suspicious-enum-usage.cpp
misc-suspicious-missing-comma.cpp
misc-suspicious-semicolon-fail.cpp
misc-suspicious-semicolon.cpp
misc-suspicious-string-compare.c
misc-suspicious-string-compare.cpp
misc-swapped-arguments.cpp
misc-throw-by-value-catch-by-reference.cpp
misc-unconventional-assign-operator.cpp
misc-undelegated-constructor-cxx98.cpp
misc-undelegated-constructor.cpp
misc-uniqueptr-reset-release.cpp
misc-unused-alias-decls.cpp
misc-unused-parameters.c
misc-unused-parameters.cpp
misc-unused-raii.cpp
misc-unused-using-decls-errors.cpp
misc-unused-using-decls.cpp
modernize-avoid-bind.cpp
modernize-deprecated-headers-cxx03.cpp
modernize-deprecated-headers-cxx11.cpp
modernize-loop-convert-assert-failure.cpp
modernize-loop-convert-basic.cpp
modernize-loop-convert-camelback.cpp
modernize-loop-convert-const.cpp
modernize-loop-convert-extra.cpp
modernize-loop-convert-lowercase.cpp
modernize-loop-convert-negative.cpp
modernize-loop-convert-uppercase.cpp
modernize-loop-convert.c
modernize-make-shared-header.cpp
modernize-make-shared.cpp
modernize-make-unique-header.cpp
modernize-make-unique-macros.cpp
modernize-make-unique.cpp
modernize-pass-by-value-header.cpp
modernize-pass-by-value-macro-header.cpp
modernize-pass-by-value-multi-fixes.cpp
modernize-pass-by-value.cpp
modernize-raw-string-literal-delimiter.cpp
modernize-raw-string-literal-replace-shorter.cpp
modernize-raw-string-literal.cpp
modernize-redundant-void-arg-delayed.cpp
modernize-redundant-void-arg.c
modernize-redundant-void-arg.cpp
modernize-replace-auto-ptr.cpp
modernize-replace-random-shuffle.cpp
modernize-return-braced-init-list.cpp
modernize-shrink-to-fit.cpp
modernize-unary-static-assert.cpp
modernize-use-auto-cast-remove-stars.cpp
modernize-use-auto-cast.cpp
modernize-use-auto-iterator.cpp
modernize-use-auto-new-remove-stars.cpp
modernize-use-auto-new.cpp
modernize-use-bool-literals-ignore-macros.cpp
modernize-use-bool-literals.cpp
modernize-use-default-member-init-assignment.cpp
modernize-use-default-member-init-macros.cpp
modernize-use-default-member-init.cpp
modernize-use-emplace-ignore-implicit-constructors.cpp
modernize-use-emplace.cpp
modernize-use-equals-default-copy.cpp
modernize-use-equals-default-delayed.cpp
modernize-use-equals-default-macros.cpp
modernize-use-equals-default.cpp
modernize-use-equals-delete.cpp
modernize-use-noexcept-macro.cpp
modernize-use-noexcept-opt.cpp
modernize-use-noexcept.cpp
modernize-use-nullptr-basic.cpp
modernize-use-nullptr.c
modernize-use-nullptr.cpp
modernize-use-override-cxx98.cpp
modernize-use-override-ms.cpp
modernize-use-override.cpp
modernize-use-transparent-functors.cpp
modernize-use-using-macros.cpp
modernize-use-using.cpp
mpi-buffer-deref.cpp
mpi-type-mismatch.cpp
nolint.cpp
nolintnextline.cpp
nonstandard-file-extension.test
objc-arc-and-properties.m
objc-avoid-nserror-init.m
objc-avoid-spinlock.m
objc-forbidden-subclassing-custom.m
objc-forbidden-subclassing.m
objc-no-arc-or-properties.m
objc-property-declaration-custom.m
objc-property-declaration.m
overlapping.cpp
performance-faster-string-find.cpp
performance-for-range-copy-warn-on-all-auto-copies.cpp
performance-for-range-copy.cpp
performance-implicit-conversion-in-loop.cpp
performance-inefficient-algorithm.cpp
performance-inefficient-string-concatenation.cpp
performance-inefficient-vector-operation.cpp
performance-move-const-arg-trivially-copyable.cpp
performance-move-const-arg.cpp
performance-move-constructor-init.cpp
performance-noexcept-move-constructor.cpp
performance-type-promotion-in-math-fn.cpp
performance-unnecessary-copy-initialization.cpp
performance-unnecessary-value-param-delayed.cpp
performance-unnecessary-value-param-header.cpp
performance-unnecessary-value-param-incomplete-type.cpp
performance-unnecessary-value-param.cpp
readability-avoid-const-params-in-decls.cpp
readability-braces-around-statements-assert-failure.cpp
readability-braces-around-statements-few-lines.cpp
readability-braces-around-statements-format.cpp
readability-braces-around-statements-same-line.cpp
readability-braces-around-statements-single-line.cpp
readability-braces-around-statements.cpp
readability-container-size-empty.cpp
readability-delete-null-pointer.cpp
readability-deleted-default.cpp
readability-else-after-return.cpp
readability-function-size.cpp
readability-identifier-naming.cpp
readability-implicit-bool-conversion-allow-in-conditions.cpp
readability-implicit-bool-conversion-cxx98.cpp
readability-implicit-bool-conversion.cpp
readability-inconsistent-declaration-parameter-name.cpp
readability-misleading-indentation.cpp
readability-misplaced-array-index.cpp
readability-named-parameter.cpp
readability-non-const-parameter.cpp
readability-redundant-control-flow.cpp
readability-redundant-declaration-ignore-macros.cpp
readability-redundant-declaration.cpp
readability-redundant-function-ptr-dereference.cpp
readability-redundant-member-init.cpp
readability-redundant-smartptr-get.cpp
readability-redundant-string-cstr-msvc.cpp
readability-redundant-string-cstr.cpp
readability-redundant-string-init-msvc.cpp
readability-redundant-string-init.cpp
readability-simplify-bool-expr-chained-conditional-assignment.cpp
readability-simplify-bool-expr-chained-conditional-return.cpp
readability-simplify-bool-expr.cpp
readability-static-accessed-through-instance-nesting-threshold.cpp
readability-static-accessed-through-instance.cpp
readability-static-definition-in-anonymous-namespace.cpp
readability-uniqueptr-delete-release.cpp
select-checks.cpp
serialize-diagnostics.cpp
static-analyzer-config.cpp
static-analyzer.cpp
temporaries.cpp
validate-check-names.cpp
werrors-diagnostics.cpp
werrors-plural.cpp
werrors.cpp
clangd
include-fixer
modularize
pp-trace
.clang-format
CMakeLists.txt
lit.cfg
lit.site.cfg.in
tool-template
unittests
.arcconfig
.gitignore
CMakeLists.txt
CODE_OWNERS.TXT
LICENSE.TXT
README.txt
compiler-rt
libcxx
libcxxabi
libunwind
lld
lldb
llvm
openmp
polly
nuget-buildtasks
nunit-lite
roslyn-binaries
rx
xunit-binaries
how-to-bump-roslyn-binaries.md
ikvm-native
llvm
m4
man
mcs
mk
mono
msvc
netcore
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
linux-packaging-mono/external/llvm-project/clang-tools-extra/test/clang-tidy/modernize-loop-convert-basic.cpp
Xamarin Public Jenkins (auto-signing) 468663ddbb Imported Upstream version 6.10.0.49
Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
2020-01-16 16:38:04 +00:00

794 lines
26 KiB
C++

// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
#include "structures.h"
namespace Array {
const int N = 6;
const int NMinusOne = N - 1;
int Arr[N] = {1, 2, 3, 4, 5, 6};
const int ConstArr[N] = {1, 2, 3, 4, 5, 6};
int (*PArr)[N] = &Arr;
void f() {
int Sum = 0;
for (int I = 0; I < N; ++I) {
Sum += Arr[I];
int K;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert]
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: Sum += I;
// CHECK-FIXES-NEXT: int K;
for (int I = 0; I < N; ++I) {
printf("Fibonacci number is %d\n", Arr[I]);
Sum += Arr[I] + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
// CHECK-FIXES-NEXT: Sum += I + 2;
for (int I = 0; I < N; ++I) {
int X = Arr[I];
int Y = Arr[I] + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: int X = I;
// CHECK-FIXES-NEXT: int Y = I + 2;
for (int I = 0; I < N; ++I) {
int X = N;
X = Arr[I];
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: int X = N;
// CHECK-FIXES-NEXT: X = I;
for (int I = 0; I < N; ++I) {
Arr[I] += 1;
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int & I : Arr)
// CHECK-FIXES-NEXT: I += 1;
for (int I = 0; I < N; ++I) {
int X = Arr[I] + 2;
Arr[I]++;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int & I : Arr)
// CHECK-FIXES-NEXT: int X = I + 2;
// CHECK-FIXES-NEXT: I++;
for (int I = 0; I < N; ++I) {
Arr[I] = 4 + Arr[I];
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int & I : Arr)
// CHECK-FIXES-NEXT: I = 4 + I;
for (int I = 0; I < NMinusOne + 1; ++I) {
Sum += Arr[I];
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: Sum += I;
for (int I = 0; I < N; ++I) {
printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
Sum += Arr[I] + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int & I : Arr)
// CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
// CHECK-FIXES-NEXT: Sum += I + 2;
Val Teas[N];
for (int I = 0; I < N; ++I) {
Teas[I].g();
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & Tea : Teas)
// CHECK-FIXES-NEXT: Tea.g();
}
const int *constArray() {
for (int I = 0; I < N; ++I) {
printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : ConstArr)
// CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
const NonTriviallyCopyable NonCopy[N]{};
for (int I = 0; I < N; ++I) {
printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & I : NonCopy)
// CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
const TriviallyCopyableButBig Big[N]{};
for (int I = 0; I < N; ++I) {
printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & I : Big)
// CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
bool Something = false;
for (int I = 0; I < N; ++I) {
if (Something)
return &ConstArr[I];
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const int & I : ConstArr)
// CHECK-FIXES-NEXT: if (Something)
// CHECK-FIXES-NEXT: return &I;
}
struct HasArr {
int Arr[N];
Val ValArr[N];
void implicitThis() {
for (int I = 0; I < N; ++I) {
printf("%d", Arr[I]);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: printf("%d", I);
for (int I = 0; I < N; ++I) {
printf("%d", ValArr[I].X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : ValArr)
// CHECK-FIXES-NEXT: printf("%d", I.X);
}
void explicitThis() {
for (int I = 0; I < N; ++I) {
printf("%d", this->Arr[I]);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : this->Arr)
// CHECK-FIXES-NEXT: printf("%d", I);
for (int I = 0; I < N; ++I) {
printf("%d", this->ValArr[I].X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : this->ValArr)
// CHECK-FIXES-NEXT: printf("%d", I.X);
}
};
struct HasIndirectArr {
HasArr HA;
void implicitThis() {
for (int I = 0; I < N; ++I) {
printf("%d", HA.Arr[I]);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : HA.Arr)
// CHECK-FIXES-NEXT: printf("%d", I);
for (int I = 0; I < N; ++I) {
printf("%d", HA.ValArr[I].X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : HA.ValArr)
// CHECK-FIXES-NEXT: printf("%d", I.X);
}
void explicitThis() {
for (int I = 0; I < N; ++I) {
printf("%d", this->HA.Arr[I]);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : this->HA.Arr)
// CHECK-FIXES-NEXT: printf("%d", I);
for (int I = 0; I < N; ++I) {
printf("%d", this->HA.ValArr[I].X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : this->HA.ValArr)
// CHECK-FIXES-NEXT: printf("%d", I.X);
}
};
// Loops whose bounds are value-dependent should not be converted.
template <int N>
void dependentExprBound() {
for (int I = 0; I < N; ++I)
Arr[I] = 0;
}
template void dependentExprBound<20>();
void memberFunctionPointer() {
Val V;
void (Val::*mfpArr[N])(void) = {&Val::g};
for (int I = 0; I < N; ++I)
(V.*mfpArr[I])();
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : mfpArr)
// CHECK-FIXES-NEXT: (V.*I)();
struct Foo {
int (Val::*f)();
} Foo[N];
for (int I = 0; I < N; ++I)
int R = (V.*(Foo[I].f))();
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : Foo)
// CHECK-FIXES-NEXT: int R = (V.*(I.f))();
}
} // namespace Array
namespace Iterator {
void f() {
/// begin()/end() - based for loops here:
T Tt;
for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
printf("I found %d\n", *It);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int & It : Tt)
// CHECK-FIXES-NEXT: printf("I found %d\n", It);
T *Pt;
for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
printf("I found %d\n", *It);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int & It : *Pt)
// CHECK-FIXES-NEXT: printf("I found %d\n", It);
S Ss;
for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
printf("s has value %d\n", (*It).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Ss)
// CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
S *Ps;
for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
printf("s has value %d\n", (*It).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & P : *Ps)
// CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
printf("s has value %d\n", (*It).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto It : Ss)
// CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
printf("s has value %d\n", It->X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Ss)
// CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
It->X = 3;
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Ss)
// CHECK-FIXES-NEXT: It.X = 3;
for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
(*It).X = 3;
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Ss)
// CHECK-FIXES-NEXT: It.X = 3;
for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
It->nonConstFun(4, 5);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Ss)
// CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
U Uu;
for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
printf("s has value %d\n", It->X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Uu)
// CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
printf("s has value %d\n", (*It).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Uu)
// CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
Val* a = It.operator->();
}
U::iterator A;
for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
int K = A->X + I->X;
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : Uu)
// CHECK-FIXES-NEXT: int K = A->X + I.X;
dependent<int> V;
for (dependent<int>::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>::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);
doublyDependent<int, int> Intmap;
for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
It != E; ++It) {
printf("Intmap[%d] = %d", It->first, It->second);
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & It : Intmap)
// CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
// PtrSet's iterator dereferences by value so auto & can't be used.
{
PtrSet<int *> Val_int_ptrs;
for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
E = Val_int_ptrs.end();
I != E; ++I) {
(void) *I;
}
// CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
}
// This container uses an iterator where the derefence 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.
{
TypedefDerefContainer<int> Int_ptrs;
for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
E = Int_ptrs.end();
I != E; ++I) {
(void) *I;
}
// CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
}
{
// Iterators returning an rvalue reference should disqualify the loop from
// transformation.
RValueDerefContainer<int> Container;
for (RValueDerefContainer<int>::iterator I = Container.begin(),
E = Container.end();
I != E; ++I) {
(void) *I;
}
}
dependent<Val *> Dpp;
for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
printf("%d\n", (**I).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : Dpp)
// CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
printf("%d\n", (*I)->X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : Dpp)
// CHECK-FIXES-NEXT: printf("%d\n", I->X);
}
// Tests to verify the proper use of auto where the init variable type and the
// initializer type differ or are mostly the same except for const qualifiers.
void different_type() {
// Ss.begin() returns a type 'iterator' which is just a non-const pointer and
// differs from const_iterator only on the const qualification.
S Ss;
for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
printf("s has value %d\n", (*It).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto It : Ss)
// CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
S *Ps;
for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
printf("s has value %d\n", (*It).X);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// 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);
}
for (dependent<int>::const_iterator It(V.begin()), E = V.end();
It != E; ++It) {
printf("Fibonacci number is %d\n", *It);
}
}
// Tests to ensure that an implicit 'this' is picked up as the container.
// If member calls are made to 'this' within the loop, the transform becomes
// risky as these calls may affect state that affects the loop.
class C {
public:
typedef MutableVal *iterator;
typedef const MutableVal *const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
void doSomething();
void doSomething() const;
void doLoop() {
for (iterator I = begin(), E = end(); I != E; ++I)
(void) *I;
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : *this)
for (iterator I = C::begin(), E = C::end(); I != E; ++I)
(void) *I;
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : *this)
for (iterator I = begin(), E = end(); I != E; ++I) {
(void) *I;
doSomething();
}
for (iterator I = begin(); I != end(); ++I)
(void) *I;
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : *this)
for (iterator I = begin(); I != end(); ++I) {
(void) *I;
doSomething();
}
}
void doLoop() const {
for (const_iterator I = begin(), E = end(); I != E; ++I)
(void) *I;
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto I : *this)
for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
(void) *I;
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto I : *this)
for (const_iterator I = begin(), E = end(); I != E; ++I) {
(void) *I;
doSomething();
}
}
};
class C2 {
public:
typedef MutableVal *iterator;
iterator begin() const;
iterator end() const;
void doLoop() {
// The implicit 'this' will have an Implicit cast to const C2* wrapped
// around it. Make sure the replacement still happens.
for (iterator I = begin(), E = end(); I != E; ++I)
(void) *I;
// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : *this)
}
};
} // namespace Iterator
namespace PseudoArray {
const int N = 6;
dependent<int> V;
dependent<int> *Pv;
const dependent<NonTriviallyCopyable> Constv;
const dependent<NonTriviallyCopyable> *Pconstv;
transparent<dependent<int>> Cv;
void f() {
int Sum = 0;
for (int I = 0, E = V.size(); I < E; ++I) {
printf("Fibonacci number is %d\n", V[I]);
Sum += V[I] + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : V)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
// CHECK-FIXES-NEXT: Sum += I + 2;
for (int I = 0, E = V.size(); I < E; ++I) {
printf("Fibonacci number is %d\n", V.at(I));
Sum += V.at(I) + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : V)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
// CHECK-FIXES-NEXT: Sum += I + 2;
for (int I = 0, E = Pv->size(); I < E; ++I) {
printf("Fibonacci number is %d\n", Pv->at(I));
Sum += Pv->at(I) + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : *Pv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
// CHECK-FIXES-NEXT: Sum += I + 2;
// This test will fail if size() isn't called repeatedly, since it
// returns unsigned int, and 0 is deduced to be signed int.
// FIXME: Insert the necessary explicit conversion, or write out the types
// explicitly.
for (int I = 0; I < Pv->size(); ++I) {
printf("Fibonacci number is %d\n", (*Pv).at(I));
Sum += (*Pv)[I] + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : *Pv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
// CHECK-FIXES-NEXT: Sum += I + 2;
for (int I = 0; I < Cv->size(); ++I) {
printf("Fibonacci number is %d\n", Cv->at(I));
Sum += Cv->at(I) + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : *Cv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
// CHECK-FIXES-NEXT: Sum += I + 2;
}
// Ensure that 'const auto &' is used with containers of non-trivial types.
void constness() {
int Sum = 0;
for (int I = 0, E = Constv.size(); I < E; ++I) {
printf("Fibonacci number is %d\n", Constv[I].X);
Sum += Constv[I].X + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & I : Constv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
// CHECK-FIXES-NEXT: Sum += I.X + 2;
for (int I = 0, E = Constv.size(); I < E; ++I) {
printf("Fibonacci number is %d\n", Constv.at(I).X);
Sum += Constv.at(I).X + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & I : Constv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
// CHECK-FIXES-NEXT: Sum += I.X + 2;
for (int I = 0, E = Pconstv->size(); I < E; ++I) {
printf("Fibonacci number is %d\n", Pconstv->at(I).X);
Sum += Pconstv->at(I).X + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & I : *Pconstv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
// CHECK-FIXES-NEXT: Sum += I.X + 2;
// This test will fail if size() isn't called repeatedly, since it
// returns unsigned int, and 0 is deduced to be signed int.
// FIXME: Insert the necessary explicit conversion, or write out the types
// explicitly.
for (int I = 0; I < Pconstv->size(); ++I) {
printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
Sum += (*Pconstv)[I].X + 2;
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & I : *Pconstv)
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
// CHECK-FIXES-NEXT: Sum += I.X + 2;
}
void constRef(const dependent<int>& ConstVRef) {
int sum = 0;
// FIXME: This does not work with size_t (probably due to the implementation
// of dependent); make dependent work exactly like a std container type.
for (int I = 0; I < ConstVRef.size(); ++I) {
sum += ConstVRef[I];
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : ConstVRef)
// CHECK-FIXES-NEXT: sum += I;
for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
sum += *I;
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (int I : ConstVRef)
// CHECK-FIXES-NEXT: sum += I;
}
// Check for loops that don't mention containers.
void noContainer() {
for (auto I = 0; I < V.size(); ++I) {
}
for (auto I = 0; I < V.size(); ++I)
;
}
struct NoBeginEnd {
unsigned size() const;
unsigned& operator[](int);
const unsigned& operator[](int) const;
};
struct NoConstBeginEnd {
NoConstBeginEnd();
unsigned size() const;
unsigned* begin();
unsigned* end();
unsigned& operator[](int);
const unsigned& operator[](int) const;
};
struct ConstBeginEnd {
ConstBeginEnd();
unsigned size() const;
unsigned* begin() const;
unsigned* end() const;
unsigned& operator[](int);
const unsigned& operator[](int) const;
};
// Shouldn't transform pseudo-array uses if the container doesn't provide
// begin() and end() of the right const-ness.
void NoBeginEndTest() {
NoBeginEnd NBE;
for (unsigned I = 0, E = NBE.size(); I < E; ++I)
printf("%d\n", NBE[I]);
const NoConstBeginEnd Const_NCBE;
for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
printf("%d\n", Const_NCBE[I]);
ConstBeginEnd CBE;
for (unsigned I = 0, E = CBE.size(); I < E; ++I)
printf("%d\n", CBE[I]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (unsigned int I : CBE)
// CHECK-FIXES-NEXT: printf("%d\n", I);
const ConstBeginEnd Const_CBE;
for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
printf("%d\n", Const_CBE[I]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (unsigned int I : Const_CBE)
// CHECK-FIXES-NEXT: printf("%d\n", I);
}
struct DerefByValue {
DerefByValue();
struct iter { unsigned operator*(); };
unsigned size() const;
iter begin();
iter end();
unsigned operator[](int);
};
void derefByValueTest() {
DerefByValue DBV;
for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
printf("%d\n", DBV[I]);
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (unsigned int I : DBV)
// CHECK-FIXES-NEXT: printf("%d\n", I);
for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
auto f = [DBV, I]() {};
printf("%d\n", DBV[I]);
}
// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (unsigned int I : DBV)
// CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
// CHECK-FIXES-NEXT: printf("%d\n", I);
}
void fundamentalTypesTest() {
const int N = 10;
bool Bools[N];
for (int i = 0; i < N; ++i)
printf("%d", Bools[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (bool Bool : Bools)
int Ints[N];
unsigned short int Shorts[N];
for (int i = 0; i < N; ++i)
printf("%d", Shorts[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (unsigned short Short : Shorts)
signed long Longs[N];
for (int i = 0; i < N; ++i)
printf("%d", Longs[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (long Long : Longs)
long long int LongLongs[N];
for (int i = 0; i < N; ++i)
printf("%d", LongLongs[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (long long LongLong : LongLongs)
char Chars[N];
for (int i = 0; i < N; ++i)
printf("%d", Chars[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (char Char : Chars)
wchar_t WChars[N];
for (int i = 0; i < N; ++i)
printf("%d", WChars[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (wchar_t WChar : WChars)
float Floats[N];
for (int i = 0; i < N; ++i)
printf("%d", Floats[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (float Float : Floats)
double Doubles[N];
for (int i = 0; i < N; ++i)
printf("%d", Doubles[i]);
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (double Double : Doubles)
}
} // namespace PseudoArray