aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis/ViewPureChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/analysis/ViewPureChecker.cpp')
-rw-r--r--libsolidity/analysis/ViewPureChecker.cpp39
1 files changed, 34 insertions, 5 deletions
diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp
index 7f28c7d2..13c3ab68 100644
--- a/libsolidity/analysis/ViewPureChecker.cpp
+++ b/libsolidity/analysis/ViewPureChecker.cpp
@@ -40,19 +40,20 @@ public:
void operator()(assembly::Label const&) { }
void operator()(assembly::Instruction const& _instruction)
{
- if (eth::SemanticInformation::invalidInViewFunctions(_instruction.instruction))
- m_reportMutability(StateMutability::NonPayable, _instruction.location);
- else if (eth::SemanticInformation::invalidInPureFunctions(_instruction.instruction))
- m_reportMutability(StateMutability::View, _instruction.location);
+ checkInstruction(_instruction.location, _instruction.instruction);
}
void operator()(assembly::Literal const&) {}
void operator()(assembly::Identifier const&) {}
void operator()(assembly::FunctionalInstruction const& _instr)
{
- (*this)(_instr.instruction);
+ checkInstruction(_instr.location, _instr.instruction);
for (auto const& arg: _instr.arguments)
boost::apply_visitor(*this, arg);
}
+ void operator()(assembly::ExpressionStatement const& _expr)
+ {
+ boost::apply_visitor(*this, _expr.expression);
+ }
void operator()(assembly::StackAssignment const&) {}
void operator()(assembly::Assignment const& _assignment)
{
@@ -72,6 +73,11 @@ public:
for (auto const& arg: _funCall.arguments)
boost::apply_visitor(*this, arg);
}
+ void operator()(assembly::If const& _if)
+ {
+ boost::apply_visitor(*this, *_if.condition);
+ (*this)(_if.body);
+ }
void operator()(assembly::Switch const& _switch)
{
boost::apply_visitor(*this, *_switch.expression);
@@ -97,6 +103,13 @@ public:
private:
std::function<void(StateMutability, SourceLocation const&)> m_reportMutability;
+ void checkInstruction(SourceLocation _location, solidity::Instruction _instruction)
+ {
+ if (eth::SemanticInformation::invalidInViewFunctions(_instruction))
+ m_reportMutability(StateMutability::NonPayable, _location);
+ else if (eth::SemanticInformation::invalidInPureFunctions(_instruction))
+ m_reportMutability(StateMutability::View, _location);
+ }
};
}
@@ -262,6 +275,22 @@ void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
reportMutability(mut, _functionCall.location());
}
+bool ViewPureChecker::visit(MemberAccess const& _memberAccess)
+{
+ // Catch the special case of `this.f.selector` which is a pure expression.
+ ASTString const& member = _memberAccess.memberName();
+ if (
+ _memberAccess.expression().annotation().type->category() == Type::Category::Function &&
+ member == "selector"
+ )
+ if (auto const* expr = dynamic_cast<MemberAccess const*>(&_memberAccess.expression()))
+ if (auto const* exprInt = dynamic_cast<Identifier const*>(&expr->expression()))
+ if (exprInt->name() == "this")
+ // Do not continue visiting.
+ return false;
+ return true;
+}
+
void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
{
StateMutability mutability = StateMutability::Pure;