diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/for_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/for_declaration_err.sol new file mode 100644 index 000000000..ddb5faa9f --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/for_declaration_err.sol @@ -0,0 +1,38 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure { + S storage c; + assembly { + for {} eq(0,0) { c_slot := s_slot } {} + } + c; + } + function g() internal pure { + S storage c; + assembly { + for {} eq(0,1) { c_slot := s_slot } {} + } + c; + } + function h() internal pure { + S storage c; + assembly { + for {} eq(0,0) {} { c_slot := s_slot } + } + c; + } + function i() internal pure { + S storage c; + assembly { + for {} eq(0,1) {} { c_slot := s_slot } + } + c; + } +} +// ---- +// TypeError: (189-190): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (340-341): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (491-492): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (642-643): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. + diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/for_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/for_declaration_fine.sol new file mode 100644 index 000000000..19a58b234 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/for_declaration_fine.sol @@ -0,0 +1,19 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure { + S storage c; + assembly { + for { c_slot := s_slot } iszero(0) {} {} + } + c; + } + function g() internal pure { + S storage c; + assembly { + for { c_slot := s_slot } iszero(1) {} {} + } + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/if_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/if_declaration_err.sol new file mode 100644 index 000000000..1d4302755 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/if_declaration_err.sol @@ -0,0 +1,13 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal pure { + S storage c; + assembly { + if flag { c_slot := s_slot } + } + c; + } +} +// ---- +// TypeError: (188-189): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/returning_function_declaration.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/returning_function_declaration.sol new file mode 100644 index 000000000..180feb770 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/returning_function_declaration.sol @@ -0,0 +1,15 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure { + S storage c; + // this should warn about unreachable code, but currently function flow is ignored + assembly { + function f() { return(0, 0) } + f() + c_slot := s_slot + } + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/reverting_function_declaration.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/reverting_function_declaration.sol new file mode 100644 index 000000000..bba9daf34 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/reverting_function_declaration.sol @@ -0,0 +1,15 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure { + S storage c; + // this could be allowed, but currently control flow for functions is not analysed + assembly { + function f() { revert(0, 0) } + f() + } + c; + } +} +// ---- +// TypeError: (287-288): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/stub_declaration.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/stub_declaration.sol new file mode 100644 index 000000000..c3f240915 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/stub_declaration.sol @@ -0,0 +1,12 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure { + S storage c; + assembly { + c_slot := s_slot + } + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/switch_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/switch_declaration_err.sol new file mode 100644 index 000000000..72884e741 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/switch_declaration_err.sol @@ -0,0 +1,33 @@ +contract C { + struct S { bool f; } + S s; + function f(uint256 a) internal pure { + S storage c; + assembly { + switch a + case 0 { c_slot := s_slot } + } + c; + } + function g(bool flag) internal pure { + S storage c; + assembly { + switch flag + case 0 { c_slot := s_slot } + case 1 { c_slot := s_slot } + } + c; + } + function h(uint256 a) internal pure { + S storage c; + assembly { + switch a + case 0 { c_slot := s_slot } + default { return(0,0) } + } + c; + } +} +// ---- +// TypeError: (208-209): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (421-422): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/switch_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/switch_declaration_fine.sol new file mode 100644 index 000000000..d72310924 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly/switch_declaration_fine.sol @@ -0,0 +1,31 @@ +contract C { + struct S { bool f; } + S s; + function f(uint256 a) internal pure { + S storage c; + assembly { + switch a + default { c_slot := s_slot } + } + c; + } + function g(bool flag) internal pure { + S storage c; + assembly { + switch flag + case 0 { c_slot := s_slot } + default { c_slot := s_slot } + } + c; + } + function h(uint256 a) internal pure { + S storage c; + assembly { + switch a + case 0 { revert(0, 0) } + default { c_slot := s_slot } + } + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_declaration_err.sol new file mode 100644 index 000000000..25654b1dd --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_declaration_err.sol @@ -0,0 +1,66 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + do { + break; + c = s; + } while(false); + c; + } + function g() internal view { + S storage c; + do { + if (s.f) { + continue; + c = s; + } + else { + } + } while(false); + c; + } + function h() internal view { + S storage c; + do { + if (s.f) { + break; + } + else { + c = s; + } + } while(false); + c; + } + function i() internal view { + S storage c; + do { + if (s.f) { + continue; + } + else { + c = s; + } + } while(false); + c; + } + function j() internal view { + S storage c; + do { + continue; + c = s; + } while(false); + c; + } +} +// ---- +// TypeError: (184-185): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// Warning: (145-150): Unreachable code. +// Warning: (168-173): Unreachable code. +// TypeError: (411-412): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// Warning: (325-330): Unreachable code. +// TypeError: (635-636): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (862-863): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (1011-1012): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// Warning: (972-977): Unreachable code. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_declaration_fine.sol new file mode 100644 index 000000000..40ddc3777 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_declaration_fine.sol @@ -0,0 +1,44 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + do {} while((c = s).f); + c; + } + function g() internal view { + S storage c; + do { c = s; } while(false); + c; + } + function h() internal view { + S storage c; + c = s; + do {} while(false); + c; + } + function i() internal view { + S storage c; + do {} while(false); + c = s; + c; + } + function j() internal view { + S storage c; + do { + c = s; + break; + } while(false); + c; + } + function k() internal view { + S storage c; + do { + c = s; + continue; + } while(false); + c; + } +} +// ---- +// Warning: (606-611): Unreachable code. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_declaration_err.sol new file mode 100644 index 000000000..e93d9798f --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_declaration_err.sol @@ -0,0 +1,20 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + for(;; c = s) { + } + c; + } + function g() internal view { + S storage c; + for(;;) { + c = s; + } + c; + } +} +// ---- +//TypeError: (143-144): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (261-262): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_declaration_fine.sol new file mode 100644 index 000000000..b3e9f46d1 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_declaration_fine.sol @@ -0,0 +1,17 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + for(c = s;;) { + } + c; + } + function g() internal view { + S storage c; + for(; (c = s).f;) { + } + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_declaration_err.sol new file mode 100644 index 000000000..7da6bef92 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_declaration_err.sol @@ -0,0 +1,22 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal { + S storage c; + if (flag) c = s; + c; + } + function g(bool flag) internal { + S storage c; + if (flag) c = s; + else + { + if (!flag) c = s; + else s.f = true; + } + c; + } +} +// ---- +// TypeError: (138-139): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (330-331): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_declaration_fine.sol new file mode 100644 index 000000000..5d3a6d5bd --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_declaration_fine.sol @@ -0,0 +1,39 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view { + S storage c; + if (flag) c = s; + else c = s; + c; + } + function g(bool flag) internal view { + S storage c; + if (flag) c = s; + else { c = s; } + c; + } + function h(bool flag) internal view { + S storage c; + if (flag) c = s; + else + { + if (!flag) c = s; + else c = s; + } + c; + } + function i() internal view { + S storage c; + if ((c = s).f) { + } + c; + } + function j() internal view { + S storage c; + if ((c = s).f && !(c = s).f) { + } + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_declaration_fine.sol new file mode 100644 index 000000000..6df4939cf --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_declaration_fine.sol @@ -0,0 +1,20 @@ +contract C { + modifier revertIfNoReturn() { + _; + revert(); + } + modifier ifFlag(bool flag) { + if (flag) + _; + } + struct S { uint a; } + S s; + function f(bool flag) revertIfNoReturn() internal view { + if (flag) s; + } + function g(bool flag) revertIfNoReturn() ifFlag(flag) internal view { + s; + } + +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/revert_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/revert_declaration_fine.sol new file mode 100644 index 000000000..5cb580528 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/revert_declaration_fine.sol @@ -0,0 +1,11 @@ +contract C { + struct S { bool f; } + S s; + function g(bool flag) internal view { + S storage c; + if (flag) c = s; + else revert(); + s; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_declaration_err.sol new file mode 100644 index 000000000..a6dd300ce --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_declaration_err.sol @@ -0,0 +1,24 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + false && (c = s).f; + c; + } + function g() internal view { + S storage c; + true || (c = s).f; + c; + } + function h() internal view { + S storage c; + // expect error, although this is always fine + true && (false || (c = s).f); + c; + } +} +// ---- +// TypeError: (137-138): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (235-236): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (398-399): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_declaration_fine.sol new file mode 100644 index 000000000..e8ad5e485 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_declaration_fine.sol @@ -0,0 +1,15 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + (c = s).f && false; + c; + } + function g() internal view { + S storage c; + (c = s).f || true; + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/smoke_declaration.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/smoke_declaration.sol new file mode 100644 index 000000000..f820456e1 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/smoke_declaration.sol @@ -0,0 +1,17 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure {} + function g() internal view { s; } + function h() internal view { + S storage c; + c = s; + c; + } + function i() internal view { + S storage c; + (c) = s; + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_declaration_err.sol new file mode 100644 index 000000000..3b4552f86 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_declaration_err.sol @@ -0,0 +1,17 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view { + S storage c; + flag ? (c = s).f : false; + c; + } + function g(bool flag) internal view { + S storage c; + flag ? false : (c = s).f; + c; + } +} +// ---- +// TypeError: (152-153): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (266-267): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_declaration_fine.sol new file mode 100644 index 000000000..1dd8d2f57 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_declaration_fine.sol @@ -0,0 +1,20 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view { + S storage c; + flag ? c = s : c = s; + c; + } + function g(bool flag) internal view { + S storage c; + flag ? c = s : (c = s); + c; + } + function h(bool flag) internal view { + S storage c; + flag ? (c = s).f : (c = s).f; + c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/try_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/try_declaration_err.sol new file mode 100644 index 000000000..ca43dc346 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/try_declaration_err.sol @@ -0,0 +1,42 @@ +contract C { + struct S { bool f; } + S s; + function ext() external {} + function f() internal + { + S storage r; + try this.ext() { } + catch (bytes memory) { r = s; } + r; + } + function g() internal + { + S storage r; + try this.ext() { r = s; } + catch (bytes memory) { } + r; + } + function h() internal + { + S storage r; + try this.ext() {} + catch Error (string memory) { r = s; } + catch (bytes memory) { r = s; } + r; + } + function i() internal + { + S storage r; + try this.ext() { r = s; } + catch (bytes memory) { r; } + r = s; + r; + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// TypeError: (206-207): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (343-344): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (526-527): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError: (653-654): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/try_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/try_declaration_fine.sol new file mode 100644 index 000000000..6834525d5 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/try_declaration_fine.sol @@ -0,0 +1,30 @@ +contract C { + struct S { bool f; } + S s; + function ext() external { } + function f() internal + { + S storage r; + try this.ext() { r = s; } + catch (bytes memory) { r = s; } + r; + } + function g() internal + { + S storage r; + try this.ext() { r = s; } + catch Error (string memory) { r = s; } + catch (bytes memory) { r = s; } + r; + } + function h() internal + { + S storage r; + try this.ext() { } + catch (bytes memory) { } + r = s; + r; + } +} +// ==== +// EVMVersion: >=byzantium diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_declaration_fine.sol new file mode 100644 index 000000000..e2e274196 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/tuple_declaration_fine.sol @@ -0,0 +1,17 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage, uint) { + return (s,2); + } + function g() internal view { + uint a; + S storage c; + (c, a) = f(); + c; + } + function h() internal view { + (s, s); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_declaration_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_declaration_err.sol new file mode 100644 index 000000000..cd6fee8db --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_declaration_err.sol @@ -0,0 +1,13 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + while(false) { + c = s; + } + c; + } +} +// ---- +// TypeError: (161-162): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_declaration_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_declaration_fine.sol new file mode 100644 index 000000000..20e72e5db --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_declaration_fine.sol @@ -0,0 +1,25 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view { + S storage c; + while((c = s).f) { + } + c; + } + function g() internal view { + S storage c; + c = s; + while(false) { + } + c; + } + function h() internal view { + S storage c; + while(false) { + } + c = s; + c; + } +} +// ----