Fix several corner cases for loop-convert check.

Summary: Reduced the amount of wrong conversions of this check.

Reviewers: klimek

Subscribers: alexfh, cfe-commits

Differential Revision: http://reviews.llvm.org/D12530

llvm-svn: 246550
This commit is contained in:
Angel Garcia Gomez 2015-09-01 15:05:15 +00:00
parent 7a9495bcd5
commit 692cbb5bb0
6 changed files with 334 additions and 217 deletions

View File

@ -364,6 +364,23 @@ static bool isDirectMemberExpr(const Expr *E) {
return false;
}
/// \brief Returns true when it can be guaranteed that the elements of the
/// container are not being modified.
static bool usagesAreConst(const UsageResult &Usages) {
// FIXME: Make this function more generic.
return Usages.empty();
}
/// \brief Returns true if the elements of the container are never accessed
/// by reference.
static bool usagesReturnRValues(const UsageResult &Usages) {
for (const auto &U : Usages) {
if (!U.Expression->isRValue())
return false;
}
return true;
}
LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo),
MinConfidence(StringSwitch<Confidence::Level>(
@ -452,7 +469,8 @@ void LoopConvertCheck::doConversion(
StringRef MaybeDereference = ContainerNeedsDereference ? "*" : "";
std::string TypeString = AutoRefType.getAsString();
std::string Range = ("(" + TypeString + " " + VarName + " : " +
MaybeDereference + ContainerString + ")").str();
MaybeDereference + ContainerString + ")")
.str();
Diag << FixItHint::CreateReplacement(
CharSourceRange::getTokenRange(ParenRange), Range);
TUInfo->getGeneratedDecls().insert(make_pair(TheLoop, VarName));
@ -464,7 +482,7 @@ void LoopConvertCheck::doConversion(
StringRef LoopConvertCheck::checkRejections(ASTContext *Context,
const Expr *ContainerExpr,
const ForStmt *TheLoop) {
// If we already modified the reange of this for loop, don't do any further
// If we already modified the range of this for loop, don't do any further
// updates on this iteration.
if (TUInfo->getReplacedVars().count(TheLoop))
return "";
@ -525,6 +543,18 @@ void LoopConvertCheck::findAndVerifyUsages(
if (!getReferencedVariable(ContainerExpr) &&
!isDirectMemberExpr(ContainerExpr))
ConfidenceLevel.lowerTo(Confidence::CL_Risky);
} else if (FixerKind == LFK_PseudoArray) {
if (!DerefByValue && !DerefByConstRef) {
const UsageResult &Usages = Finder.getUsages();
if (usagesAreConst(Usages)) {
// FIXME: check if the type is trivially copiable.
DerefByConstRef = true;
} else if (usagesReturnRValues(Usages)) {
// If the index usages (dereference, subscript, at) return RValues,
// then we should not use a non-const reference.
DerefByValue = true;
}
}
}
StringRef ContainerString = checkRejections(Context, ContainerExpr, TheLoop);

View File

@ -425,12 +425,8 @@ ForLoopIndexUseVisitor::ForLoopIndexUseVisitor(ASTContext *Context,
ConfidenceLevel(Confidence::CL_Safe), NextStmtParent(nullptr),
CurrStmtParent(nullptr), ReplaceWithAliasUse(false),
AliasFromForInit(false) {
if (ContainerExpr) {
if (ContainerExpr)
addComponent(ContainerExpr);
FoldingSetNodeID ID;
const Expr *E = ContainerExpr->IgnoreParenImpCasts();
E->Profile(ID, *Context, true);
}
}
bool ForLoopIndexUseVisitor::findAndVerifyUsages(const Stmt *Body) {
@ -521,7 +517,13 @@ bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
}
}
if (Member->isArrow() && Obj && exprReferencesVariable(IndexVar, Obj)) {
if (Obj && exprReferencesVariable(IndexVar, Obj)) {
// Member calls on the iterator with '.' are not allowed.
if (!Member->isArrow()) {
OnlyUsedAsIndex = false;
return true;
}
if (ExprType.isNull())
ExprType = Obj->getType();
@ -539,7 +541,7 @@ bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
return true;
}
}
return TraverseStmt(Member->getBase());
return VisitorBase::TraverseMemberExpr(Member);
}
/// \brief If a member function call is the at() accessor on the container with
@ -576,7 +578,7 @@ bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr(
}
/// \brief If an overloaded operator call is a dereference of IndexVar or
/// a subscript of a the container with IndexVar as the single argument,
/// a subscript of the container with IndexVar as the single argument,
/// include it as a valid usage and prune the traversal.
///
/// For example, given
@ -682,9 +684,6 @@ bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) {
/// i.insert(0);
/// for (vector<int>::iterator i = container.begin(), e = container.end();
/// i != e; ++i)
/// i.insert(0);
/// for (vector<int>::iterator i = container.begin(), e = container.end();
/// i != e; ++i)
/// if (i + 1 != e)
/// printf("%d", *i);
/// \endcode
@ -700,7 +699,9 @@ bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) {
/// \endcode
bool ForLoopIndexUseVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
const ValueDecl *TheDecl = E->getDecl();
if (areSameVariable(IndexVar, TheDecl) || areSameVariable(EndVar, TheDecl))
if (areSameVariable(IndexVar, TheDecl) ||
exprReferencesVariable(IndexVar, E) || areSameVariable(EndVar, TheDecl) ||
exprReferencesVariable(EndVar, E))
OnlyUsedAsIndex = false;
if (containsExpr(Context, &DependentExprs, E))
ConfidenceLevel.lowerTo(Confidence::CL_Risky);

View File

@ -197,14 +197,14 @@ private:
/// \brief The information needed to describe a valid convertible usage
/// of an array index or iterator.
struct Usage {
const Expr *E;
const Expr *Expression;
bool IsArrow;
SourceRange Range;
explicit Usage(const Expr *E)
: E(E), IsArrow(false), Range(E->getSourceRange()) {}
: Expression(E), IsArrow(false), Range(Expression->getSourceRange()) {}
Usage(const Expr *E, bool IsArrow, SourceRange Range)
: E(E), IsArrow(IsArrow), Range(std::move(Range)) {}
: Expression(E), IsArrow(IsArrow), Range(std::move(Range)) {}
};
/// \brief A class to encapsulate lowering of the tool's confidence level.

View File

@ -494,12 +494,12 @@ void noContainer() {
for (auto i = 0; i < v.size(); ++i) {
}
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & elem : v) {
// CHECK-FIXES: for (const auto & elem : v) {
for (auto i = 0; i < v.size(); ++i)
;
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & elem : v)
// CHECK-FIXES: for (const auto & elem : v)
}
struct NoBeginEnd {
@ -509,15 +509,15 @@ struct NoBeginEnd {
struct NoConstBeginEnd {
NoConstBeginEnd();
unsigned size() const;
unsigned begin();
unsigned end();
unsigned* begin();
unsigned* end();
};
struct ConstBeginEnd {
ConstBeginEnd();
unsigned size() const;
unsigned begin() const;
unsigned end() const;
unsigned* begin() const;
unsigned* end() const;
};
// Shouldn't transform pseudo-array uses if the container doesn't provide
@ -535,13 +535,32 @@ void NoBeginEndTest() {
for (unsigned i = 0, e = CBE.size(); i < e; ++i) {
}
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & elem : CBE) {
// CHECK-FIXES: for (const auto & elem : CBE) {
const ConstBeginEnd const_CBE;
for (unsigned i = 0, e = const_CBE.size(); i < e; ++i) {
}
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & elem : const_CBE) {
// CHECK-FIXES: for (const auto & elem : const_CBE) {
}
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 (auto && elem : DBV) {
}
} // namespace PseudoArray

View File

@ -387,6 +387,14 @@ void f() {
namespace Nesting {
void g(S::iterator it);
void const_g(S::const_iterator it);
class Foo {
public:
void g(S::iterator it);
void const_g(S::const_iterator it);
};
void f() {
const int N = 10;
const int M = 15;
@ -454,6 +462,48 @@ void f() {
// CHECK-FIXES: for (const auto & elem : NestS) {
// CHECK-FIXES-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI) {
// CHECK-FIXES-NEXT: printf("%d", *SI);
for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
const S &s = *I;
for (S::const_iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
printf("%d", *SI);
const_g(SI);
}
}
// CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & s : NestS) {
for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
S &s = *I;
for (S::iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
printf("%d", *SI);
g(SI);
}
}
// CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & s : NestS) {
Foo foo;
for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
const S &s = *I;
for (S::const_iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
printf("%d", *SI);
foo.const_g(SI);
}
}
// CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (const auto & s : NestS) {
for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
S &s = *I;
for (S::iterator SI = s.begin(), SE = s.end(); SI != SE; ++SI) {
printf("%d", *SI);
foo.g(SI);
}
}
// CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & s : NestS) {
}
} // namespace Nesting

View File

@ -3,91 +3,92 @@
#include "structures.h"
// CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
// CHECK-MESSAGES-NOT: modernize-loop-convert
namespace Negative {
const int N = 6;
int arr[N] = {1, 2, 3, 4, 5, 6};
int (*pArr)[N] = &arr;
int sum = 0;
int Sum = 0;
// Checks for the index start and end:
void indexStartAndEnd() {
for (int i = 0; i < N + 1; ++i)
sum += arr[i];
// Checks for the Index start and end:
void IndexStartAndEnd() {
for (int I = 0; I < N + 1; ++I)
Sum += arr[I];
for (int i = 0; i < N - 1; ++i)
sum += arr[i];
for (int I = 0; I < N - 1; ++I)
Sum += arr[I];
for (int i = 1; i < N; ++i)
sum += arr[i];
for (int I = 1; I < N; ++I)
Sum += arr[I];
for (int i = 1; i < N; ++i)
sum += arr[i];
for (int I = 1; I < N; ++I)
Sum += arr[I];
for (int i = 0;; ++i)
sum += (*pArr)[i];
for (int I = 0;; ++I)
Sum += (*pArr)[I];
}
// Checks for invalid increment steps:
void increment() {
for (int i = 0; i < N; --i)
sum += arr[i];
for (int I = 0; I < N; --I)
Sum += arr[I];
for (int i = 0; i < N; i)
sum += arr[i];
for (int I = 0; I < N; I)
Sum += arr[I];
for (int i = 0; i < N;)
sum += arr[i];
for (int I = 0; I < N;)
Sum += arr[I];
for (int i = 0; i < N; i += 2)
sum++;
for (int I = 0; I < N; I += 2)
Sum++;
}
// Checks to make sure that the index isn't used outside of the array:
void indexUse() {
for (int i = 0; i < N; ++i)
arr[i] += 1 + i;
// Checks to make sure that the Index isn't used outside of the array:
void IndexUse() {
for (int I = 0; I < N; ++I)
arr[I] += 1 + I;
}
// Check for loops that don't mention arrays
void noArray() {
for (int i = 0; i < N; ++i)
sum += i;
for (int I = 0; I < N; ++I)
Sum += I;
for (int i = 0; i < N; ++i) {
for (int I = 0; I < N; ++I) {
}
for (int i = 0; i < N; ++i)
for (int I = 0; I < N; ++I)
;
}
// Checks for incorrect loop variables.
void mixedVariables() {
int badIndex;
for (int i = 0; badIndex < N; ++i)
sum += arr[i];
for (int I = 0; badIndex < N; ++I)
Sum += arr[I];
for (int i = 0; i < N; ++badIndex)
sum += arr[i];
for (int I = 0; I < N; ++badIndex)
Sum += arr[I];
for (int i = 0; badIndex < N; ++badIndex)
sum += arr[i];
for (int I = 0; badIndex < N; ++badIndex)
Sum += arr[I];
for (int i = 0; badIndex < N; ++badIndex)
sum += arr[badIndex];
for (int I = 0; badIndex < N; ++badIndex)
Sum += arr[badIndex];
}
// Checks for multiple arrays indexed.
// Checks for multiple arrays Indexed.
void multipleArrays() {
int badArr[N];
for (int i = 0; i < N; ++i)
sum += arr[i] + badArr[i];
for (int I = 0; I < N; ++I)
Sum += arr[I] + badArr[I];
for (int i = 0; i < N; ++i) {
int k = badArr[i];
sum += arr[i] + k;
for (int I = 0; I < N; ++I) {
int K = badArr[I];
Sum += arr[I] + K;
}
}
@ -99,22 +100,22 @@ struct HasArr {
struct HasIndirectArr {
HasArr HA;
void implicitThis() {
for (int i = 0; i < N; ++i) {
printf("%d", HA.Arr[i]);
for (int I = 0; I < N; ++I) {
printf("%d", HA.Arr[I]);
}
for (int i = 0; i < N; ++i) {
printf("%d", HA.ValArr[i].x);
for (int I = 0; I < N; ++I) {
printf("%d", HA.ValArr[I].x);
}
}
void explicitThis() {
for (int i = 0; i < N; ++i) {
printf("%d", this->HA.Arr[i]);
for (int I = 0; I < N; ++I) {
printf("%d", this->HA.Arr[I]);
}
for (int i = 0; i < N; ++i) {
printf("%d", this->HA.ValArr[i].x);
for (int I = 0; I < N; ++I) {
printf("%d", this->HA.ValArr[I].x);
}
}
};
@ -133,38 +134,38 @@ struct BadBeginEnd : T {
void notBeginOrEnd() {
BadBeginEnd Bad;
for (T::iterator i = Bad.notBegin(), e = Bad.end(); i != e; ++i)
int k = *i;
for (T::iterator I = Bad.notBegin(), E = Bad.end(); I != E; ++I)
int K = *I;
for (T::iterator i = Bad.begin(), e = Bad.notEnd(); i != e; ++i)
int k = *i;
for (T::iterator I = Bad.begin(), E = Bad.notEnd(); I != E; ++I)
int K = *I;
}
void badLoopShapes() {
for (T::iterator i = t.begin(), e = t.end(), f = e; i != e; ++i)
int k = *i;
for (T::iterator I = t.begin(), E = t.end(), F = E; I != E; ++I)
int K = *I;
for (T::iterator i = t.begin(), e = t.end(); i != e;)
int k = *i;
for (T::iterator I = t.begin(), E = t.end(); I != E;)
int K = *I;
for (T::iterator i = t.begin(), e = t.end();; ++i)
int k = *i;
for (T::iterator I = t.begin(), E = t.end();; ++I)
int K = *I;
T::iterator outsideI;
T::iterator outsideE;
for (; outsideI != outsideE; ++outsideI)
int k = *outsideI;
int K = *outsideI;
}
void iteratorArrayMix() {
int lower;
const int N = 6;
for (T::iterator i = t.begin(), e = t.end(); lower < N; ++i)
int k = *i;
for (T::iterator I = t.begin(), E = t.end(); lower < N; ++I)
int K = *I;
for (T::iterator i = t.begin(), e = t.end(); lower < N; ++lower)
int k = *i;
for (T::iterator I = t.begin(), E = t.end(); lower < N; ++lower)
int K = *I;
}
struct ExtraConstructor : T::iterator {
@ -173,61 +174,77 @@ struct ExtraConstructor : T::iterator {
};
void badConstructor() {
for (T::iterator i = ExtraConstructor(t.begin(), 0), e = t.end();
i != e; ++i)
int k = *i;
for (T::iterator i = ExtraConstructor(t.begin()), e = t.end(); i != e; ++i)
int k = *i;
for (T::iterator I = ExtraConstructor(t.begin(), 0), E = t.end();
I != E; ++I)
int K = *I;
for (T::iterator I = ExtraConstructor(t.begin()), E = t.end(); I != E; ++I)
int K = *I;
}
void foo(S::iterator It) {}
class Foo {public: void bar(S::iterator It); };
Foo fo;
void iteratorUsed() {
for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
foo(I);
for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
fo.bar(I);
S::iterator Ret;
for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
Ret = I;
}
void iteratorMemberUsed() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
i.x = *i;
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
I.x = *I;
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
int k = i.x + *i;
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
int K = I.x + *I;
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
int k = e.x + *i;
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
int K = E.x + *I;
}
void iteratorMethodCalled() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
i.insert(3);
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
I.insert(3);
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
if (i != i)
int k = 3;
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
if (I != I)
int K = 3;
}
void iteratorOperatorCalled() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
int k = *(++i);
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
int K = *(++I);
for (S::iterator i = s.begin(), e = s.end(); i != e; ++i)
MutableVal k = *(++i);
for (S::iterator I = s.begin(), E = s.end(); I != E; ++I)
MutableVal K = *(++I);
}
void differentContainers() {
T other;
for (T::iterator i = t.begin(), e = other.end(); i != e; ++i)
int k = *i;
for (T::iterator I = t.begin(), E = other.end(); I != E; ++I)
int K = *I;
for (T::iterator i = other.begin(), e = t.end(); i != e; ++i)
int k = *i;
for (T::iterator I = other.begin(), E = t.end(); I != E; ++I)
int K = *I;
S otherS;
for (S::iterator i = s.begin(), e = otherS.end(); i != e; ++i)
MutableVal k = *i;
for (S::iterator I = s.begin(), E = otherS.end(); I != E; ++I)
MutableVal K = *I;
for (S::iterator i = otherS.begin(), e = s.end(); i != e; ++i)
MutableVal k = *i;
for (S::iterator I = otherS.begin(), E = s.end(); I != E; ++I)
MutableVal K = *I;
}
void wrongIterators() {
T::iterator other;
for (T::iterator i = t.begin(), e = t.end(); i != other; ++i)
int k = *i;
for (T::iterator I = t.begin(), E = t.end(); I != other; ++I)
int K = *I;
}
struct EvilArrow : U {
@ -237,10 +254,10 @@ struct EvilArrow : U {
void differentMemberAccessTypes() {
EvilArrow A;
for (EvilArrow::iterator i = A.begin(), e = A->end(); i != e; ++i)
Val k = *i;
for (EvilArrow::iterator i = A->begin(), e = A.end(); i != e; ++i)
Val k = *i;
for (EvilArrow::iterator I = A.begin(), E = A->end(); I != E; ++I)
Val K = *I;
for (EvilArrow::iterator I = A->begin(), E = A.end(); I != E; ++I)
Val K = *I;
}
void f(const T::iterator &it, int);
@ -248,21 +265,21 @@ void f(const T &it, int);
void g(T &it, int);
void iteratorPassedToFunction() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
f(i, *i);
for (T::iterator I = t.begin(), E = t.end(); I != E; ++I)
f(I, *I);
}
// FIXME: These tests can be removed if this tool ever does enough analysis to
// decide that this is a safe transformation. Until then, we don't want it
// applied.
void iteratorDefinedOutside() {
T::iterator theEnd = t.end();
for (T::iterator i = t.begin(); i != theEnd; ++i)
int k = *i;
T::iterator TheEnd = t.end();
for (T::iterator I = t.begin(); I != TheEnd; ++I)
int K = *I;
T::iterator theBegin = t.begin();
for (T::iterator e = t.end(); theBegin != e; ++theBegin)
int k = *theBegin;
T::iterator TheBegin = t.begin();
for (T::iterator E = t.end(); TheBegin != E; ++TheBegin)
int K = *TheBegin;
}
} // namespace NegativeIterator
@ -274,102 +291,102 @@ dependent<int> v;
dependent<int> *pv;
transparent<dependent<int>> cv;
int sum = 0;
int Sum = 0;
// Checks for the index start and end:
void indexStartAndEnd() {
for (int i = 0; i < v.size() + 1; ++i)
sum += v[i];
// Checks for the Index start and end:
void IndexStartAndEnd() {
for (int I = 0; I < v.size() + 1; ++I)
Sum += v[I];
for (int i = 0; i < v.size() - 1; ++i)
sum += v[i];
for (int I = 0; I < v.size() - 1; ++I)
Sum += v[I];
for (int i = 1; i < v.size(); ++i)
sum += v[i];
for (int I = 1; I < v.size(); ++I)
Sum += v[I];
for (int i = 1; i < v.size(); ++i)
sum += v[i];
for (int I = 1; I < v.size(); ++I)
Sum += v[I];
for (int i = 0;; ++i)
sum += (*pv)[i];
for (int I = 0;; ++I)
Sum += (*pv)[I];
}
// Checks for invalid increment steps:
void increment() {
for (int i = 0; i < v.size(); --i)
sum += v[i];
for (int I = 0; I < v.size(); --I)
Sum += v[I];
for (int i = 0; i < v.size(); i)
sum += v[i];
for (int I = 0; I < v.size(); I)
Sum += v[I];
for (int i = 0; i < v.size();)
sum += v[i];
for (int I = 0; I < v.size();)
Sum += v[I];
for (int i = 0; i < v.size(); i += 2)
sum++;
for (int I = 0; I < v.size(); I += 2)
Sum++;
}
// Checks to make sure that the index isn't used outside of the container:
void indexUse() {
for (int i = 0; i < v.size(); ++i)
v[i] += 1 + i;
// Checks to make sure that the Index isn't used outside of the container:
void IndexUse() {
for (int I = 0; I < v.size(); ++I)
v[I] += 1 + I;
}
// Checks for incorrect loop variables.
void mixedVariables() {
int badIndex;
for (int i = 0; badIndex < v.size(); ++i)
sum += v[i];
for (int I = 0; badIndex < v.size(); ++I)
Sum += v[I];
for (int i = 0; i < v.size(); ++badIndex)
sum += v[i];
for (int I = 0; I < v.size(); ++badIndex)
Sum += v[I];
for (int i = 0; badIndex < v.size(); ++badIndex)
sum += v[i];
for (int I = 0; badIndex < v.size(); ++badIndex)
Sum += v[I];
for (int i = 0; badIndex < v.size(); ++badIndex)
sum += v[badIndex];
for (int I = 0; badIndex < v.size(); ++badIndex)
Sum += v[badIndex];
}
// Checks for an array indexed in addition to the container.
// Checks for an array Indexed in addition to the container.
void multipleArrays() {
int badArr[N];
for (int i = 0; i < v.size(); ++i)
sum += v[i] + badArr[i];
for (int I = 0; I < v.size(); ++I)
Sum += v[I] + badArr[I];
for (int i = 0; i < v.size(); ++i)
sum += badArr[i];
for (int I = 0; I < v.size(); ++I)
Sum += badArr[I];
for (int i = 0; i < v.size(); ++i) {
int k = badArr[i];
sum += k + 2;
for (int I = 0; I < v.size(); ++I) {
int K = badArr[I];
Sum += K + 2;
}
for (int i = 0; i < v.size(); ++i) {
int k = badArr[i];
sum += v[i] + k;
for (int I = 0; I < v.size(); ++I) {
int K = badArr[I];
Sum += v[I] + K;
}
}
// Checks for multiple containers being indexed container.
// Checks for multiple containers being Indexed container.
void multipleContainers() {
dependent<int> badArr;
for (int i = 0; i < v.size(); ++i)
sum += v[i] + badArr[i];
for (int I = 0; I < v.size(); ++I)
Sum += v[I] + badArr[I];
for (int i = 0; i < v.size(); ++i)
sum += badArr[i];
for (int I = 0; I < v.size(); ++I)
Sum += badArr[I];
for (int i = 0; i < v.size(); ++i) {
int k = badArr[i];
sum += k + 2;
for (int I = 0; I < v.size(); ++I) {
int K = badArr[I];
Sum += K + 2;
}
for (int i = 0; i < v.size(); ++i) {
int k = badArr[i];
sum += v[i] + k;
for (int I = 0; I < v.size(); ++I) {
int K = badArr[I];
Sum += v[I] + K;
}
}
@ -377,31 +394,31 @@ void multipleContainers() {
void derefContainer() {
// Note the dependent<T>::operator*() returns another dependent<T>.
// This test makes sure that we don't allow an arbitrary number of *'s.
for (int i = 0; i < pv->size(); ++i)
sum += (**pv).at(i);
for (int I = 0; I < pv->size(); ++I)
Sum += (**pv).at(I);
for (int i = 0; i < pv->size(); ++i)
sum += (**pv)[i];
for (int I = 0; I < pv->size(); ++I)
Sum += (**pv)[I];
}
void wrongEnd() {
int bad;
for (int i = 0, e = v.size(); i < bad; ++i)
sum += v[i];
int Bad;
for (int I = 0, E = v.size(); I < Bad; ++I)
Sum += v[I];
}
// Checks to see that non-const member functions are not called on the container
// object.
// These could be conceivably allowed with a lower required confidence level.
void memberFunctionCalled() {
for (int i = 0; i < v.size(); ++i) {
sum += v[i];
for (int I = 0; I < v.size(); ++I) {
Sum += v[I];
v.foo();
}
for (int i = 0; i < v.size(); ++i) {
sum += v[i];
dependent<int>::iterator it = v.begin();
for (int I = 0; I < v.size(); ++I) {
Sum += v[I];
dependent<int>::iterator It = v.begin();
}
}
@ -419,39 +436,39 @@ void f(T);
void complexContainer() {
X x;
for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
for (S::iterator I = x.s.begin(), E = x.s.end(); I != E; ++I) {
f(x);
MutableVal k = *i;
MutableVal K = *I;
}
for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
for (T::iterator I = x.t.begin(), E = x.t.end(); I != E; ++I) {
f(x);
int k = *i;
int K = *I;
}
for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
for (S::iterator I = x.s.begin(), E = x.s.end(); I != E; ++I) {
f(x.s);
MutableVal k = *i;
MutableVal K = *I;
}
for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
for (T::iterator I = x.t.begin(), E = x.t.end(); I != E; ++I) {
f(x.t);
int k = *i;
int K = *I;
}
for (S::iterator i = x.getS().begin(), e = x.getS().end(); i != e; ++i) {
for (S::iterator I = x.getS().begin(), E = x.getS().end(); I != E; ++I) {
f(x.getS());
MutableVal k = *i;
MutableVal K = *I;
}
X exes[5];
int index = 0;
X Exes[5];
int Index = 0;
for (S::iterator i = exes[index].getS().begin(),
e = exes[index].getS().end();
i != e; ++i) {
index++;
MutableVal k = *i;
for (S::iterator I = Exes[Index].getS().begin(),
E = Exes[Index].getS().end();
I != E; ++I) {
Index++;
MutableVal K = *I;
}
}