Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1632,10 +1632,13 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
resultType = builtinResult;
else if (!matchingDefinitions.empty())
{
// This is checked along with `using for` directive but the error is not fatal.
if (matchingDefinitions.size() != 1)
solAssert(m_errorReporter.hasErrors());

// Duplicate user-defined operator bindings are flagged later by
// endVisit(UsingForDirective) (error 4705). When a function body that
// uses the operator is type-checked before the directive is fully
// processed (e.g. for self-referential `using for` definitions), no
// error has been emitted yet and the previous solAssert(hasErrors())
// triggered an ICE. Pick the first match and let the directive's own
// duplicate check surface the error.
operatorDefinition = *matchingDefinitions.begin();
}
else
Expand Down Expand Up @@ -1697,10 +1700,13 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
commonType = builtinResult.get();
else if (!matchingDefinitions.empty())
{
// This is checked along with `using for` directive but the error is not fatal.
if (matchingDefinitions.size() != 1)
solAssert(m_errorReporter.hasErrors());

// Duplicate user-defined operator bindings are flagged later by
// endVisit(UsingForDirective) (error 4705). When a function body that
// uses the operator is type-checked before the directive is fully
// processed (e.g. for self-referential `using for` definitions), no
// error has been emitted yet and the previous solAssert(hasErrors())
// triggered an ICE. Pick the first match and let the directive's own
// duplicate check surface the error.
operatorDefinition = *matchingDefinitions.begin();

// Set common type to the type used in the `using for` directive.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Used to cause ICE in TypeChecker::endVisit(BinaryOperation) when a
// function body referenced an operator that had multiple matching
// `using for` definitions before the directive's own duplicate check
// (error 4705) had a chance to run.
type T is int256;
function sub(T a, T b) pure returns (T) {}
function add(T a, T b) pure returns (T) { T c = a + b; c; }
using {sub as +, add as +} for T global;
// ----
// TypeError 4705: (267-270): User-defined binary operator + has more than one definition matching the operand type visible in the current scope.
// TypeError 4705: (277-280): User-defined binary operator + has more than one definition matching the operand type visible in the current scope.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Used to cause ICE in TypeChecker::visit(UnaryOperation) when a function
// body referenced an operator that had multiple matching `using for`
// definitions before the directive's own duplicate check (error 4705)
// had a chance to run.
type T is int256;
function neg1(T a) pure returns (T) { return -a; }
function neg2(T a) pure returns (T) { return a; }
using {neg1 as -, neg2 as -} for T global;
// ----
// TypeError 4705: (262-266): User-defined unary operator - has more than one definition matching the operand type visible in the current scope.
// TypeError 4705: (273-277): User-defined unary operator - has more than one definition matching the operand type visible in the current scope.