diff --git a/docs/control-structures.rst b/docs/control-structures.rst index a21de757d..0559e6546 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -44,6 +44,7 @@ this nonsensical example:: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; + // This will report a warning contract C { function g(uint a) public pure returns (uint ret) { return a + f(); } function f() internal pure returns (uint ret) { return g(7) + f(); } diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index da6886bbe..42c71a5dd 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -260,6 +260,7 @@ bool ControlFlowBuilder::visit(PlaceholderStatement const&) bool ControlFlowBuilder::visit(FunctionCall const& _functionCall) { + solAssert(!!m_revertNode, ""); solAssert(!!m_currentNode, ""); solAssert(!!_functionCall.expression().annotation().type, ""); @@ -267,30 +268,43 @@ bool ControlFlowBuilder::visit(FunctionCall const& _functionCall) switch (functionType->kind()) { case FunctionType::Kind::Revert: - solAssert(!!m_revertNode, ""); visitNode(_functionCall); _functionCall.expression().accept(*this); ASTNode::listAccept(_functionCall.arguments(), *this); + connect(m_currentNode, m_revertNode); + m_currentNode = newLabel(); return false; case FunctionType::Kind::Require: case FunctionType::Kind::Assert: { - solAssert(!!m_revertNode, ""); visitNode(_functionCall); _functionCall.expression().accept(*this); ASTNode::listAccept(_functionCall.arguments(), *this); + connect(m_currentNode, m_revertNode); + auto nextNode = newLabel(); + connect(m_currentNode, nextNode); m_currentNode = nextNode; return false; } case FunctionType::Kind::Internal: { + visitNode(_functionCall); + _functionCall.expression().accept(*this); + ASTNode::listAccept(_functionCall.arguments(), *this); + m_currentNode->functionCalls.emplace_back(&_functionCall); - break; + + auto nextNode = newLabel(); + + connect(m_currentNode, nextNode); + m_currentNode = nextNode; + + return false; } default: break; diff --git a/libsolidity/analysis/ControlFlowRevertPruner.cpp b/libsolidity/analysis/ControlFlowRevertPruner.cpp index aedf5aed8..af301cc72 100644 --- a/libsolidity/analysis/ControlFlowRevertPruner.cpp +++ b/libsolidity/analysis/ControlFlowRevertPruner.cpp @@ -20,6 +20,8 @@ #include +#include + namespace solidity::frontend { @@ -192,7 +194,11 @@ void ControlFlowRevertPruner::modifyFunctionFlows() // change anymore, we treat all "unknown" states as // "reverting", since they can only be caused by // recursion. + for (CFGNode * node: _node->exits) + ranges::remove(node->entries, _node); + _node->exits = {functionFlow.revert}; + functionFlow.revert->entries.push_back(_node); return; default: break;