|
|
|
pragma solidity 0.8.17;
|
|
|
|
|
|
|
|
contract CacheArrayLength
|
|
|
|
{
|
|
|
|
struct S
|
|
|
|
{
|
|
|
|
uint s;
|
|
|
|
}
|
|
|
|
|
|
|
|
S[] array;
|
|
|
|
S[] array2;
|
|
|
|
uint public x;
|
|
|
|
|
|
|
|
function h() external
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function g() internal
|
|
|
|
{
|
|
|
|
this.h();
|
|
|
|
}
|
|
|
|
|
|
|
|
function h_view() external view
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function g_view() internal view
|
|
|
|
{
|
|
|
|
this.h_view();
|
|
|
|
}
|
|
|
|
|
|
|
|
function f() public
|
|
|
|
{
|
|
|
|
// array accessed but length doesn't change
|
|
|
|
for (uint i = 0; i < array.length; i++) // warning should appear
|
|
|
|
{
|
|
|
|
array[i] = S(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length doesn't change, but array.length not used in loop condition
|
|
|
|
for (uint i = array.length; i >= 0; i--)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length changes in the inner loop
|
|
|
|
for (uint i = 0; i < array.length; i++)
|
|
|
|
{
|
|
|
|
for (uint j = i; j < 2 * i; j++)
|
|
|
|
array.push(S(j));
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length changes
|
|
|
|
for (uint i = 0; i < array.length; i++)
|
|
|
|
{
|
|
|
|
array.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length changes
|
|
|
|
for (uint i = 0; i < array.length; i++)
|
|
|
|
{
|
|
|
|
delete array;
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length doesn't change despite using delete
|
|
|
|
for (uint i = 0; i < array.length; i++) // warning should appear
|
|
|
|
{
|
|
|
|
delete array[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length changes; push used in more complex expression
|
|
|
|
for (uint i = 0; i < array.length; i++)
|
|
|
|
{
|
|
|
|
array.push() = S(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length doesn't change
|
|
|
|
for (uint i = 0; i < array.length; i++) // warning should appear
|
|
|
|
{
|
|
|
|
array2.pop();
|
|
|
|
array2.push();
|
|
|
|
array2.push(S(i));
|
|
|
|
delete array2;
|
|
|
|
delete array[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length changes; array2.length doesn't change
|
|
|
|
for (uint i = 0; i < 7; i++)
|
|
|
|
{
|
|
|
|
for (uint j = i; j < array.length; j++)
|
|
|
|
{
|
|
|
|
for (uint k = 0; k < j; k++)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint k = 0; k < array2.length; k++) // warning should appear
|
|
|
|
{
|
|
|
|
array.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// array.length doesn't change; array2.length changes
|
|
|
|
for (uint i = 0; i < 7; i++)
|
|
|
|
{
|
|
|
|
for (uint j = i; j < array.length; j++) // warning should appear
|
|
|
|
{
|
|
|
|
for (uint k = 0; k < j; k++)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint k = 0; k < array2.length; k++)
|
|
|
|
{
|
|
|
|
array2.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// none of array.length and array2.length changes
|
|
|
|
for (uint i = 0; i < 7; i++)
|
|
|
|
{
|
|
|
|
for (uint j = i; j < array.length; j++) // warning should appear
|
|
|
|
{
|
|
|
|
for (uint k = 0; k < j; k++)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint k = 0; k < array2.length; k++) // warning should appear
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
S[] memory array3;
|
|
|
|
|
|
|
|
// array3 not modified, but it's not a storage array
|
|
|
|
for (uint i = 0; i < array3.length; i++)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// array not modified, but it may potentially change in an internal function call
|
|
|
|
for (uint i = 0; i < array.length; i++)
|
|
|
|
{
|
|
|
|
g();
|
|
|
|
}
|
|
|
|
|
|
|
|
// array not modified, but it may potentially change in an external function call
|
|
|
|
for (uint i = 0; i < array.length; i++)
|
|
|
|
{
|
|
|
|
this.h();
|
|
|
|
}
|
|
|
|
|
|
|
|
// array not modified and it cannot be changed in a function call since g_view is a view function
|
|
|
|
for (uint i = 0; i < array.length; i++) // warning should appear
|
|
|
|
{
|
|
|
|
g_view();
|
|
|
|
}
|
|
|
|
|
|
|
|
// array not modified and it cannot be changed in a function call since h_view is a view function
|
|
|
|
for (uint i = 0; i < array.length; i++) // warning should appear
|
|
|
|
{
|
|
|
|
this.h_view();
|
|
|
|
}
|
|
|
|
// array not modified and it cannot be changed in a function call since x is a public state variable
|
|
|
|
for (uint i = 0; i < array.length; i++) // warning should appear
|
|
|
|
{
|
|
|
|
this.x();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|