Skip to content

Commit 33f2709

Browse files
authored
Merge pull request #13739 from ethereum/code-reshuffling-before-operators
Code reshuffling before custom operators
2 parents 39a8ec1 + 261e819 commit 33f2709

File tree

4 files changed

+54
-34
lines changed

4 files changed

+54
-34
lines changed

libsolidity/analysis/TypeChecker.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,7 +1751,9 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
17511751
else
17521752
_operation.annotation().type = result.get();
17531753
_operation.annotation().isConstant = false;
1754-
_operation.annotation().isPure = !modifying && *_operation.subExpression().annotation().isPure;
1754+
_operation.annotation().isPure =
1755+
!modifying &&
1756+
*_operation.subExpression().annotation().isPure;
17551757
_operation.annotation().isLValue = false;
17561758

17571759
return false;
@@ -3750,8 +3752,9 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
37503752
solAssert(m_errorReporter.hasErrors());
37513753
return;
37523754
}
3753-
solAssert(_usingFor.typeName()->annotation().type);
3754-
if (Declaration const* typeDefinition = _usingFor.typeName()->annotation().type->typeDefinition())
3755+
Type const* usingForType = _usingFor.typeName()->annotation().type;
3756+
solAssert(usingForType);
3757+
if (Declaration const* typeDefinition = usingForType->typeDefinition())
37553758
{
37563759
if (typeDefinition->scope() != m_currentSourceUnit)
37573760
m_errorReporter.typeError(
@@ -3785,10 +3788,12 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
37853788
return;
37863789
}
37873790

3788-
solAssert(_usingFor.typeName()->annotation().type);
3791+
Type const* usingForType = _usingFor.typeName()->annotation().type;
3792+
solAssert(usingForType);
3793+
37893794
Type const* normalizedType = TypeProvider::withLocationIfReference(
37903795
DataLocation::Storage,
3791-
_usingFor.typeName()->annotation().type
3796+
usingForType
37923797
);
37933798
solAssert(normalizedType);
37943799

@@ -3824,7 +3829,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
38243829
"The function \"{}\" cannot be bound to the type \"{}\" because the type cannot "
38253830
"be implicitly converted to the first argument of the function (\"{}\"){}",
38263831
joinHumanReadable(path->path(), "."),
3827-
_usingFor.typeName()->annotation().type->toString(true /* withoutDataLocation */),
3832+
usingForType->toString(true /* withoutDataLocation */),
38283833
functionType->selfType()->humanReadableName(),
38293834
result.message().empty() ? "." : ": " + result.message()
38303835
)

libsolidity/analysis/ViewPureChecker.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,23 @@ ViewPureChecker::MutabilityAndLocation const& ViewPureChecker::modifierMutabilit
323323
return m_inferredMutability.at(&_modifier);
324324
}
325325

326+
void ViewPureChecker::reportFunctionCallMutability(StateMutability _mutability, langutil::SourceLocation const& _location)
327+
{
328+
// We only require "nonpayable" to call a payable function.
329+
if (_mutability == StateMutability::Payable)
330+
_mutability = StateMutability::NonPayable;
331+
reportMutability(_mutability, _location);
332+
}
333+
326334
void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
327335
{
328336
if (*_functionCall.annotation().kind != FunctionCallKind::FunctionCall)
329337
return;
330338

331-
StateMutability mutability = dynamic_cast<FunctionType const&>(*_functionCall.expression().annotation().type).stateMutability();
332-
// We only require "nonpayable" to call a payble function.
333-
if (mutability == StateMutability::Payable)
334-
mutability = StateMutability::NonPayable;
335-
reportMutability(mutability, _functionCall.location());
339+
reportFunctionCallMutability(
340+
dynamic_cast<FunctionType const&>(*_functionCall.expression().annotation().type).stateMutability(),
341+
_functionCall.location()
342+
);
336343
}
337344

338345
bool ViewPureChecker::visit(MemberAccess const& _memberAccess)

libsolidity/analysis/ViewPureChecker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class ViewPureChecker: private ASTConstVisitor
7373
std::optional<langutil::SourceLocation> const& _nestedLocation = {}
7474
);
7575

76+
void reportFunctionCallMutability(StateMutability _mutability, langutil::SourceLocation const& _location);
77+
7678
/// Determines the mutability of modifier if not already cached.
7779
MutabilityAndLocation const& modifierMutability(ModifierDefinition const& _modifier);
7880

libsolidity/ast/Types.cpp

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <range/v3/view/reverse.hpp>
4949
#include <range/v3/view/tail.hpp>
5050
#include <range/v3/view/transform.hpp>
51+
#include <range/v3/view/filter.hpp>
5152

5253
#include <limits>
5354
#include <unordered_set>
@@ -337,7 +338,10 @@ Type const* Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
337338
return encodingType;
338339
}
339340

340-
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
341+
namespace
342+
{
343+
344+
vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, ASTNode const& _scope)
341345
{
342346
vector<UsingForDirective const*> usingForDirectives;
343347
SourceUnit const* sourceUnit = dynamic_cast<SourceUnit const*>(&_scope);
@@ -362,6 +366,25 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
362366
if (auto refType = dynamic_cast<ReferenceType const*>(&_type))
363367
typeLocation = refType->location();
364368

369+
return usingForDirectives | ranges::views::filter([&](UsingForDirective const* _directive) -> bool {
370+
// Convert both types to pointers for comparison to see if the `using for` directive applies.
371+
// Note that at this point we don't yet know if the functions are actually usable with the type.
372+
// `_type` may not be convertible to the function parameter type.
373+
return
374+
!_directive->typeName() ||
375+
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) ==
376+
*TypeProvider::withLocationIfReference(
377+
typeLocation,
378+
_directive->typeName()->annotation().type,
379+
true
380+
);
381+
}) | ranges::to<vector<UsingForDirective const*>>;
382+
}
383+
384+
}
385+
386+
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
387+
{
365388
MemberList::MemberMap members;
366389

367390
set<pair<string, Declaration const*>> seenFunctions;
@@ -381,27 +404,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
381404
members.emplace_back(&_function, asBoundFunction, *_name);
382405
};
383406

384-
for (UsingForDirective const* ufd: usingForDirectives)
385-
{
386-
// Convert both types to pointers for comparison to see if the `using for`
387-
// directive applies.
388-
// Further down, we check more detailed for each function if `_type` is
389-
// convertible to the function parameter type.
390-
if (
391-
ufd->typeName() &&
392-
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) !=
393-
*TypeProvider::withLocationIfReference(
394-
typeLocation,
395-
ufd->typeName()->annotation().type,
396-
true
397-
)
398-
)
399-
continue;
400-
401-
for (auto const& pathPointer: ufd->functionsOrLibrary())
407+
for (UsingForDirective const* ufd: usingForDirectivesForType(_type, _scope))
408+
for (auto const& identifierPath: ufd->functionsOrLibrary())
402409
{
403-
solAssert(pathPointer);
404-
Declaration const* declaration = pathPointer->annotation().referencedDeclaration;
410+
solAssert(identifierPath);
411+
Declaration const* declaration = identifierPath->annotation().referencedDeclaration;
405412
solAssert(declaration);
406413

407414
if (ContractDefinition const* library = dynamic_cast<ContractDefinition const*>(declaration))
@@ -417,10 +424,9 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
417424
else
418425
addFunction(
419426
dynamic_cast<FunctionDefinition const&>(*declaration),
420-
pathPointer->path().back()
427+
identifierPath->path().back()
421428
);
422429
}
423-
}
424430

425431
return members;
426432
}

0 commit comments

Comments
 (0)