mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Assembly: Revive warning on not-yet-available EVM instructions in (strict) inline assembly.
This commit is contained in:
parent
044eb2d161
commit
a6e34bd441
@ -337,7 +337,8 @@ bool AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
|||||||
}
|
}
|
||||||
)))
|
)))
|
||||||
{
|
{
|
||||||
m_errorReporter.declarationError(_funCall.functionName.location, "Function not found.");
|
if (!warnOnInstructions(_funCall.functionName.name.str(), _funCall.functionName.location))
|
||||||
|
m_errorReporter.declarationError(_funCall.functionName.location, "Function not found.");
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
if (success)
|
if (success)
|
||||||
@ -653,7 +654,39 @@ void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _loc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsmAnalyzer::warnOnInstructions(dev::eth::Instruction _instr, SourceLocation const& _location)
|
// FIXME: copy'n'paste from AsmParser. make it more general (by putting it into dev::eth namespace)
|
||||||
|
std::map<string, dev::eth::Instruction> const& instructions()
|
||||||
|
{
|
||||||
|
// Allowed instructions, lowercase names.
|
||||||
|
static map<string, dev::eth::Instruction> s_instructions;
|
||||||
|
if (s_instructions.empty())
|
||||||
|
{
|
||||||
|
for (auto const& instruction: dev::eth::c_instructions)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
instruction.second == dev::eth::Instruction::JUMPDEST ||
|
||||||
|
dev::eth::isPushInstruction(instruction.second)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
string name = instruction.first;
|
||||||
|
transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
|
||||||
|
s_instructions[name] = instruction.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s_instructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsmAnalyzer::warnOnInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location)
|
||||||
|
{
|
||||||
|
auto const& instructionMap = instructions();
|
||||||
|
auto const identifier = boost::to_lower_copy(_instructionIdentifier);
|
||||||
|
if (auto const i = instructionMap.find(identifier); i != instructionMap.end())
|
||||||
|
return warnOnInstructions(i->second, _location);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsmAnalyzer::warnOnInstructions(dev::eth::Instruction _instr, SourceLocation const& _location)
|
||||||
{
|
{
|
||||||
// We assume that returndatacopy, returndatasize and staticcall are either all available
|
// We assume that returndatacopy, returndatasize and staticcall are either all available
|
||||||
// or all not available.
|
// or all not available.
|
||||||
@ -725,4 +758,8 @@ void AsmAnalyzer::warnOnInstructions(dev::eth::Instruction _instr, SourceLocatio
|
|||||||
"Use functions, \"switch\", \"if\" or \"for\" statements instead."
|
"Use functions, \"switch\", \"if\" or \"for\" statements instead."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,8 @@ private:
|
|||||||
|
|
||||||
Scope& scope(Block const* _block);
|
Scope& scope(Block const* _block);
|
||||||
void expectValidType(std::string const& type, langutil::SourceLocation const& _location);
|
void expectValidType(std::string const& type, langutil::SourceLocation const& _location);
|
||||||
void warnOnInstructions(dev::eth::Instruction _instr, langutil::SourceLocation const& _location);
|
bool warnOnInstructions(dev::eth::Instruction _instr, langutil::SourceLocation const& _location);
|
||||||
|
bool warnOnInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location);
|
||||||
|
|
||||||
int m_stackHeight = 0;
|
int m_stackHeight = 0;
|
||||||
yul::ExternalIdentifierAccess::Resolver m_resolver;
|
yul::ExternalIdentifierAccess::Resolver m_resolver;
|
||||||
|
@ -321,7 +321,12 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
|
|||||||
{
|
{
|
||||||
Identifier identifier{location(), literal};
|
Identifier identifier{location(), literal};
|
||||||
advance();
|
advance();
|
||||||
return FunctionCall{identifier.location, identifier, {}};
|
if (m_scanner->currentToken() == Token::LParen)
|
||||||
|
return FunctionCall{identifier.location, identifier, {}};
|
||||||
|
else if (instructions().count(identifier.name.str()))
|
||||||
|
m_errorReporter.syntaxError(identifier.location, "Instructions must be invoked function style. Expecting an '(' after the instruction.");
|
||||||
|
else
|
||||||
|
m_errorReporter.syntaxError(identifier.location, "Invalid identifier.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = Identifier{location(), literal};
|
ret = Identifier{location(), literal};
|
||||||
|
Loading…
Reference in New Issue
Block a user