#pragma once
#include <libsolidity/ast/ASTVisitor.h>
#include <liblangutil/ErrorReporter.h>
#include <memory>
namespace solidity::frontend
{
class ImmutableValidator: private ASTConstVisitor
{
using CallableDeclarationSet = std::set<CallableDeclaration const*, ASTNode::CompareByID>;
public:
ImmutableValidator(langutil::ErrorReporter& _errorReporter, ContractDefinition const& _contractDefinition):
m_mostDerivedContract(_contractDefinition),
m_errorReporter(_errorReporter)
{ }
void analyze();
private:
bool visit(Assignment const& _assignment);
bool visit(FunctionDefinition const& _functionDefinition);
bool visit(ModifierDefinition const& _modifierDefinition);
bool visit(MemberAccess const& _memberAccess);
bool visit(IfStatement const& _ifStatement);
bool visit(WhileStatement const& _whileStatement);
void endVisit(IdentifierPath const& _identifierPath);
void endVisit(Identifier const& _identifier);
void endVisit(Return const& _return);
bool analyseCallable(CallableDeclaration const& _callableDeclaration);
void analyseVariableReference(VariableDeclaration const& _variableReference, Expression const& _expression);
void checkAllVariablesInitialized(langutil::SourceLocation const& _location);
void visitCallableIfNew(Declaration const& _declaration);
ContractDefinition const& m_mostDerivedContract;
CallableDeclarationSet m_visitedCallables;
std::set<VariableDeclaration const*, ASTNode::CompareByID> m_initializedStateVariables;
langutil::ErrorReporter& m_errorReporter;
FunctionDefinition const* m_currentConstructor = nullptr;
ContractDefinition const* m_currentConstructorContract = nullptr;
bool m_inLoop = false;
bool m_inBranch = false;
bool m_inCreationContext = true;
};
}