forked from OSchip/llvm-project
Add support for 'cbegin()' and 'cend()' on modernize-loop-convert.
Summary: This fixes https://llvm.org/bugs/show_bug.cgi?id=22196 . Also add a non-trivially copyable type to fix some tests that were meant to be about using const-refs, but were changed in r248438. Reviewers: klimek Subscribers: alexfh, cfe-commits Differential Revision: http://reviews.llvm.org/D13292 llvm-svn: 248994
This commit is contained in:
parent
7362982e62
commit
2bfb7cbddb
|
@ -112,8 +112,9 @@ StatementMatcher makeArrayLoopMatcher() {
|
|||
/// - If the end iterator variable 'g' is defined, it is the same as 'f'.
|
||||
StatementMatcher makeIteratorLoopMatcher() {
|
||||
StatementMatcher BeginCallMatcher =
|
||||
cxxMemberCallExpr(argumentCountIs(0),
|
||||
callee(cxxMethodDecl(hasName("begin"))))
|
||||
cxxMemberCallExpr(
|
||||
argumentCountIs(0),
|
||||
callee(cxxMethodDecl(anyOf(hasName("begin"), hasName("cbegin")))))
|
||||
.bind(BeginCallName);
|
||||
|
||||
DeclarationMatcher InitDeclMatcher =
|
||||
|
@ -127,7 +128,8 @@ StatementMatcher makeIteratorLoopMatcher() {
|
|||
varDecl(hasInitializer(anything())).bind(EndVarName);
|
||||
|
||||
StatementMatcher EndCallMatcher = cxxMemberCallExpr(
|
||||
argumentCountIs(0), callee(cxxMethodDecl(hasName("end"))));
|
||||
argumentCountIs(0),
|
||||
callee(cxxMethodDecl(anyOf(hasName("end"), hasName("cend")))));
|
||||
|
||||
StatementMatcher IteratorBoundMatcher =
|
||||
expr(anyOf(ignoringParenImpCasts(
|
||||
|
@ -296,7 +298,8 @@ static const Expr *getContainerFromBeginEndCall(const Expr *Init, bool IsBegin,
|
|||
return nullptr;
|
||||
StringRef Name = Member->getMemberDecl()->getName();
|
||||
StringRef TargetName = IsBegin ? "begin" : "end";
|
||||
if (Name != TargetName)
|
||||
StringRef ConstTargetName = IsBegin ? "cbegin" : "cend";
|
||||
if (Name != TargetName && Name != ConstTargetName)
|
||||
return nullptr;
|
||||
|
||||
const Expr *SourceExpr = Member->getBase();
|
||||
|
@ -423,7 +426,7 @@ void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
|||
Options.store(Opts, "MinConfidence", Confs[static_cast<int>(MinConfidence)]);
|
||||
|
||||
SmallVector<std::string, 4> Styles{"camelBack", "CamelCase", "lower_case",
|
||||
"UPPER_CASE"};
|
||||
"UPPER_CASE"};
|
||||
Options.store(Opts, "NamingStyle", Styles[static_cast<int>(NamingStyle)]);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,20 @@ struct MutableVal {
|
|||
int X;
|
||||
};
|
||||
|
||||
struct NonTriviallyCopyable {
|
||||
NonTriviallyCopyable() = default;
|
||||
// Define this constructor to make this class non-trivially copyable.
|
||||
NonTriviallyCopyable(const NonTriviallyCopyable& Ntc);
|
||||
int X;
|
||||
};
|
||||
|
||||
struct S {
|
||||
typedef MutableVal *iterator;
|
||||
typedef const MutableVal *const_iterator;
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
const_iterator cbegin() const;
|
||||
const_iterator cend() const;
|
||||
iterator begin();
|
||||
iterator end();
|
||||
};
|
||||
|
|
|
@ -104,6 +104,14 @@ void constArray() {
|
|||
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
|
||||
// CHECK-FIXES: for (auto Elem : ConstArr)
|
||||
// CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem, Elem + Elem);
|
||||
|
||||
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 & Elem : NonCopy)
|
||||
// CHECK-FIXES-NEXT: printf("2 * %d = %d\n", Elem.X, Elem.X + Elem.X);
|
||||
}
|
||||
|
||||
struct HasArr {
|
||||
|
@ -209,6 +217,13 @@ void f() {
|
|||
// 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 Elem : Ss)
|
||||
// CHECK-FIXES-NEXT: printf("s has value %d\n", Elem.X);
|
||||
|
||||
for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
|
||||
printf("s has value %d\n", It->X);
|
||||
}
|
||||
|
@ -459,8 +474,8 @@ namespace PseudoArray {
|
|||
const int N = 6;
|
||||
dependent<int> V;
|
||||
dependent<int> *Pv;
|
||||
const dependent<int> Constv;
|
||||
const dependent<int> *Pconstv;
|
||||
const dependent<NonTriviallyCopyable> Constv;
|
||||
const dependent<NonTriviallyCopyable> *Pconstv;
|
||||
|
||||
transparent<dependent<int>> Cv;
|
||||
|
||||
|
@ -516,50 +531,51 @@ void f() {
|
|||
// CHECK-FIXES-NEXT: Sum += Elem + 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]);
|
||||
Sum += Constv[I] + 2;
|
||||
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 (auto Elem : Constv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem + 2;
|
||||
// CHECK-FIXES: for (const auto & Elem : Constv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem.X + 2;
|
||||
|
||||
for (int I = 0, E = Constv.size(); I < E; ++I) {
|
||||
printf("Fibonacci number is %d\n", Constv.at(I));
|
||||
Sum += Constv.at(I) + 2;
|
||||
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 (auto Elem : Constv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem + 2;
|
||||
// CHECK-FIXES: for (const auto & Elem : Constv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem.X + 2;
|
||||
|
||||
for (int I = 0, E = Pconstv->size(); I < E; ++I) {
|
||||
printf("Fibonacci number is %d\n", Pconstv->at(I));
|
||||
Sum += Pconstv->at(I) + 2;
|
||||
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 (auto Elem : *Pconstv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem + 2;
|
||||
// CHECK-FIXES: for (const auto & Elem : *Pconstv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem.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));
|
||||
Sum += (*Pconstv)[I] + 2;
|
||||
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 (auto Elem : *Pconstv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem + 2;
|
||||
// CHECK-FIXES: for (const auto & Elem : *Pconstv)
|
||||
// CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem.X);
|
||||
// CHECK-FIXES-NEXT: Sum += Elem.X + 2;
|
||||
}
|
||||
|
||||
void ConstRef(const dependent<int>& ConstVRef) {
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue