Coverage Report

Created: 2022-08-24 06:43

/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/YulString.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
  using YulType = YulString;
39
40
  struct Variable
41
  {
42
    YulType type;
43
    YulString name;
44
  };
45
  struct Function
46
  {
47
    std::vector<YulType> arguments;
48
    std::vector<YulType> returns;
49
    YulString name;
50
  };
51
52
  using Identifier = std::variant<Variable, Function>;
53
54
  bool registerVariable(YulString _name, YulType const& _type);
55
  bool registerFunction(
56
    YulString _name,
57
    std::vector<YulType> _arguments,
58
    std::vector<YulType> _returns
59
  );
60
61
  /// Looks up the identifier in this or super scopes and returns a valid pointer if found
62
  /// or a nullptr if not found. Variable lookups up across function boundaries will fail, as
63
  /// will any lookups across assembly boundaries.
64
  /// The pointer will be invalidated if the scope is modified.
65
  /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup
66
  Identifier* lookup(YulString _name);
67
  /// Looks up the identifier in this and super scopes (will not find variables across function
68
  /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns
69
  /// false if not found.
70
  template <class V>
71
  bool lookup(YulString _name, V const& _visitor)
72
2.97M
  {
73
2.97M
    if (Identifier* id = lookup(_name))
74
2.92M
    {
75
2.92M
      std::visit(_visitor, *id);
76
2.92M
      return true;
77
2.92M
    }
78
56.5k
    else
79
56.5k
      return false;
80
2.97M
  }
AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_0, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_1> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_0, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_1> const&)
Line
Count
Source
72
1.51M
  {
73
1.51M
    if (Identifier* id = lookup(_name))
74
1.48M
    {
75
1.48M
      std::visit(_visitor, *id);
76
1.48M
      return true;
77
1.48M
    }
78
28.1k
    else
79
28.1k
      return false;
80
1.51M
  }
AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_4, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_5> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_4, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_5> const&)
Line
Count
Source
72
338k
  {
73
338k
    if (Identifier* id = lookup(_name))
74
337k
    {
75
337k
      std::visit(_visitor, *id);
76
337k
      return true;
77
337k
    }
78
415
    else
79
415
      return false;
80
338k
  }
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_0, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_0, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1> const&)
Line
Count
Source
72
84.7k
  {
73
84.7k
    if (Identifier* id = lookup(_name))
74
84.7k
    {
75
84.7k
      std::visit(_visitor, *id);
76
84.7k
      return true;
77
84.7k
    }
78
0
    else
79
0
      return false;
80
84.7k
  }
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3> const&)
Line
Count
Source
72
422k
  {
73
422k
    if (Identifier* id = lookup(_name))
74
394k
    {
75
394k
      std::visit(_visitor, *id);
76
394k
      return true;
77
394k
    }
78
27.9k
    else
79
27.9k
      return false;
80
422k
  }
VariableReferenceCounter.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_0, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_0, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1> const&)
Line
Count
Source
72
287k
  {
73
287k
    if (Identifier* id = lookup(_name))
74
287k
    {
75
287k
      std::visit(_visitor, *id);
76
287k
      return true;
77
287k
    }
78
4
    else
79
4
      return false;
80
287k
  }
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_12, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_12, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13> const&)
Line
Count
Source
72
11.8k
  {
73
11.8k
    if (Identifier* id = lookup(_name))
74
11.8k
    {
75
11.8k
      std::visit(_visitor, *id);
76
11.8k
      return true;
77
11.8k
    }
78
0
    else
79
0
      return false;
80
11.8k
  }
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_14, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_14, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15> const&)
Line
Count
Source
72
320k
  {
73
320k
    if (Identifier* id = lookup(_name))
74
320k
    {
75
320k
      std::visit(_visitor, *id);
76
320k
      return true;
77
320k
    }
78
0
    else
79
0
      return false;
80
320k
  }
81
  /// @returns true if the name exists in this scope or in super scopes (also searches
82
  /// across function and assembly boundaries).
83
  bool exists(YulString _name) const;
84
85
  /// @returns the number of variables directly registered inside the scope.
86
  size_t numberOfVariables() const;
87
  /// @returns true if this scope is inside a function.
88
  bool insideFunction() const;
89
90
  Scope* superScope = nullptr;
91
  /// If true, variables from the super scope are not visible here (other identifiers are),
92
  /// but they are still taken into account to prevent shadowing.
93
  bool functionScope = false;
94
  std::map<YulString, Identifier> identifiers;
95
};
96
97
}