| 669 | } |
| 670 | |
| 671 | void AsmAnalyzer::checkAssignment(Identifier const& _variable) |
| 672 | { |
| 673 | yulAssert(!_variable.name.empty()); |
| 674 | auto watcher = m_errorReporter.errorWatcher(); |
| 675 | bool hasVariable = false; |
| 676 | bool found = false; |
| 677 | if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name)) |
| 678 | { |
| 679 | if (m_resolver) |
| 680 | // We found a local reference, make sure there is no external reference. |
| 681 | // Used for side effects, e.g., error reporting in TypeChecker, hence ignoring return value |
| 682 | std::ignore = m_resolver( |
| 683 | _variable, |
| 684 | yul::IdentifierContext::NonExternal, |
| 685 | m_currentScope->insideFunction() |
| 686 | ); |
| 687 | |
| 688 | if (!std::holds_alternative<Scope::Variable>(*var)) |
| 689 | m_errorReporter.typeError(2657_error, nativeLocationOf(_variable), "Assignment requires variable."); |
| 690 | else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var))) |
| 691 | m_errorReporter.declarationError( |
| 692 | 1133_error, |
| 693 | nativeLocationOf(_variable), |
| 694 | fmt::format("Variable {} used before it was declared.", _variable.name.str()) |
| 695 | ); |
| 696 | else |
| 697 | hasVariable = true; |
| 698 | found = true; |
| 699 | } |
| 700 | else if (m_resolver) |
| 701 | { |
| 702 | bool insideFunction = m_currentScope->insideFunction(); |
| 703 | if (m_resolver(_variable, yul::IdentifierContext::LValue, insideFunction)) |
| 704 | { |
| 705 | found = true; |
| 706 | hasVariable = true; |
| 707 | } |
| 708 | } |
| 709 | |
| 710 | if (!found && watcher.ok()) |
| 711 | // Only add message if the callback did not. |
| 712 | m_errorReporter.declarationError(4634_error, nativeLocationOf(_variable), "Variable not found or variable not lvalue."); |
| 713 | |
| 714 | yulAssert(!watcher.ok() || hasVariable, ""); |
| 715 | } |
| 716 | |
| 717 | Scope& AsmAnalyzer::scope(Block const* _block) |
| 718 | { |
nothing calls this directly
no test coverage detected