Coverage Report

Created: 2025-06-24 07:59

/src/solidity/libyul/Scope.h
Line
Count
Source
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * Scopes for identifiers.
20
 */
21
22
#pragma once
23
24
#include <liblangutil/Exceptions.h>
25
26
#include <libyul/YulName.h>
27
28
#include <functional>
29
#include <memory>
30
#include <optional>
31
#include <variant>
32
33
namespace solidity::yul
34
{
35
36
struct Scope
37
{
38
  struct Variable
39
  {
40
    YulName name;
41
  };
42
  struct Function
43
  {
44
    size_t numArguments;
45
    size_t numReturns;
46
    YulName name;
47
  };
48
49
  using Identifier = std::variant<Variable, Function>;
50
51
  bool registerVariable(YulName _name);
52
  bool registerFunction(
53
    YulName _name,
54
    size_t _numArguments,
55
    size_t _numReturns
56
  );
57
58
  /// Looks up the identifier in this or super scopes and returns a valid pointer if found
59
  /// or a nullptr if not found. Variable lookups up across function boundaries will fail, as
60
  /// will any lookups across assembly boundaries.
61
  /// The pointer will be invalidated if the scope is modified.
62
  /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup
63
  Identifier* lookup(YulName _name);
64
  /// Looks up the identifier in this and super scopes (will not find variables across function
65
  /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns
66
  /// false if not found.
67
  template <class V>
68
  bool lookup(YulName _name, V const& _visitor)
69
18.4M
  {
70
18.4M
    if (Identifier* id = lookup(_name))
71
18.2M
    {
72
18.2M
      std::visit(_visitor, *id);
73
18.2M
      return true;
74
18.2M
    }
75
133k
    else
76
133k
      return false;
77
18.4M
  }
AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Variable const&)#1}, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Function const&)#1}> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Variable const&)#1}, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Function const&)#1}> const&)
Line
Count
Source
69
2.81M
  {
70
2.81M
    if (Identifier* id = lookup(_name))
71
2.80M
    {
72
2.80M
      std::visit(_visitor, *id);
73
2.80M
      return true;
74
2.80M
    }
75
11.5k
    else
76
11.5k
      return false;
77
2.81M
  }
AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_3> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_3> const&)
Line
Count
Source
69
6.97M
  {
70
6.97M
    if (Identifier* id = lookup(_name))
71
6.90M
    {
72
6.90M
      std::visit(_visitor, *id);
73
6.90M
      return true;
74
6.90M
    }
75
64.8k
    else
76
64.8k
      return false;
77
6.97M
  }
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_2> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_2> const&)
Line
Count
Source
69
458k
  {
70
458k
    if (Identifier* id = lookup(_name))
71
458k
    {
72
458k
      std::visit(_visitor, *id);
73
458k
      return true;
74
458k
    }
75
0
    else
76
0
      return false;
77
458k
  }
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_4> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_4> const&)
Line
Count
Source
69
1.37M
  {
70
1.37M
    if (Identifier* id = lookup(_name))
71
1.31M
    {
72
1.31M
      std::visit(_visitor, *id);
73
1.31M
      return true;
74
1.31M
    }
75
57.1k
    else
76
57.1k
      return false;
77
1.37M
  }
Unexecuted instantiation: SSAControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_21, solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_22> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_21, solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_22> const&)
Unexecuted instantiation: SSAControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_23, solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_24> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_23, solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_24> const&)
VariableReferenceCounter.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_2> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_2> const&)
Line
Count
Source
69
887k
  {
70
887k
    if (Identifier* id = lookup(_name))
71
887k
    {
72
887k
      std::visit(_visitor, *id);
73
887k
      return true;
74
887k
    }
75
0
    else
76
0
      return false;
77
887k
  }
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_14> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_14> const&)
Line
Count
Source
69
933k
  {
70
933k
    if (Identifier* id = lookup(_name))
71
933k
    {
72
933k
      std::visit(_visitor, *id);
73
933k
      return true;
74
933k
    }
75
0
    else
76
0
      return false;
77
933k
  }
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_16> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_16> const&)
Line
Count
Source
69
4.97M
  {
70
4.97M
    if (Identifier* id = lookup(_name))
71
4.97M
    {
72
4.97M
      std::visit(_visitor, *id);
73
4.97M
      return true;
74
4.97M
    }
75
0
    else
76
0
      return false;
77
4.97M
  }
78
  /// @returns true if the name exists in this scope or in super scopes (also searches
79
  /// across function and assembly boundaries).
80
  bool exists(YulName _name) const;
81
82
  /// @returns the number of variables directly registered inside the scope.
83
  size_t numberOfVariables() const;
84
  /// @returns true if this scope is inside a function.
85
  bool insideFunction() const;
86
87
  Scope* superScope = nullptr;
88
  /// If true, variables from the super scope are not visible here (other identifiers are),
89
  /// but they are still taken into account to prevent shadowing.
90
  bool functionScope = false;
91
  std::map<YulName, Identifier> identifiers;
92
};
93
94
}