mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11741 from ethereum/shadowing_inlineasm_fix_yul_codegen
Fixed inline assembly external identifier access.
This commit is contained in:
commit
ccdc11ea5b
@ -742,8 +742,15 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
yul::Identifier const& _identifier,
|
yul::Identifier const& _identifier,
|
||||||
yul::IdentifierContext _context,
|
yul::IdentifierContext _context,
|
||||||
bool
|
bool
|
||||||
)
|
) -> bool
|
||||||
{
|
{
|
||||||
|
if (_context == yul::IdentifierContext::NonExternal)
|
||||||
|
{
|
||||||
|
// Hack until we can disallow any shadowing: If we found an internal reference,
|
||||||
|
// clear the external references, so that codegen does not use it.
|
||||||
|
_inlineAssembly.annotation().externalReferences.erase(& _identifier);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
||||||
if (ref == _inlineAssembly.annotation().externalReferences.end())
|
if (ref == _inlineAssembly.annotation().externalReferences.end())
|
||||||
return false;
|
return false;
|
||||||
|
@ -411,6 +411,7 @@ void CompilerContext::appendInlineAssembly(
|
|||||||
yul::AbstractAssembly& _assembly
|
yul::AbstractAssembly& _assembly
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
|
||||||
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
|
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
|
||||||
solAssert(it != _localVariables.end(), "");
|
solAssert(it != _localVariables.end(), "");
|
||||||
auto stackDepth = static_cast<size_t>(distance(it, _localVariables.end()));
|
auto stackDepth = static_cast<size_t>(distance(it, _localVariables.end()));
|
||||||
|
@ -708,6 +708,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
yul::AbstractAssembly& _assembly
|
yul::AbstractAssembly& _assembly
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
|
||||||
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
|
||||||
solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), "");
|
solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), "");
|
||||||
Declaration const* decl = ref->second.declaration;
|
Declaration const* decl = ref->second.declaration;
|
||||||
|
@ -146,6 +146,13 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
|
if (m_resolver)
|
||||||
|
// We found a local reference, make sure there is no external reference.
|
||||||
|
m_resolver(
|
||||||
|
_identifier,
|
||||||
|
yul::IdentifierContext::NonExternal,
|
||||||
|
m_currentScope->insideFunction()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -308,7 +315,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
|||||||
|
|
||||||
validateInstructions(_funCall);
|
validateInstructions(_funCall);
|
||||||
}
|
}
|
||||||
else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
|
else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
|
||||||
[&](Scope::Variable const&)
|
[&](Scope::Variable const&)
|
||||||
{
|
{
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
@ -323,6 +330,16 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
|||||||
returnTypes = &_fun.returns;
|
returnTypes = &_fun.returns;
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
{
|
||||||
|
if (m_resolver)
|
||||||
|
// We found a local reference, make sure there is no external reference.
|
||||||
|
m_resolver(
|
||||||
|
_funCall.functionName,
|
||||||
|
yul::IdentifierContext::NonExternal,
|
||||||
|
m_currentScope->insideFunction()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (!validateInstructions(_funCall))
|
if (!validateInstructions(_funCall))
|
||||||
m_errorReporter.declarationError(
|
m_errorReporter.declarationError(
|
||||||
@ -539,6 +556,14 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
|
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
|
||||||
{
|
{
|
||||||
|
if (m_resolver)
|
||||||
|
// We found a local reference, make sure there is no external reference.
|
||||||
|
m_resolver(
|
||||||
|
_variable,
|
||||||
|
yul::IdentifierContext::NonExternal,
|
||||||
|
m_currentScope->insideFunction()
|
||||||
|
);
|
||||||
|
|
||||||
if (!holds_alternative<Scope::Variable>(*var))
|
if (!holds_alternative<Scope::Variable>(*var))
|
||||||
m_errorReporter.typeError(2657_error, _variable.debugData->location, "Assignment requires variable.");
|
m_errorReporter.typeError(2657_error, _variable.debugData->location, "Assignment requires variable.");
|
||||||
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))
|
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))
|
||||||
|
@ -117,7 +117,7 @@ public:
|
|||||||
virtual void markAsInvalid() = 0;
|
virtual void markAsInvalid() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IdentifierContext { LValue, RValue, VariableDeclaration };
|
enum class IdentifierContext { LValue, RValue, VariableDeclaration, NonExternal };
|
||||||
|
|
||||||
/// Object that is used to resolve references and generate code for access to identifiers external
|
/// Object that is used to resolve references and generate code for access to identifiers external
|
||||||
/// to inline assembly (not used in standalone assembly mode).
|
/// to inline assembly (not used in standalone assembly mode).
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint x) {
|
||||||
|
assembly {
|
||||||
|
function g() -> f { f := 2 }
|
||||||
|
x := g()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 2
|
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public returns (uint x) {
|
||||||
|
assembly {
|
||||||
|
function g() -> x {
|
||||||
|
x := 42
|
||||||
|
}
|
||||||
|
x := g()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError 6578: (123-124): Cannot access local Solidity variables from inside an inline assembly function.
|
Loading…
Reference in New Issue
Block a user