diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7bc4677e2..ebf70f87a 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2303,11 +2303,19 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) functionType = dynamic_cast(expressionType); funcCallAnno.kind = FunctionCallKind::FunctionCall; + if (auto memberAccess = dynamic_cast(&_functionCall.expression())) + { + if (dynamic_cast(memberAccess->annotation().referencedDeclaration)) + _functionCall.expression().annotation().calledDirectly = true; + } + else if (auto identifier = dynamic_cast(&_functionCall.expression())) + if (dynamic_cast(identifier->annotation().referencedDeclaration)) + _functionCall.expression().annotation().calledDirectly = true; + // Purity for function calls also depends upon the callee and its FunctionType funcCallAnno.isPure = argumentsArePure && *_functionCall.expression().annotation().isPure && - functionType && functionType->isPure(); if ( diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 28beb0d45..027b48a30 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -260,6 +260,15 @@ struct ExpressionAnnotation: ASTAnnotation /// Types and - if given - names of arguments if the expr. is a function /// that is called, used for overload resolution std::optional arguments; + + /// True if the expression consists solely of the name of the function and the function is called immediately + /// instead of being stored or processed. The name may be qualified with the name of a contract, library + /// module, etc., that clarifies the scope. For example: `m.L.f()`, where `m` is a module, `L` is a library + /// and `f` is a function is a direct call. This means that the function to be called is known at compilation + /// time and it's not necessary to rely on any runtime dispatch mechanism to resolve it. + /// Note that even the simplest expressions, like `(f)()`, result in an indirect call even if they consist of + /// values known at compilation time. + bool calledDirectly = false; }; struct IdentifierAnnotation: ExpressionAnnotation