diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 1833cb170..1967064b2 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -44,6 +44,18 @@ ASTNode::ASTNode(int64_t _id, SourceLocation _location): { } +Declaration const* ASTNode::referencedDeclaration(Expression const& _expression) +{ + if (auto const* memberAccess = dynamic_cast(&_expression)) + return memberAccess->annotation().referencedDeclaration; + else if (auto const* identifierPath = dynamic_cast(&_expression)) + return identifierPath->annotation().referencedDeclaration; + else if (auto const* identifier = dynamic_cast(&_expression)) + return identifier->annotation().referencedDeclaration; + else + return nullptr; +} + ASTAnnotation& ASTNode::annotation() const { if (!m_annotation) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 701ce6235..d546a029f 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -112,6 +112,10 @@ public: template static std::vector filteredNodes(std::vector> const& _nodes); + /// Extracts the referenced declaration from all nodes whose annotations support + /// `referencedDeclaration`. + static Declaration const* referencedDeclaration(Expression const& _expression); + /// Returns the source code location of this node. SourceLocation const& location() const { return m_location; } diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 2f7138249..3ed47d6f2 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -28,26 +28,21 @@ bool isConstantVariableRecursive(VariableDeclaration const& _varDecl) { solAssert(_varDecl.isConstant(), "Constant variable expected"); - auto referencedDeclaration = [&](Expression const* _e) -> VariableDeclaration const* - { - if (auto identifier = dynamic_cast(_e)) - return dynamic_cast(identifier->annotation().referencedDeclaration); - else if (auto memberAccess = dynamic_cast(_e)) - return dynamic_cast(memberAccess->annotation().referencedDeclaration); - return nullptr; - }; - - auto visitor = [&](VariableDeclaration const& _variable, util::CycleDetector& _cycleDetector, size_t _depth) + auto visitor = [](VariableDeclaration const& _variable, util::CycleDetector& _cycleDetector, size_t _depth) { solAssert(_depth < 256, "Recursion depth limit reached"); + if (!_variable.value()) + // This should result in an error later on. + return; - if (auto referencedVarDecl = referencedDeclaration(_variable.value().get())) + if (auto referencedVarDecl = dynamic_cast( + ASTNode::referencedDeclaration(*_variable.value())) + ) if (referencedVarDecl->isConstant()) - if (_cycleDetector.run(*referencedVarDecl)) - return; + _cycleDetector.run(*referencedVarDecl); }; - return util::CycleDetector(visitor).run(_varDecl); + return util::CycleDetector(visitor).run(_varDecl) != nullptr; } VariableDeclaration const* rootConstVariableDeclaration(VariableDeclaration const& _varDecl) diff --git a/libsolidity/codegen/ir/Common.cpp b/libsolidity/codegen/ir/Common.cpp index ae30f48f9..3fbcfe746 100644 --- a/libsolidity/codegen/ir/Common.cpp +++ b/libsolidity/codegen/ir/Common.cpp @@ -122,13 +122,3 @@ string IRNames::zeroValue(Type const& _type, string const& _variableName) { return "zero_" + _type.identifier() + _variableName; } - -FunctionDefinition const* IRHelpers::referencedFunctionDeclaration(Expression const& _expression) -{ - if (auto memberAccess = dynamic_cast(&_expression)) - return dynamic_cast(memberAccess->annotation().referencedDeclaration); - else if (auto identifier = dynamic_cast(&_expression)) - return dynamic_cast(identifier->annotation().referencedDeclaration); - else - return nullptr; -} diff --git a/libsolidity/codegen/ir/Common.h b/libsolidity/codegen/ir/Common.h index 76bb575aa..23d74cd21 100644 --- a/libsolidity/codegen/ir/Common.h +++ b/libsolidity/codegen/ir/Common.h @@ -66,11 +66,6 @@ struct IRNames static std::string zeroValue(Type const& _type, std::string const& _variableName); }; -struct IRHelpers -{ - static FunctionDefinition const* referencedFunctionDeclaration(Expression const& _expression); -}; - } // Overloading std::less() makes it possible to use YulArity as a map key. We could define operator< diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index b7d0f483b..2578c0fb5 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -903,7 +903,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) case FunctionType::Kind::Internal: { auto identifier = dynamic_cast(&_functionCall.expression()); - FunctionDefinition const* functionDef = IRHelpers::referencedFunctionDeclaration(_functionCall.expression()); + auto const* functionDef = dynamic_cast( + ASTNode::referencedDeclaration(_functionCall.expression()) + ); if (functionDef) {