Fix shadowing error for inline assembly.

This commit is contained in:
chriseth 2021-08-04 12:10:49 +02:00
parent 838514a718
commit aeb2438eab
25 changed files with 67 additions and 56 deletions

View File

@ -2,6 +2,7 @@
Breaking changes:
* `error` is now a keyword that can only be used for defining errors.
* Inline Assembly: Consider functions, function parameters and return variables for shadowing checks.
### 0.8.8 (unreleased)

View File

@ -274,28 +274,8 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
{
for (auto const& identifier: _varDecl.variables)
{
validateYulIdentifierName(identifier.name, identifier.debugData->location);
if (
auto declarations = m_resolver.nameFromCurrentScope(identifier.name.str());
!declarations.empty()
)
{
SecondarySourceLocation ssl;
for (auto const* decl: declarations)
ssl.append("The shadowed declaration is here:", decl->location());
if (!ssl.infos.empty())
m_errorReporter.declarationError(
3859_error,
identifier.debugData->location,
ssl,
"This declaration shadows a declaration outside the inline assembly block."
);
}
}
if (_varDecl.value)
visit(*_varDecl.value);
}
@ -385,4 +365,20 @@ void ReferencesResolver::validateYulIdentifierName(yul::YulString _name, SourceL
_location,
"The identifier name \"" + _name.str() + "\" is reserved."
);
auto declarations = m_resolver.nameFromCurrentScope(_name.str());
if (!declarations.empty())
{
SecondarySourceLocation ssl;
for (auto const* decl: declarations)
if (decl->location().hasText())
ssl.append("The shadowed declaration is here:", decl->location());
if (!ssl.infos.empty())
m_errorReporter.declarationError(
3859_error,
_location,
ssl,
"This declaration shadows a declaration outside the inline assembly block."
);
}
}

View File

@ -323,7 +323,6 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
returnTypes = &_fun.returns;
}
}))
else
{
if (!validateInstructions(_funCall))
m_errorReporter.declarationError(

View File

@ -1,12 +0,0 @@
contract C {
function f() public returns (uint x) {
assembly {
function g() -> f { f := 2 }
x := g()
}
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2

View File

@ -7,11 +7,11 @@ contract C {
uint256 off1;
uint256 off2;
assembly {
function f() -> o1 {
function g() -> o1 {
sstore(z.slot, 7)
o1 := y.offset
}
off2 := f()
off2 := g()
}
assert(off2 == 2);
return true;

View File

@ -1,5 +1,5 @@
contract C {
function f() public pure returns (uint w) {
function g() public pure returns (uint w) {
assembly {
function f() -> t {
t := 2
@ -14,4 +14,4 @@ contract C {
// compileToEwasm: also
// compileViaYul: also
// ----
// f() -> 2
// g() -> 2

View File

@ -1,7 +1,7 @@
contract C {
uint256 public z;
function f() public {
function g() public {
z = 42;
uint i = 32;
assembly {

View File

@ -1,7 +1,7 @@
contract C {
function f() public pure {
assembly {
function f() {
function g() {
// Make sure this doesn't trigger the unimplemented assertion in the control flow builder.
leave
}

View File

@ -1,7 +1,7 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
function g() internal pure {
S storage c;
// this should warn about unreachable code, but currently function flow is ignored
assembly {

View File

@ -1,7 +1,7 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure {
function g() internal pure {
S storage c;
// this could be allowed, but currently control flow for functions is not analysed
assembly {

View File

@ -1,7 +1,7 @@
contract C {
struct S { bool f; }
S s;
function f() internal pure returns (S storage c) {
function g() internal pure returns (S storage c) {
// this should warn about unreachable code, but currently function flow is ignored
assembly {
function f() { return(0, 0) }

View File

@ -4,8 +4,8 @@ contract C {
function f() internal pure returns (S storage c) {
// this could be allowed, but currently control flow for functions is not analysed
assembly {
function f() { revert(0, 0) }
f()
function g() { revert(0, 0) }
g()
}
}
}

View File

@ -9,4 +9,5 @@ contract C {
}
}
// ----
// DeclarationError 3859: (103-104): This declaration shadows a declaration outside the inline assembly block.
// DeclarationError 6578: (123-124): Cannot access local Solidity variables from inside an inline assembly function.

View File

@ -1,5 +1,5 @@
contract C {
function f() public pure {
function g() public pure {
assembly {
function f(a) {}

View File

@ -1,7 +1,7 @@
contract C {
function f() pure public {
assembly {
function f (a, b , c ) -> y,x,z {
function g (a, b , c ) -> y,x,z {
}
}
}

View File

@ -1,8 +1,8 @@
contract C {
function f() public pure {
assembly {
function f() {}
f := 1
function g() {}
g := 1
}
}
}

View File

@ -1,5 +1,5 @@
contract C {
function f() public pure {
function g() public pure {
assembly {
function f(a., x.b) -> t.b, b.. {}
}

View File

@ -1,5 +1,5 @@
contract C {
function f() public pure {
function g() public pure {
assembly {
function f() -> x, y, z {}
let a., aa.b := f()

View File

@ -49,7 +49,5 @@ contract C {
// DeclarationError 4113: (595-600): The identifier name "super" is reserved.
// DeclarationError 4113: (645-646): The identifier name "_" is reserved.
// DeclarationError 4113: (759-763): The identifier name "this" is reserved.
// DeclarationError 3859: (759-763): This declaration shadows a declaration outside the inline assembly block.
// DeclarationError 4113: (785-790): The identifier name "super" is reserved.
// DeclarationError 3859: (785-790): This declaration shadows a declaration outside the inline assembly block.
// DeclarationError 4113: (812-813): The identifier name "_" is reserved.

View File

@ -1,7 +1,7 @@
contract C {
function f() public pure {
assembly {
function f() {
function g() {
leave
}
}

View File

@ -0,0 +1,11 @@
contract C {
uint x;
function f() public pure {
assembly {
function g(f) -> x {}
}
}
}
// ----
// DeclarationError 3859: (98-99): This declaration shadows a declaration outside the inline assembly block.
// DeclarationError 3859: (104-105): This declaration shadows a declaration outside the inline assembly block.

View File

@ -0,0 +1,9 @@
contract C {
function f() public pure {
assembly {
function f() {}
}
}
}
// ----
// DeclarationError 3859: (75-90): This declaration shadows a declaration outside the inline assembly block.

View File

@ -0,0 +1,10 @@
contract C {
function f() public pure {
uint a;
assembly {
function g(a) {}
}
}
}
// ----
// DeclarationError 3859: (102-103): This declaration shadows a declaration outside the inline assembly block.

View File

@ -9,7 +9,5 @@ contract C {
}
// ----
// DeclarationError 4113: (74-79): The identifier name "super" is reserved.
// DeclarationError 3859: (74-79): This declaration shadows a declaration outside the inline assembly block.
// DeclarationError 4113: (101-105): The identifier name "this" is reserved.
// DeclarationError 3859: (101-105): This declaration shadows a declaration outside the inline assembly block.
// DeclarationError 4113: (127-128): The identifier name "_" is reserved.

View File

@ -12,7 +12,7 @@ contract C {
assembly { for {} 1 { pop(sload(0)) } { } pop(gas()) }
}
function h() view public {
assembly { function g() { pop(blockhash(20)) } }
assembly { function g1() { pop(blockhash(20)) } }
}
function i() public {
assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) }