diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8556487ff4ca..341d7ea71511 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3249,13 +3249,26 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) { if (ContractType const* contractType = dynamic_cast(typeType->actualType())) { + // ContractType has only user defined members, so annotation.referencedDeclaration is not NULL. + solAssert(annotation.referencedDeclaration); annotation.isLValue = annotation.referencedDeclaration->isLValue(); + // In case an expression `C.foo`, where `foo` is a function, assign C's purity to `C.foo`. + // This does not allow to assign it to a constant variable, because of different kind. + // Left-hand side of the variable declaration statement never has `Declaration` kind. It is used only to + // mark, that a function containing only such an expression has no effect. if ( auto const* functionType = dynamic_cast(annotation.type); functionType && functionType->kind() == FunctionType::Kind::Declaration ) annotation.isPure = *_memberAccess.expression().annotation().isPure; + // In case `Base.value` or `Lib.value` and when `value` is constant, the whole expression is pure. + else if ( + auto const* varDecl = dynamic_cast(annotation.referencedDeclaration); + varDecl && + varDecl->isConstant() + ) + annotation.isPure = true; } else annotation.isLValue = false; @@ -3322,14 +3335,6 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) annotation.isPure = true; } - if ( - auto const* varDecl = dynamic_cast(annotation.referencedDeclaration); - !annotation.isPure.set() && - varDecl && - varDecl->isConstant() - ) - annotation.isPure = true; - if (auto magicType = dynamic_cast(exprType)) { if (magicType->kind() == MagicType::Kind::ABI) @@ -3409,6 +3414,16 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (!annotation.isPure.set()) annotation.isPure = false; + if ( + auto const* funcType = dynamic_cast(annotation.type); + funcType && + funcType->kind() != FunctionType::Kind::Declaration && + funcType->kind() != FunctionType::Kind::Internal && + funcType->kind() != FunctionType::Kind::Error && + funcType->kind() != FunctionType::Kind::Event + ) + solAssert(funcType->isPure() == *annotation.isPure); + return false; }