mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow memory-safe inline assembly dialect flag.
This commit is contained in:
parent
6b6e163be5
commit
290b1c3a90
@ -202,7 +202,17 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly)
|
|||||||
if (valuesSeen.insert(value).second)
|
if (valuesSeen.insert(value).second)
|
||||||
{
|
{
|
||||||
if (value == "memory-safe-assembly")
|
if (value == "memory-safe-assembly")
|
||||||
|
{
|
||||||
|
if (_assembly.annotation().markedMemorySafe)
|
||||||
|
m_errorReporter.warning(
|
||||||
|
8544_error,
|
||||||
|
_assembly.location(),
|
||||||
|
"Inline assembly marked as memory safe using both a NatSpec tag and an assembly flag. "
|
||||||
|
"If you are not concerned with backwards compatibility, only use the assembly flag, "
|
||||||
|
"otherwise only use the NatSpec tag."
|
||||||
|
);
|
||||||
_assembly.annotation().markedMemorySafe = true;
|
_assembly.annotation().markedMemorySafe = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
8787_error,
|
8787_error,
|
||||||
|
@ -334,6 +334,27 @@ bool SyntaxChecker::visit(UnaryOperation const& _operation)
|
|||||||
|
|
||||||
bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly)
|
bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||||
{
|
{
|
||||||
|
if (_inlineAssembly.flags())
|
||||||
|
for (auto flag: *_inlineAssembly.flags())
|
||||||
|
{
|
||||||
|
if (*flag == "memory-safe")
|
||||||
|
{
|
||||||
|
if (_inlineAssembly.annotation().markedMemorySafe)
|
||||||
|
m_errorReporter.syntaxError(
|
||||||
|
7026_error,
|
||||||
|
_inlineAssembly.location(),
|
||||||
|
"Inline assembly marked memory-safe multiple times."
|
||||||
|
);
|
||||||
|
_inlineAssembly.annotation().markedMemorySafe = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_errorReporter.warning(
|
||||||
|
4430_error,
|
||||||
|
_inlineAssembly.location(),
|
||||||
|
"Unknown inline assembly flag: \"" + *flag + "\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_useYulOptimizer)
|
if (!m_useYulOptimizer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1463,19 +1463,26 @@ public:
|
|||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
ASTPointer<ASTString> const& _docString,
|
ASTPointer<ASTString> const& _docString,
|
||||||
yul::Dialect const& _dialect,
|
yul::Dialect const& _dialect,
|
||||||
|
ASTPointer<std::vector<ASTPointer<ASTString>>> _flags,
|
||||||
std::shared_ptr<yul::Block> _operations
|
std::shared_ptr<yul::Block> _operations
|
||||||
):
|
):
|
||||||
Statement(_id, _location, _docString), m_dialect(_dialect), m_operations(std::move(_operations)) {}
|
Statement(_id, _location, _docString),
|
||||||
|
m_dialect(_dialect),
|
||||||
|
m_flags(move(_flags)),
|
||||||
|
m_operations(std::move(_operations))
|
||||||
|
{}
|
||||||
void accept(ASTVisitor& _visitor) override;
|
void accept(ASTVisitor& _visitor) override;
|
||||||
void accept(ASTConstVisitor& _visitor) const override;
|
void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
yul::Dialect const& dialect() const { return m_dialect; }
|
yul::Dialect const& dialect() const { return m_dialect; }
|
||||||
yul::Block const& operations() const { return *m_operations; }
|
yul::Block const& operations() const { return *m_operations; }
|
||||||
|
ASTPointer<std::vector<ASTPointer<ASTString>>> const& flags() const { return m_flags; }
|
||||||
|
|
||||||
InlineAssemblyAnnotation& annotation() const override;
|
InlineAssemblyAnnotation& annotation() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
yul::Dialect const& m_dialect;
|
yul::Dialect const& m_dialect;
|
||||||
|
ASTPointer<std::vector<ASTPointer<ASTString>>> m_flags;
|
||||||
std::shared_ptr<yul::Block> m_operations;
|
std::shared_ptr<yul::Block> m_operations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -600,11 +600,23 @@ bool ASTJsonConverter::visit(InlineAssembly const& _node)
|
|||||||
for (Json::Value& it: externalReferences | ranges::views::values)
|
for (Json::Value& it: externalReferences | ranges::views::values)
|
||||||
externalReferencesJson.append(std::move(it));
|
externalReferencesJson.append(std::move(it));
|
||||||
|
|
||||||
setJsonNode(_node, "InlineAssembly", {
|
std::vector<pair<string, Json::Value>> attributes = {
|
||||||
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
|
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
|
||||||
make_pair("externalReferences", std::move(externalReferencesJson)),
|
make_pair("externalReferences", std::move(externalReferencesJson)),
|
||||||
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
|
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (_node.flags())
|
||||||
|
{
|
||||||
|
Json::Value flags(Json::arrayValue);
|
||||||
|
for (auto const& flag: *_node.flags())
|
||||||
|
if (flag)
|
||||||
|
flags.append(*flag);
|
||||||
|
else
|
||||||
|
flags.append(Json::nullValue);
|
||||||
|
attributes.emplace_back(make_pair("flags", move(flags)));
|
||||||
|
}
|
||||||
|
setJsonNode(_node, "InlineAssembly", move(attributes));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -626,11 +626,24 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json::Value con
|
|||||||
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");
|
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");
|
||||||
|
|
||||||
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
|
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
|
||||||
|
ASTPointer<vector<ASTPointer<ASTString>>> flags;
|
||||||
|
if (_node.isMember("flags"))
|
||||||
|
{
|
||||||
|
flags = make_shared<vector<ASTPointer<ASTString>>>();
|
||||||
|
Json::Value const& flagsNode = _node["flags"];
|
||||||
|
astAssert(flagsNode.isArray(), "Assembly flags must be an array.");
|
||||||
|
for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i)
|
||||||
|
{
|
||||||
|
astAssert(flagsNode[i].isString(), "Assembly flag must be a string.");
|
||||||
|
flags->emplace_back(make_shared<ASTString>(flagsNode[i].asString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
shared_ptr<yul::Block> operations = make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST")));
|
shared_ptr<yul::Block> operations = make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST")));
|
||||||
return createASTNode<InlineAssembly>(
|
return createASTNode<InlineAssembly>(
|
||||||
_node,
|
_node,
|
||||||
nullOrASTString(_node, "documentation"),
|
nullOrASTString(_node, "documentation"),
|
||||||
dialect,
|
dialect,
|
||||||
|
move(flags),
|
||||||
operations
|
operations
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1321,13 +1321,28 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
|
|||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPointer<vector<ASTPointer<ASTString>>> flags;
|
||||||
|
if (m_scanner->currentToken() == Token::LParen)
|
||||||
|
{
|
||||||
|
flags = make_shared<vector<ASTPointer<ASTString>>>();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
advance();
|
||||||
|
expectToken(Token::StringLiteral, false);
|
||||||
|
flags->emplace_back(make_shared<ASTString>(m_scanner->currentLiteral()));
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
while (m_scanner->currentToken() == Token::Comma);
|
||||||
|
expectToken(Token::RParen);
|
||||||
|
}
|
||||||
|
|
||||||
yul::Parser asmParser(m_errorReporter, dialect);
|
yul::Parser asmParser(m_errorReporter, dialect);
|
||||||
shared_ptr<yul::Block> block = asmParser.parseInline(m_scanner);
|
shared_ptr<yul::Block> block = asmParser.parseInline(m_scanner);
|
||||||
if (block == nullptr)
|
if (block == nullptr)
|
||||||
BOOST_THROW_EXCEPTION(FatalError());
|
BOOST_THROW_EXCEPTION(FatalError());
|
||||||
|
|
||||||
location.end = nativeLocationOf(*block).end;
|
location.end = nativeLocationOf(*block).end;
|
||||||
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, block);
|
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, move(flags), block);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
|
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
|
||||||
|
Loading…
Reference in New Issue
Block a user