Compare commits

..

No commits in common. "develop" and "v0.8.21" have entirely different histories.

840 changed files with 12246 additions and 16123 deletions

View File

@ -179,199 +179,47 @@ commands:
paths:
- << parameters.install_path >>
# --------------------------------------------------------------------------
# Build Commands
defaults:
setup_prerelease_commit_hash:
steps:
- run:
# --------------------------------------------------------------------------
# Build Templates
- setup_prerelease_commit_hash: &setup_prerelease_commit_hash
name: Store commit hash and prerelease
command: |
if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG ]]; then
echo -n > prerelease.txt;
else
date -u +"nightly.%Y.%-m.%-d" > prerelease.txt;
fi
if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
echo -n "$CIRCLE_SHA1" > commit_hash.txt
run_build:
steps:
- run:
- run_build: &run_build
name: Build
command: scripts/ci/build.sh
run_build_ossfuzz:
steps:
- run:
- run_build_ossfuzz: &run_build_ossfuzz
name: Build_ossfuzz
command: scripts/ci/build_ossfuzz.sh
run_proofs:
steps:
- run:
- run_proofs: &run_proofs
name: Correctness proofs for optimization rules
command: scripts/run_proofs.sh
run_soltest:
steps:
- run:
- run_soltest: &run_soltest
name: soltest
no_output_timeout: 30m
command: .circleci/soltest.sh
command: ./.circleci/soltest.sh
run_soltest_all:
steps:
- run:
- run_soltest_all: &run_soltest_all
name: soltest_all
no_output_timeout: 30m
command: .circleci/soltest_all.sh
command: ./.circleci/soltest_all.sh
run_cmdline_tests:
steps:
- run:
- run_cmdline_tests: &run_cmdline_tests
name: command line tests
no_output_timeout: 30m
command: .circleci/parallel_cli_tests.py
run_docs_pragma_min_version:
steps:
- run:
- run_docs_pragma_min_version: &run_docs_pragma_min_version
name: docs pragma version check
command: scripts/docs_version_pragma_check.sh
# --------------------------------------------------------------------------
# Artifact Commands
store_artifacts_solc:
description: Store compiled solc executable as artifact
steps:
- store_artifacts:
path: build/solc/solc
destination: solc
store_artifacts_yul_phaser:
steps:
- store_artifacts:
path: build/tools/yul-phaser
destination: yul-phaser
persist_executables_to_workspace:
description: Persist compiled target executables to workspace
steps:
- persist_to_workspace:
root: build
paths:
- solc/solc
- test/soltest
- test/tools/solfuzzer
persist_executables_to_workspace_osx:
description: Persist compiled target executables to workspace on macOS
steps:
- persist_to_workspace:
root: .
paths:
- build/solc/solc
- build/test/soltest
- build/test/tools/solfuzzer
persist_ossfuzz_executables_to_workspace:
description: Persist compiled OSSFUZZ executables to workspace
steps:
- persist_to_workspace:
root: build
paths:
- test/tools/ossfuzz/abiv2_proto_ossfuzz
- test/tools/ossfuzz/abiv2_isabelle_ossfuzz
- test/tools/ossfuzz/const_opt_ossfuzz
- test/tools/ossfuzz/solc_mutator_ossfuzz
- test/tools/ossfuzz/solc_ossfuzz
- test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
- test/tools/ossfuzz/strictasm_diff_ossfuzz
- test/tools/ossfuzz/strictasm_opt_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
- test/tools/ossfuzz/yul_proto_ossfuzz
- test/tools/ossfuzz/sol_proto_ossfuzz
store_artifacts_test_results:
description: Store test output dir as artifact
steps:
- store_artifacts:
path: test_results/
destination: test_results/
# --------------------------------------------------------------------------
# Complex Build Commands
soltest:
steps:
- checkout
- attach_workspace:
at: build
# NOTE: Different build jobs produce different soltest executables (release/debug,
# clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the
# attached workspace and we only see the items added to the workspace by jobs we depend on.
- run_soltest
- store_test_results:
path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr
test_lsp:
steps:
- checkout
- attach_workspace:
at: build
- run:
name: Install dependencies
command: pip install --user deepdiff colorama
- run:
name: Executing solc LSP test suite
command: test/lsp.py build/solc/solc --non-interactive
- matrix_notify_failure_unless_pr
build:
steps:
- checkout
- run_build
- store_artifacts_solc
- store_artifacts_yul_phaser
- persist_executables_to_workspace
- matrix_notify_failure_unless_pr
soltest_all:
steps:
- checkout
- attach_workspace:
at: build
- run_soltest_all
- store_test_results:
path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr
cmdline_tests:
steps:
- checkout
- attach_workspace:
at: build
- run_cmdline_tests
- store_test_results:
path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr
install_dependencies_osx:
steps:
# FIXME: We used to cache dependencies on macOS but now it takes longer than just installing
# them each time. See https://github.com/ethereum/solidity/issues/12925.
- run:
name: Install build dependencies
command: .circleci/osx_install_dependencies.sh
defaults:
command: ./scripts/docs_version_pragma_check.sh
# --------------------------------------------------------------------------
# Matrix templates
@ -393,6 +241,122 @@ defaults:
- via-ir-no-optimize
# --------------------------------------------------------------------------
# Artifacts Templates
# compiled solc executable target
- artifacts_solc: &artifacts_solc
path: build/solc/solc
destination: solc
# windows artifacts
- artifact_solc_windows: &artifact_solc_windows
path: upload/
- artifact_yul_phaser: &artifact_yul_phaser
path: build/tools/yul-phaser
destination: yul-phaser
# compiled executable targets
- artifacts_executables: &artifacts_executables
root: build
paths:
- solc/solc
- test/soltest
- test/tools/solfuzzer
# compiled OSSFUZZ targets
- artifacts_executables_ossfuzz: &artifacts_executables_ossfuzz
root: build
paths:
- test/tools/ossfuzz/abiv2_proto_ossfuzz
- test/tools/ossfuzz/abiv2_isabelle_ossfuzz
- test/tools/ossfuzz/const_opt_ossfuzz
- test/tools/ossfuzz/solc_mutator_ossfuzz
- test/tools/ossfuzz/solc_ossfuzz
- test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
- test/tools/ossfuzz/strictasm_diff_ossfuzz
- test/tools/ossfuzz/strictasm_opt_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
- test/tools/ossfuzz/yul_proto_ossfuzz
- test/tools/ossfuzz/sol_proto_ossfuzz
# test result output directory
- artifacts_test_results: &artifacts_test_results
path: test_results/
destination: test_results/
# --------------------------------------------------------------------------
# Step Templates
# store_test_results helper
- store_test_results: &store_test_results
path: test_results/
- steps_soltest: &steps_soltest
steps:
- checkout
- attach_workspace:
at: build
# NOTE: Different build jobs produce different soltest executables (release/debug,
# clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the
# attached workspace and we only see the items added to the workspace by jobs we depend on.
- run: *run_soltest
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
- steps_test_lsp: &steps_test_lsp
steps:
- checkout
- attach_workspace:
at: build
- run:
name: Install dependencies
command: pip install --user deepdiff colorama
- run:
name: Executing solc LSP test suite
command: ./test/lsp.py ./build/solc/solc --non-interactive
- matrix_notify_failure_unless_pr
- steps_build: &steps_build
steps:
- checkout
- run: *run_build
- store_artifacts: *artifacts_solc
- store_artifacts: *artifact_yul_phaser
- persist_to_workspace: *artifacts_executables
- matrix_notify_failure_unless_pr
- steps_soltest_all: &steps_soltest_all
steps:
- checkout
- attach_workspace:
at: build
- run: *run_soltest_all
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
- steps_cmdline_tests: &steps_cmdline_tests
steps:
- checkout
- attach_workspace:
at: build
- run: *run_cmdline_tests
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
- steps_install_dependencies_osx: &steps_install_dependencies_osx
steps:
# FIXME: We used to cache dependencies on macOS but now it takes longer than just installing
# them each time. See https://github.com/ethereum/solidity/issues/12925.
- run:
name: Install build dependencies
command: ./.circleci/osx_install_dependencies.sh
# --------------------------------------------------------------------------
# Base Image Templates
@ -402,7 +366,6 @@ defaults:
environment: &base_archlinux_env
TERM: xterm
MAKEFLAGS: -j 3
CPUs: 3
- base_archlinux_large: &base_archlinux_large
<<: *base_archlinux
@ -410,7 +373,6 @@ defaults:
environment: &base_archlinux_large_env
<<: *base_archlinux_env
MAKEFLAGS: -j 5
CPUs: 5
- base_cimg_small: &base_cimg_small
docker:
@ -419,7 +381,6 @@ defaults:
environment: &base_cimg_small_env
TERM: xterm
MAKEFLAGS: -j 2
CPUs: 2
- base_ems_large: &base_ems_large
docker:
@ -428,7 +389,6 @@ defaults:
environment: &base_ems_large_env
TERM: xterm
MAKEFLAGS: -j 5
CPUs: 5
- base_node_small: &base_node_small
docker:
@ -437,7 +397,6 @@ defaults:
environment: &base_node_small_env
TERM: xterm
MAKEFLAGS: -j 2
CPUs: 2
- base_osx: &base_osx
macos:
@ -446,7 +405,6 @@ defaults:
environment: &base_osx_env
TERM: xterm
MAKEFLAGS: -j5
CPUs: 5
- base_osx_large: &base_osx_large
<<: *base_osx
@ -454,7 +412,6 @@ defaults:
environment: &base_osx_large_env
<<: *base_osx_env
MAKEFLAGS: -j10
CPUs: 10
- base_python_small: &base_python_small
docker:
@ -463,7 +420,6 @@ defaults:
environment: &base_python_small_env
TERM: xterm
MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu_clang: &base_ubuntu_clang
docker:
@ -471,7 +427,6 @@ defaults:
environment: &base_ubuntu_clang_env
TERM: xterm
MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu_clang_small: &base_ubuntu_clang_small
<<: *base_ubuntu_clang
@ -479,7 +434,6 @@ defaults:
environment: &base_ubuntu_clang_small_env
<<: *base_ubuntu_clang_env
MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu2004: &base_ubuntu2004
docker:
@ -487,7 +441,6 @@ defaults:
environment: &base_ubuntu2004_env
TERM: xterm
MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu2004_small: &base_ubuntu2004_small
<<: *base_ubuntu2004
@ -495,7 +448,6 @@ defaults:
environment: &base_ubuntu2004_small_env
<<: *base_ubuntu2004_env
MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu2004_xlarge: &base_ubuntu2004_xlarge
<<: *base_ubuntu2004
@ -503,7 +455,6 @@ defaults:
environment: &base_ubuntu2004_xlarge_env
<<: *base_ubuntu2004_env
MAKEFLAGS: -j 10
CPUs: 10
- base_ubuntu2204: &base_ubuntu2204
docker:
@ -511,7 +462,6 @@ defaults:
environment: &base_ubuntu2204_env
TERM: xterm
MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu2204_clang: &base_ubuntu2204_clang
docker:
@ -521,7 +471,6 @@ defaults:
CC: clang
CXX: clang++
MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large
<<: *base_ubuntu2204_clang
@ -529,7 +478,6 @@ defaults:
environment: &base_ubuntu2204_clang_large_env
<<: *base_ubuntu2204_clang_env
MAKEFLAGS: -j 5
CPUs: 5
- base_ubuntu2204_small: &base_ubuntu2204_small
<<: *base_ubuntu2204
@ -537,7 +485,6 @@ defaults:
environment: &base_ubuntu2204_small_env
<<: *base_ubuntu2204_env
MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu2204_large: &base_ubuntu2204_large
<<: *base_ubuntu2204
@ -545,7 +492,6 @@ defaults:
environment: &base_ubuntu2204_large_env
<<: *base_ubuntu2204_env
MAKEFLAGS: -j 5
CPUs: 5
- base_ubuntu2204_xlarge: &base_ubuntu2204_xlarge
<<: *base_ubuntu2204
@ -553,7 +499,6 @@ defaults:
environment: &base_ubuntu2204_xlarge_env
<<: *base_ubuntu2204_env
MAKEFLAGS: -j 10
CPUs: 10
- base_win: &base_win
executor:
@ -746,7 +691,7 @@ defaults:
name: t_native_test_ext_prb_math
project: prb-math
binary_type: native
image: cimg/rust:1.70
image: cimg/node:18.16
- job_native_test_ext_elementfi: &job_native_test_ext_elementfi
<<: *requires_b_ubu_static
@ -803,11 +748,7 @@ jobs:
pip install --user codespell
- run:
name: Check spelling
command: |
~/.local/bin/codespell \
--skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" \
--ignore-words scripts/codespell_whitelist.txt \
--exclude-file scripts/codespell_ignored_lines.txt
command: ~/.local/bin/codespell --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" --ignore-words ./scripts/codespell_whitelist.txt --exclude-file ./scripts/codespell_ignored_lines.txt
- matrix_notify_failure_unless_pr
chk_docs_examples:
@ -821,7 +762,7 @@ jobs:
command: sudo npm install -g solhint
- run:
name: Test Docs examples
command: test/docsCodeStyle.sh
command: ./test/docsCodeStyle.sh
- matrix_notify_failure_unless_pr
chk_coding_style:
@ -835,13 +776,13 @@ jobs:
sudo apt install -y shellcheck
- run:
name: Check for C++ coding style
command: scripts/check_style.sh
command: ./scripts/check_style.sh
- run:
name: checking shell scripts
command: scripts/chk_shellscripts/chk_shellscripts.sh
command: ./scripts/chk_shellscripts/chk_shellscripts.sh
- run:
name: Check for broken symlinks
command: scripts/check_symlinks.sh
command: ./scripts/check_symlinks.sh
- matrix_notify_failure_unless_pr
chk_errorcodes:
@ -850,7 +791,7 @@ jobs:
- checkout
- run:
name: Check for error codes
command: scripts/error_codes.py --check
command: ./scripts/error_codes.py --check
- matrix_notify_failure_unless_pr
chk_pylint:
@ -870,7 +811,7 @@ jobs:
- run: pylint --version
- run:
name: Linting Python Scripts
command: scripts/pylint_all.py
command: ./scripts/pylint_all.py
- matrix_notify_failure_unless_pr
chk_antlr_grammar:
@ -884,7 +825,7 @@ jobs:
sudo apt install -y openjdk-17-jdk
- run:
name: Run tests
command: scripts/test_antlr_grammar.sh
command: ./scripts/test_antlr_grammar.sh
- matrix_notify_failure_unless_pr
chk_buglist:
@ -899,7 +840,7 @@ jobs:
npm install mktemp
- run:
name: Test buglist
command: test/buglistTests.js
command: ./test/buglistTests.js
- matrix_notify_failure_unless_pr
chk_proofs:
@ -908,14 +849,14 @@ jobs:
- checkout
- install_python3:
packages: z3-solver
- run_proofs
- run: *run_proofs
- matrix_notify_failure_unless_pr
chk_docs_pragma_min_version:
<<: *base_ubuntu2204_small
steps:
- checkout
- run_docs_pragma_min_version
- run: *run_docs_pragma_min_version
- matrix_notify_failure_unless_pr
t_ubu_pyscripts:
@ -941,8 +882,7 @@ jobs:
# this runs 2x faster on xlarge but takes 4x more resources (compared to medium).
# Enough other jobs depend on it that it's worth it though.
<<: *base_ubuntu2204_xlarge
steps:
- build
<<: *steps_build
# x64 ASAN build, for testing for memory related bugs
b_ubu_asan: &b_ubu_asan
@ -952,16 +892,14 @@ jobs:
<<: *base_ubuntu2204_env
CMAKE_OPTIONS: -DSANITIZE=address
CMAKE_BUILD_TYPE: Release
steps:
- build
<<: *steps_build
b_ubu_clang: &b_ubu_clang
<<: *base_ubuntu2204_clang_large
environment:
<<: *base_ubuntu2204_clang_large_env
MAKEFLAGS: -j 10
steps:
- build
<<: *steps_build
b_ubu_san_clang:
# This runs a bit faster on large and xlarge but on nightly efficiency matters more.
@ -972,8 +910,7 @@ jobs:
environment:
<<: *base_ubuntu2204_clang_env
CMAKE_OPTIONS: << parameters.cmake_options >>
steps:
- build
<<: *steps_build
b_ubu_force_release: &b_ubu_force_release
<<: *b_ubu
@ -992,7 +929,7 @@ jobs:
CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON
steps:
- checkout
- run_build
- run: *run_build
- run:
name: strip binary
command: strip build/solc/solc
@ -1015,8 +952,8 @@ jobs:
CMAKE_BUILD_TYPE: Debug
steps:
- checkout
- run_build
- persist_executables_to_workspace
- run: *run_build
- persist_to_workspace: *artifacts_executables
- matrix_notify_failure_unless_pr
t_ubu_codecov:
@ -1035,11 +972,11 @@ jobs:
- run:
name: "Code Coverage: Syntax Tests"
command: codecov --flags syntax --gcov-root build
- run_soltest
- run: *run_soltest
- run:
name: "Coverage: All"
command: codecov --flags all --gcov-root build
- store_artifacts_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
# Builds in C++20 mode and uses debug build in order to speed up.
@ -1053,16 +990,16 @@ jobs:
MAKEFLAGS: -j 10
steps:
- checkout
- run_build
- run: *run_build
- matrix_notify_failure_unless_pr
b_ubu_ossfuzz: &b_ubu_ossfuzz
<<: *base_ubuntu_clang
steps:
- checkout
- setup_prerelease_commit_hash
- run_build_ossfuzz
- persist_ossfuzz_executables_to_workspace
- run: *setup_prerelease_commit_hash
- run: *run_build_ossfuzz
- persist_to_workspace: *artifacts_executables_ossfuzz
- matrix_notify_failure_unless_pr
t_ubu_ossfuzz: &t_ubu_ossfuzz
@ -1077,9 +1014,8 @@ jobs:
git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus
mkdir -p test_results
scripts/regressions.py -o test_results
- store_test_results:
path: test_results/
- store_artifacts_test_results
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
b_archlinux:
<<: *base_archlinux_large
@ -1093,9 +1029,9 @@ jobs:
command: |
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar
- checkout
- run_build
- store_artifacts_solc
- persist_executables_to_workspace
- run: *run_build
- store_artifacts: *artifacts_solc
- persist_to_workspace: *artifacts_executables
- matrix_notify_failure_unless_pr
b_osx:
@ -1105,11 +1041,18 @@ jobs:
CMAKE_BUILD_TYPE: Release
steps:
- checkout
- install_dependencies_osx
- run_build
- store_artifacts_solc
- store_artifacts_yul_phaser
- persist_executables_to_workspace_osx
- when:
condition: true
<<: *steps_install_dependencies_osx
- run: *run_build
- store_artifacts: *artifacts_solc
- store_artifacts: *artifact_yul_phaser
- persist_to_workspace:
root: .
paths:
- build/solc/solc
- build/test/soltest
- build/test/tools/solfuzzer
- matrix_notify_failure_unless_pr
t_osx_soltest: &t_osx_soltest
@ -1120,13 +1063,14 @@ jobs:
OPTIMIZE: 0
steps:
- checkout
- install_dependencies_osx
- when:
condition: true
<<: *steps_install_dependencies_osx
- attach_workspace:
at: .
- run_soltest
- store_test_results:
path: test_results/
- store_artifacts_test_results
- run: *run_soltest
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
t_osx_cli:
@ -1134,11 +1078,13 @@ jobs:
parallelism: 7 # Should match number of tests in .circleci/cli.sh
steps:
- checkout
- install_dependencies_osx
- when:
condition: true
<<: *steps_install_dependencies_osx
- attach_workspace:
at: .
- run_cmdline_tests
- store_artifacts_test_results
- run: *run_cmdline_tests
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
b_ems:
@ -1169,10 +1115,10 @@ jobs:
<<: *base_ubuntu2204_small
steps:
- checkout
- setup_prerelease_commit_hash
- run: *setup_prerelease_commit_hash
- run:
name: Build documentation
command: docs/docs.sh
command: ./docs/docs.sh
- store_artifacts:
path: docs/_build/html/
destination: docs-html
@ -1181,13 +1127,11 @@ jobs:
t_ubu_soltest_all: &t_ubu_soltest_all
<<: *base_ubuntu2204_large
parallelism: 50
steps:
- soltest_all
<<: *steps_soltest_all
t_ubu_lsp: &t_ubu_lsp
<<: *base_ubuntu2204_small
steps:
- test_lsp
<<: *steps_test_lsp
t_archlinux_soltest: &t_archlinux_soltest
<<: *base_archlinux
@ -1204,7 +1148,9 @@ jobs:
name: Install runtime dependencies
command: |
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
- soltest
- when:
condition: true
<<: *steps_soltest
t_ubu_clang_soltest: &t_ubu_clang_soltest
<<: *base_ubuntu2204_clang
@ -1216,8 +1162,7 @@ jobs:
# The high parallelism in this job is causing the SMT tests to run out of memory,
# so disabling for now.
SOLTEST_FLAGS: --no-smt
steps:
- soltest
<<: *steps_soltest
t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all
# NOTE: This definition is identical to t_ubu_soltest_all but in the workflow we make it depend on
@ -1227,8 +1172,7 @@ jobs:
t_ubu_cli: &t_ubu_cli
<<: *base_ubuntu2204_small
parallelism: 7 # Should match number of tests in .circleci/cli.sh
steps:
- cmdline_tests
<<: *steps_cmdline_tests
t_ubu_force_release_cli: &t_ubu_force_release_cli
<<: *t_ubu_cli
@ -1252,8 +1196,7 @@ jobs:
# Suppress CLN memory leak.
# See: https://github.com/ethereum/solidity/issues/13891 for details.
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0
steps:
- cmdline_tests
<<: *steps_cmdline_tests
t_ubu_asan_soltest:
<<: *base_ubuntu2204
@ -1267,8 +1210,7 @@ jobs:
# Suppress CLN memory leak.
# See: https://github.com/ethereum/solidity/issues/13891 for details.
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp
steps:
- soltest
<<: *steps_soltest
t_ubu_asan_clang_soltest:
<<: *base_ubuntu2204_clang
@ -1279,8 +1221,7 @@ jobs:
OPTIMIZE: 0
SOLTEST_FLAGS: --no-smt
ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
steps:
- soltest
<<: *steps_soltest
t_ubu_ubsan_clang_soltest:
<<: *base_ubuntu2204_clang
@ -1289,14 +1230,12 @@ jobs:
<<: *base_ubuntu2204_clang_env
EVM: << pipeline.parameters.evm-version >>
SOLTEST_FLAGS: --no-smt
steps:
- soltest
<<: *steps_soltest
t_ubu_ubsan_clang_cli:
<<: *base_ubuntu2204_clang
parallelism: 7 # Should match number of tests in .circleci/cli.sh
steps:
- cmdline_tests
<<: *steps_cmdline_tests
t_ems_solcjs:
# Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small).
@ -1520,8 +1459,7 @@ jobs:
name: "Run solc.exe to make sure build was successful."
command: .\build\solc\Release\solc.exe --version
shell: powershell.exe
- store_artifacts:
path: upload/
- store_artifacts: *artifact_solc_windows
- persist_to_workspace:
root: build
paths:
@ -1550,11 +1488,10 @@ jobs:
command: python -m pip install --user deepdiff colorama
- run:
name: Executing solc LSP test suite
command: python test/lsp.py build\solc\Release\solc.exe --non-interactive
command: python ./test/lsp.py .\build\solc\Release\solc.exe --non-interactive
shell: powershell.exe
- store_test_results:
path: test_results/
- store_artifacts_test_results
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
# Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu
@ -1787,13 +1724,11 @@ workflows:
- t_native_test_ext_yield_liquidator
- t_native_test_ext_perpetual_pools
- t_native_test_ext_uniswap
- t_native_test_ext_prb_math
- t_native_test_ext_elementfi
- t_native_test_ext_brink
# NOTE: We are disabling gp2 tests due to constant failures.
#- t_native_test_ext_gp2
# TODO: Dropping prb-math from the benchmarks since it is not implemented yet
# in the new Foundry external testing infrastructure.
# - t_native_test_ext_prb_math
# NOTE: The external tests below were commented because they
# depend on a specific version of hardhat which does not support shanghai EVM.
#- t_native_test_ext_trident

View File

@ -52,8 +52,6 @@ function validate_checksum {
if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not restored), rebuild dependencies
then
brew update
brew upgrade
brew install boost
brew install cmake
brew install wget

View File

@ -36,7 +36,6 @@ set -e
OPTIMIZE=${OPTIMIZE:-"0"}
EVM=${EVM:-"invalid"}
CPUs=${CPUs:-3}
REPODIR="$(realpath "$(dirname "$0")/..")"
IFS=" " read -r -a BOOST_TEST_ARGS <<< "$BOOST_TEST_ARGS"
@ -68,6 +67,7 @@ get_logfile_basename() {
# long-running test cases are next to each other.
CIRCLE_NODE_INDEX=$(((CIRCLE_NODE_INDEX + 23 * INDEX_SHIFT) % CIRCLE_NODE_TOTAL))
CPUs=3
PIDs=()
for run in $(seq 0 $((CPUs - 1)))
do

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.13.0)
set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake" CACHE PATH "The path to the cmake directory")
set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake" CACHE PATH "The the path to the cmake directory")
list(APPEND CMAKE_MODULE_PATH ${ETH_CMAKE_DIR})
# Set the build type, if none was specified.
@ -21,7 +21,7 @@ include(EthPolicy)
eth_policy()
# project name and version should be set after cmake_policy CMP0048
set(PROJECT_VERSION "0.8.22")
set(PROJECT_VERSION "0.8.21")
# OSX target needed in order to support std::visit
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)

View File

@ -1,23 +1,3 @@
### 0.8.22 (unreleased)
Language Features:
* Allow defining events at file level.
Compiler Features:
* Parser: Remove the experimental error recovery mode (``--error-recovery`` / ``settings.parserErrorRecovery``).
* Yul Optimizer: If ``PUSH0`` is supported, favor zero literals over storing zero values in variables.
* Yul Optimizer: Run the ``Rematerializer`` and ``UnusedPruner`` steps at the end of the default clean-up sequence.
Bugfixes:
* AST: Fix wrong initial ID for Yul nodes in the AST.
* Code Generator: Fix output from via-IR code generator being dependent on which files were discovered by import callback. In some cases, a different AST ID assignment would alter the order of functions in internal dispatch, resulting in superficially different but semantically equivalent bytecode.
* NatSpec: Fix internal error when requesting userdoc or devdoc for a contract that emits an event defined in a foreign contract or interface.
* SMTChecker: Fix encoding error that causes loops to unroll after completion.
* SMTChecker: Fix inconsistency on constant condition checks when ``while`` or ``for`` loops are unrolled before the condition check.
### 0.8.21 (2023-07-19)
Important Bugfixes:

View File

@ -3,9 +3,9 @@
### Requirements
- [ ] GitHub account with access to [solidity](https://github.com/ethereum/solidity), [solc-js](https://github.com/ethereum/solc-js),
[solc-bin](https://github.com/ethereum/solc-bin), [homebrew-ethereum](https://github.com/ethereum/homebrew-ethereum),
[solidity-website](https://github.com/ethereum/solidity-website).
[solidity-blog](https://github.com/ethereum/solidity-blog) and [solidity-portal](https://github.com/ethereum/solidity-portal) repositories.
- [ ] DockerHub account with push rights to the [``solc`` image](https://hub.docker.com/r/ethereum/solc).
- [ ] Launchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and
- [ ] Lauchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and
a gnupg key for your email in the ``ethereum.org`` domain (has to be version 1, gpg2 won't work).
- [ ] Ubuntu/Debian dependencies of the PPA scripts: ``devscripts``, ``debhelper``, ``dput``, ``git``, ``wget``, ``ca-certificates``.
- [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [``solc`` package](https://www.npmjs.com/package/solc).
@ -37,8 +37,8 @@ At least a day before the release:
- [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements.
### Blog Post
- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Releases`` category and explain some of the new features or concepts.
- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Security Alerts`` category in case of important bug(s).
- [ ] Create a post on [solidity-blog](https://github.com/ethereum/solidity-blog) in the ``Releases`` category and explain some of the new features or concepts.
- [ ] Create a post on [solidity-blog](https://github.com/ethereum/solidity-blog) in the ``Security Alerts`` category in case of important bug(s).
### Changelog
- [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it.
@ -104,9 +104,9 @@ At least a day before the release:
- [ ] Make sure the documentation for the new release has been published successfully.
Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default.
- [ ] Remove "still in progress" warning from the [release notes](https://github.com/ethereum/solidity/releases).
- [ ] Merge the [blog posts](https://github.com/ethereum/solidity-website/pulls) related to the release.
- [ ] Merge the [blog posts](https://github.com/ethereum/solidity-blog/pulls) related to the release.
- [ ] Create a commit to increase the version number on ``develop`` in ``CMakeLists.txt`` and add a new skeleton changelog entry.
- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/ethereum/solidity-website/blob/main/src/pages/index.tsx).
- [ ] Update the release information section [in the source of soliditylang.org](https://github.com/ethereum/solidity-portal/blob/master/index.html).
- [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post.
- [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post.
- [ ] Share the announcement on Reddit in [``/r/ethdev``](https://reddit.com/r/ethdev/), cross-posted to [``/r/ethereum``](https://reddit.com/r/ethereum/).

View File

@ -4,9 +4,9 @@ FetchContent_Declare(
fmtlib
PREFIX "${PROJECT_BINARY_DIR}/deps"
DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads"
DOWNLOAD_NAME fmt-9.1.0.tar.gz
URL https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
URL_HASH SHA256=5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
DOWNLOAD_NAME fmt-8.0.1.tar.gz
URL https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz
URL_HASH SHA256=b06ca3130158c625848f3fb7418f235155a4d389b2abc3a6245fb01cb0eb1e01
)
if (CMAKE_VERSION VERSION_LESS "3.14.0")

View File

@ -112,7 +112,7 @@ New Error Reporter
~~~~~~~~~~~~~~~~~~
A new error reporter was introduced, which aims at producing more accessible error messages on the command-line.
It is enabled by default, but passing ``--old-reporter`` falls back to the deprecated old error reporter.
It is enabled by default, but passing ``--old-reporter`` falls back to the the deprecated old error reporter.
Metadata Hash Options
~~~~~~~~~~~~~~~~~~~~~

View File

@ -16,10 +16,6 @@
--navHeight: 4.5rem;
--sideWidth: 300px;
--maxWidth: 80rem;
--desktopInlinePadding: 2rem;
--mobileInlinePadding: 1rem;
--currentVersionHeight: 45px;
text-rendering: geometricPrecision;
-webkit-font-smoothing: antialiased;
@ -60,6 +56,7 @@ html,
body,
.wy-grid-for-nav {
background-color: var(--color-f) !important;
position: relative;
}
body {
@ -70,10 +67,6 @@ a {
color: var(--color-c);
}
a, section {
scroll-margin-top: calc(var(--navHeight) + 2rem);
}
hr {
margin-block: 2rem;
border-color: var(--color-d) !important;
@ -334,6 +327,7 @@ ul.current ul,
.wy-breadcrumbs-aside a,
.wy-breadcrumbs-aside a:visited,
/* .wy-breadcrumbs-aside a:not(:visited), */
a.fa.fa-github,
a.fa.fa-github:visited,
a.fa.fa-github:not(:visited),
@ -367,11 +361,10 @@ footer .rst-footer-buttons {
/* Site wrapper, and two children: header and rest */
.unified-wrapper {
position: relative;
display: flex;
flex-direction: column;
position: fixed;
inset: 0;
max-width: var(--maxWidth);
top: var(--navHeight);
max-width: 80rem;
margin-inline: auto;
}
@ -384,16 +377,17 @@ footer .rst-footer-buttons {
display: flex;
align-items: center;
box-shadow: var(--shadow);
backdrop-filter: blur(3px);
}
.unified-header .inner-header {
display: flex;
margin-inline: auto;
width: 100%;
max-width: var(--maxWidth);
max-width: 80rem;
align-items: center;
justify-content: space-between;
padding-inline: var(--desktopInlinePadding);
padding-inline: 2rem;
padding-block: 1rem;
}
@ -404,7 +398,6 @@ footer .rst-footer-buttons {
opacity: 95%;
background: var(--color-f);
z-index: -1;
backdrop-filter: blur(3px);
}
.unified-header .home-link {
@ -451,7 +444,6 @@ footer .rst-footer-buttons {
font-weight: 400;
box-sizing: content-box;
border-bottom: 1px solid transparent;
white-space: nowrap;
}
.unified-header .nav-link.active {
@ -463,36 +455,34 @@ footer .rst-footer-buttons {
border-bottom: 1px solid var(--color-c);
}
/* Rest: Flex-row, with two children: side bar, and content */
/* Rest: Grid, with two children: side bar, and content */
.unified-wrapper .wy-grid-for-nav {
position: relative !important;
display: flex;
margin-inline: auto;
display: grid !important;
grid-template-columns: var(--sideWidth) 1fr;
gap: 1rem;
}
/* First child: Side bar */
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side {
position: fixed;
position: relative;
display: flex;
flex-direction: column;
background: var(--color-f);
color: var(--color-a);
padding-bottom: unset !important;
z-index: 10 !important;
min-height: unset !important;
width: var(--sideWidth) !important;
top: var(--navHeight);
top: 0;
bottom: 0;
left: auto;
overflow: auto;
left: 0;
padding-bottom: unset !important;
min-height: unset !important;
z-index: 10 !important;
max-width: var(--sideWidth) !important;
}
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side .wy-side-scroll {
position: static !important;
width: unset !important;
overflow: unset !important;
position: relative !important;
width: fit-content !important;
height: unset !important;
padding-bottom: 2rem;
}
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side .wy-side-scroll .wy-side-nav-search {
@ -526,15 +516,15 @@ footer .rst-footer-buttons {
/* Second child: Content */
.unified-wrapper .wy-grid-for-nav .wy-nav-content {
position: relative !important;
overflow-y: scroll !important;
width: 100%;
max-width: unset !important; /* override */
padding-inline: var(--desktopInlinePadding);
margin-inline-start: var(--sideWidth);
margin-top: var(--navHeight);
max-width: 100vw !important;
padding-inline: 2rem;
}
.unified-wrapper .wy-grid-for-nav .wy-nav-content .rst-content {
max-width: min(70ch, calc(100vw - 2 * var(--desktopInlinePadding) - var(--sideWidth)));
max-width: 70ch;
margin-inline: auto;
}
@ -575,15 +565,29 @@ footer .rst-footer-buttons {
}
.unified-header .inner-header {
padding-inline: var(--mobileInlinePadding);
padding-inline: 1rem;
}
.unified-wrapper .wy-grid-for-nav {
grid-template-columns: 1fr;
}
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side {
position: absolute;
inset-block: 0;
inset-inline-start: 0;
width: var(--sideWidth);
overflow-y: scroll;
transform: translateX(-100%);
transition: transform 200ms ease-in-out;
}
/* Menu open styles */
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side {
position: absolute;
}
.unified-wrapper.menu-open nav.wy-nav-side {
transform: translateX(0);
transition: transform 200ms ease-in-out;
@ -608,18 +612,6 @@ footer .rst-footer-buttons {
a.skip-to-content {
display: none;
}
.wy-nav-content {
margin-inline-start: 0 !important;
}
.rst-content {
max-width: 100% !important;
}
.wy-side-scroll {
padding-bottom: 0 !important;
}
}
ul.search .context {
@ -666,8 +658,6 @@ ul.search .context {
.rst-other-versions {
background: var(--white) !important;
color: var(--color-a) !important;
max-height: calc(100vh - var(--navHeight) - var(--currentVersionHeight));
overflow-y: scroll;
}
.rst-other-versions a {
@ -788,8 +778,9 @@ button.mobile-menu-button {
font-family: 'Overpass Mono', monospace;
}
.wy-breadcrumbs>li {
padding-top: 8px;
.wy-breadcrumbs-aside {
display: block;
padding-top: 0;
}
.wy-breadcrumbs-aside a {
@ -810,9 +801,8 @@ a.skip-to-content {
padding: 2px 4px;
font-size: 14px;
margin-inline-end: auto;
margin-inline-start: 1.5rem;
margin-inline-start: 2rem;
color: var(--color-a);
white-space: nowrap;
}
a.skip-to-content:focus {

BIN
docs/_static/fonts/overpass-bold.otf vendored Normal file

Binary file not shown.

BIN
docs/_static/fonts/overpass-bold.woff2 vendored Normal file

Binary file not shown.

BIN
docs/_static/fonts/overpass-italic.otf vendored Normal file

Binary file not shown.

BIN
docs/_static/fonts/overpass-light.otf vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
docs/_static/fonts/overpass-regular.otf vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
docs/_static/fonts/overpass-semibold.otf vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,18 +1,11 @@
// Site URL
const SITE_URL = "https://docs.soliditylang.org"
const { origin, pathname } = location;
const pathSplit = pathname.split("/");
const rootPath = origin.includes(SITE_URL) && pathSplit.length > 3 ? pathSplit.splice(1, 2).join("/") : ''
const ROOT_URL = `${origin}/${rootPath}`;
// Color mode constants
const [DARK, LIGHT] = ["dark", "light"];
const LIGHT_LOGO_PATH = `${ROOT_URL}/_static/img/logo.svg`;
const DARK_LOGO_PATH = `${ROOT_URL}/_static/img/logo-dark.svg`;
const SUN_ICON_PATH = `${ROOT_URL}/_static/img/sun.svg`;
const MOON_ICON_PATH = `${ROOT_URL}/_static/img/moon.svg`;
const LIGHT_HAMBURGER_PATH = `${ROOT_URL}/_static/img/hamburger-light.svg`;
const DARK_HAMBURGER_PATH = `${ROOT_URL}/_static/img/hamburger-dark.svg`;
const LIGHT_LOGO_PATH = "_static/img/logo.svg";
const DARK_LOGO_PATH = "_static/img/logo-dark.svg";
const SUN_ICON_PATH = "_static/img/sun.svg";
const MOON_ICON_PATH = "_static/img/moon.svg";
const LIGHT_HAMBURGER_PATH = "_static/img/hamburger-light.svg";
const DARK_HAMBURGER_PATH = "_static/img/hamburger-dark.svg";
const COLOR_TOGGLE_ICON_CLASS = "color-toggle-icon";
const SOLIDITY_LOGO_CLASS = "solidity-logo";
const LS_COLOR_SCHEME = "color-scheme";

View File

@ -63,7 +63,7 @@ function buildHeader() {
const skipToContent = document.createElement("a");
skipToContent.classList.add("skip-to-content");
skipToContent.href = "#content";
skipToContent.innerText = "{skip to content}";
skipToContent.innerText = "{ skip to content }";
innerHeader.appendChild(skipToContent);
const navBar = document.createElement("nav");
@ -143,20 +143,23 @@ const updateActiveNavLink = () => {
document.addEventListener("locationchange", updateActiveNavLink);
function updateGitHubEditPath() {
// Replaces the version number in the GitHub edit path with "develop"
const gitHubEditAnchor = document.querySelector(".wy-breadcrumbs-aside > a");
const url = new URL(gitHubEditAnchor.href);
const split = url.pathname.split("/");
const versionIndex = split.indexOf("blob") + 1;
split[versionIndex] = "develop";
url.pathname = split.join("/");
gitHubEditAnchor.setAttribute("href", url.toString());
gitHubEditAnchor.setAttribute("target", "_blank");
gitHubEditAnchor.setAttribute("rel", "noopener noreferrer");
}
function initialize() {
// Preload fonts
const fonts = [
"overpass-regular.otf",
"overpass-bold.otf",
"overpass-mono-regular.otf",
"overpass-mono-bold.otf",
];
fonts.forEach((filename) => {
const link = document.createElement("link");
link.rel = "preload";
link.as = "font";
link.href = `https://solidity-docs-dev.readthedocs.io/en/latest/_static/fonts/${filename}`;
link.crossOrigin = "";
document.head.appendChild(link);
});
// Rearrange DOM elements for styling
rearrangeDom();
@ -211,9 +214,6 @@ function initialize() {
// Update active nav link
updateActiveNavLink();
// Update GitHub edit path to direct to `develop` branch
updateGitHubEditPath();
}
document.addEventListener("DOMContentLoaded", initialize);

View File

@ -67,7 +67,7 @@ When using the Solidity logo, please respect the Solidity logo guidelines.
Solidity Logo Guidelines
========================
.. image:: solidity_logo.svg
.. image:: logo.svg
:width: 256
*(Right click on the logo to download it.)*

View File

@ -169,7 +169,7 @@ html_js_files = ["js/constants.js", "js/initialize.js", "js/toggle.js"]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
html_extra_path = ["_static/css"]
html_extra_path = ["_static/css", "_static/fonts"]
# List of templates of static files to be included in the HTML output.
# Keys represent paths to input files and values are dicts containing:

View File

@ -9,10 +9,9 @@ Events
Solidity events give an abstraction on top of the EVM's logging functionality.
Applications can subscribe and listen to these events through the RPC interface of an Ethereum client.
Events can be defined at file level or as inheritable members of contracts (including interfaces and libraries).
When you call them, they cause the
Events are inheritable members of contracts. When you call them, they cause the
arguments to be stored in the transaction's log - a special data structure
in the blockchain. These logs are associated with the address of the contract that emitted them,
in the blockchain. These logs are associated with the address of the contract,
are incorporated into the blockchain, and stay there as long as a block is
accessible (forever as of now, but this might
change with Serenity). The Log and its event data is not accessible from within

View File

@ -132,7 +132,7 @@ variables are set to their :ref:`default values<default-value>` just as if the f
body.
The ``_`` symbol can appear in the modifier multiple times. Each occurrence is replaced with
the function body, and the function returns the return value of the final occurrence.
the function body.
Arbitrary expressions are allowed for modifier arguments and in this context,
all symbols visible from the function are visible in the modifier. Symbols

View File

@ -22,7 +22,6 @@ sourceUnit: (
| enumDefinition
| userDefinedValueTypeDefinition
| errorDefinition
| eventDefinition
)* EOF;
//@doc: inline

View File

@ -323,7 +323,7 @@ The following are dependencies for all builds of Solidity:
| `CMake`_ (version 3.21.3+ on | Cross-platform build file generator. |
| Windows, 3.13+ otherwise) | |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.77+ on | C++ libraries. |
| `Boost`_ (version 1.77 on | C++ libraries. |
| Windows, 1.65+ otherwise) | |
+-----------------------------------+-------------------------------------------------------+
| `Git`_ | Command-line tool for retrieving source code. |
@ -410,7 +410,7 @@ You need to install the following dependencies for Windows builds of Solidity:
+-----------------------------------+-------------------------------------------------------+
| `Visual Studio 2019`_ (Optional) | C++ compiler and dev environment. |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.77+) | C++ libraries. |
| `Boost`_ (version 1.77) | C++ libraries. |
+-----------------------------------+-------------------------------------------------------+
If you already have one IDE and only need the compiler and libraries,

View File

@ -338,7 +338,7 @@ You can override this sequence and supply your own using the ``--yul-optimizatio
.. code-block:: bash
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOcmu'
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOc'
The order of steps is significant and affects the quality of the output.
Moreover, applying a step may uncover new optimization opportunities for others that were already applied,

View File

@ -515,7 +515,7 @@ you can use the following in your source file:
The compiler will look for the file in the VFS under ``dapp-bin/library/math.sol``.
If the file is not available there, the source unit name will be passed to the Host Filesystem
Loader, which will then look in ``/project/dapp-bin/library/math.sol``.
Loader, which will then look in ``/project/dapp-bin/library/iterable_mapping.sol``.
.. warning::

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1300px" height="1300px"
viewBox="0 0 1300 1300" enable-background="new 0 0 1300 1300" xml:space="preserve">
<title>Vector 1</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" sketch:type="MSPage">
<g id="solidity" transform="translate(402.000000, 118.000000)" sketch:type="MSLayerGroup">
<g id="Group" sketch:type="MSShapeGroup">
<path id="Shape" opacity="0.45" enable-background="new " d="M371.772,135.308L241.068,367.61H-20.158l130.614-232.302
H371.772"/>
<path id="Shape_1_" opacity="0.6" enable-background="new " d="M241.068,367.61h261.318L371.772,135.308H110.456
L241.068,367.61z"/>
<path id="Shape_2_" opacity="0.8" enable-background="new " d="M110.456,599.822L241.068,367.61L110.456,135.308
L-20.158,367.61L110.456,599.822z"/>
<path id="Shape_3_" opacity="0.45" enable-background="new " d="M111.721,948.275l130.704-232.303h261.318L373.038,948.275
H111.721"/>
<path id="Shape_4_" opacity="0.6" enable-background="new " d="M242.424,715.973H-18.893l130.613,232.303h261.317
L242.424,715.973z"/>
<path id="Shape_5_" opacity="0.8" enable-background="new " d="M373.038,483.761L242.424,715.973l130.614,232.303
l130.704-232.303L373.038,483.761z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -112,11 +112,11 @@ Events are convenience interfaces with the EVM logging facilities.
.. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.22;
event HighestBidIncreased(address bidder, uint amount); // Event
pragma solidity >=0.4.21 <0.9.0;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // Triggering event

View File

@ -372,7 +372,7 @@ Array Members
.. note::
In EVM versions before Byzantium, it was not possible to access
dynamic arrays returned from function calls. If you call functions
dynamic arrays return from function calls. If you call functions
that return dynamic arrays, make sure to use an EVM that is set to
Byzantium mode.

View File

@ -359,7 +359,7 @@ Input Description
// Addresses of the libraries. If not all libraries are given here,
// it can result in unlinked objects whose output data is different.
"libraries": {
// The top level key is the name of the source file where the library is used.
// The top level key is the the name of the source file where the library is used.
// If remappings are used, this source file should match the global path
// after remappings were applied.
// If this key is an empty string, that refers to a global level.
@ -408,7 +408,7 @@ Input Description
// evm.methodIdentifiers - The list of function hashes
// evm.gasEstimates - Function gas estimates
//
// Note that using `evm`, `evm.bytecode`, etc. will select every
// Note that using a using `evm`, `evm.bytecode`, etc. will select every
// target part of that output. Additionally, `*` can be used as a wildcard to request everything.
//
"outputSelection": {

View File

@ -741,7 +741,7 @@ EVM Dialect
-----------
The default dialect of Yul currently is the EVM dialect for the currently selected version of the EVM.
The only type available in this dialect
with a version of the EVM. The only type available in this dialect
is ``u256``, the 256-bit native type of the Ethereum Virtual Machine.
Since it is the default type of this dialect, it can be omitted.

View File

@ -109,7 +109,7 @@ public:
/// Resets any knowledge about storage.
void resetStorage() { m_storageContent.clear(); }
/// Resets any knowledge about memory.
/// Resets any knowledge about storage.
void resetMemory() { m_memoryContent.clear(); }
/// Resets known Keccak-256 hashes
void resetKnownKeccak256Hashes() { m_knownKeccak256Hashes.clear(); }

View File

@ -170,8 +170,6 @@ class Error: virtual public util::Exception
public:
enum class Type
{
Info,
Warning,
CodeGenerationError,
DeclarationError,
DocstringParsingError,
@ -187,14 +185,15 @@ public:
UnimplementedFeatureError,
YulException,
SMTLogicException,
Warning,
Info
};
enum class Severity
{
// NOTE: We rely on these being ordered from least to most severe.
Info,
Warning,
Error,
Warning,
Info
};
Error(
@ -207,7 +206,6 @@ public:
ErrorId errorId() const { return m_errorId; }
Type type() const { return m_type; }
Severity severity() const { return errorSeverity(m_type); }
SourceLocation const* sourceLocation() const noexcept;
SecondarySourceLocation const* secondarySourceLocation() const noexcept;

View File

@ -74,10 +74,56 @@ void ParserBase::expectToken(Token _value, bool _advance)
{
Token tok = m_scanner->currentToken();
if (tok != _value)
fatalParserError(
2314_error,
"Expected " + ParserBase::tokenName(_value) + " but got " + tokenName(tok)
);
{
std::string const expectedToken = ParserBase::tokenName(_value);
if (m_parserErrorRecovery)
parserError(6635_error, "Expected " + expectedToken + " but got " + tokenName(tok));
else
fatalParserError(2314_error, "Expected " + expectedToken + " but got " + tokenName(tok));
// Do not advance so that recovery can sync or make use of the current token.
// This is especially useful if the expected token
// is the only one that is missing and is at the end of a construct.
// "{ ... ; }" is such an example.
// ^
_advance = false;
}
if (_advance)
advance();
}
void ParserBase::expectTokenOrConsumeUntil(Token _value, std::string const& _currentNodeName, bool _advance)
{
solAssert(m_inParserRecovery, "The function is supposed to be called during parser recovery only.");
Token tok = m_scanner->currentToken();
if (tok != _value)
{
SourceLocation errorLoc = currentLocation();
int startPosition = errorLoc.start;
while (m_scanner->currentToken() != _value && m_scanner->currentToken() != Token::EOS)
advance();
std::string const expectedToken = ParserBase::tokenName(_value);
if (m_scanner->currentToken() == Token::EOS)
{
// rollback to where the token started, and raise exception to be caught at a higher level.
m_scanner->setPosition(static_cast<size_t>(startPosition));
std::string const msg = "In " + _currentNodeName + ", " + expectedToken + "is expected; got " + ParserBase::tokenName(tok) + " instead.";
fatalParserError(1957_error, errorLoc, msg);
}
else
{
parserWarning(3796_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
m_inParserRecovery = false;
}
}
else
{
std::string expectedToken = ParserBase::tokenName(_value);
parserWarning(3347_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
m_inParserRecovery = false;
}
if (_advance)
advance();
}

View File

@ -38,9 +38,14 @@ struct ErrorId;
class ParserBase
{
public:
explicit ParserBase(ErrorReporter& errorReporter):
m_errorReporter(errorReporter)
{}
/// Set @a _parserErrorRecovery to true for additional error
/// recovery. This is experimental and intended for use
/// by front-end tools that need partial AST information even
/// when errors occur.
explicit ParserBase(ErrorReporter& errorReporter, bool _parserErrorRecovery = false): m_errorReporter(errorReporter)
{
m_parserErrorRecovery = _parserErrorRecovery;
}
virtual ~ParserBase() = default;
@ -65,9 +70,13 @@ protected:
///@{
///@name Helper functions
/// If current token value is not @a _value, throw exception otherwise advance token
// if @a _advance is true
// @a if _advance is true and error recovery is in effect.
void expectToken(Token _value, bool _advance = true);
/// Like expectToken but if there is an error ignores tokens until
/// the expected token or EOS is seen. If EOS is encountered, back up to the error point,
/// and throw an exception so that a higher grammar rule has an opportunity to recover.
void expectTokenOrConsumeUntil(Token _value, std::string const& _currentNodeName, bool _advance = true);
Token currentToken() const;
Token peekNextToken() const;
std::string tokenName(Token _token);
@ -99,6 +108,10 @@ protected:
ErrorReporter& m_errorReporter;
/// Current recursion depth during parsing.
size_t m_recursionDepth = 0;
/// True if we are in parser error recovery. Usually this means we are scanning for
/// a synchronization token like ';', or '}'. We use this to reduce cascaded error messages.
bool m_inParserRecovery = false;
bool m_parserErrorRecovery = false;
};
}

View File

@ -1019,28 +1019,15 @@ std::tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
while (isIdentifierPart(m_char) || (m_char == '.' && m_kind == ScannerKind::Yul))
addLiteralCharAndAdvance();
literal.complete();
auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal);
switch (m_kind)
if (m_kind == ScannerKind::Yul)
{
case ScannerKind::Solidity:
// Turn experimental Solidity keywords that are not keywords in legacy Solidity into identifiers.
if (TokenTraits::isExperimentalSolidityOnlyKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
break;
case ScannerKind::Yul:
// Turn Solidity identifier into a Yul keyword
if (m_tokens[NextNext].literal == "leave")
return std::make_tuple(Token::Leave, 0, 0);
// Turn non-Yul keywords into identifiers.
if (!TokenTraits::isYulKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
break;
case ScannerKind::ExperimentalSolidity:
// Turn legacy Solidity keywords that are not keywords in experimental Solidity into identifiers.
if (!TokenTraits::isExperimentalSolidityKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
break;
}
return token;
}

View File

@ -69,8 +69,7 @@ class ParserRecorder;
enum class ScannerKind
{
Solidity,
Yul,
ExperimentalSolidity
Yul
};
enum class ScannerError

View File

@ -46,16 +46,9 @@ public:
bool _colored,
bool _withErrorIds
):
m_stream(_stream),
m_charStreamProvider(_charStreamProvider),
m_colored(_colored),
m_withErrorIds(_withErrorIds)
m_stream(_stream), m_charStreamProvider(_charStreamProvider), m_colored(_colored), m_withErrorIds(_withErrorIds)
{}
// WARNING: Use the xyzErrorInformation() variants over xyzExceptionInformation() when you
// do have access to an Error instance. Error is implicitly convertible to util::Exception
// but the conversion loses the error ID.
/// Prints source location if it is given.
void printSourceLocation(SourceReference const& _ref);
void printExceptionInformation(SourceReferenceExtractor::Message const& _msg);
@ -68,11 +61,12 @@ public:
util::Exception const& _exception,
Error::Type _type,
CharStreamProvider const& _charStreamProvider,
bool _colored = false
bool _colored = false,
bool _withErrorIds = false
)
{
std::ostringstream errorOutput;
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, false /* _withErrorIds */);
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
formatter.printExceptionInformation(_exception, _type);
return errorOutput.str();
}
@ -81,39 +75,26 @@ public:
util::Exception const& _exception,
Error::Severity _severity,
CharStreamProvider const& _charStreamProvider,
bool _colored = false
bool _colored = false,
bool _withErrorIds = false
)
{
std::ostringstream errorOutput;
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, false /* _withErrorIds */);
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
formatter.printExceptionInformation(_exception, _severity);
return errorOutput.str();
}
static std::string formatErrorInformation(
Error const& _error,
CharStreamProvider const& _charStreamProvider,
bool _colored = false,
bool _withErrorIds = false
CharStreamProvider const& _charStreamProvider
)
{
std::ostringstream errorOutput;
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
formatter.printErrorInformation(_error);
return errorOutput.str();
}
static std::string formatErrorInformation(
langutil::ErrorList const& _errors,
CharStreamProvider const& _charStreamProvider,
bool _colored = false,
bool _withErrorIds = false
)
{
std::ostringstream errorOutput;
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
formatter.printErrorInformation(_errors);
return errorOutput.str();
return formatExceptionInformation(
_error,
Error::errorSeverity(_error.type()),
_charStreamProvider
);
}
static std::string formatErrorInformation(Error const& _error, CharStream const& _charStream);

View File

@ -268,8 +268,6 @@ namespace solidity::langutil
/* Yul-specific tokens, but not keywords. */ \
T(Leave, "leave", 0) \
\
T(NonExperimentalEnd, nullptr, 0) /* used as non-experimental enum end marker */ \
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
\
@ -325,39 +323,6 @@ namespace TokenTraits
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex;
}
constexpr bool isExperimentalSolidityKeyword(Token token)
{
return
token == Token::Assembly ||
token == Token::Contract ||
token == Token::External ||
token == Token::Fallback ||
token == Token::Pragma ||
token == Token::Import ||
token == Token::As ||
token == Token::Function ||
token == Token::Let ||
token == Token::Return ||
token == Token::Type ||
token == Token::If ||
token == Token::Else ||
token == Token::Do ||
token == Token::While ||
token == Token::For ||
token == Token::Continue ||
token == Token::Break;
// TODO: see isExperimentalSolidityKeyword below
// || (token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd);
}
constexpr bool isExperimentalSolidityOnlyKeyword(Token)
{
// TODO: use token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd
// as soon as other experimental tokens are added. For now the comparison generates
// a warning from clang because it is always false.
return false;
}
bool isYulKeyword(std::string const& _literal);
Token AssignmentToBinaryOp(Token op);

View File

@ -101,8 +101,6 @@ set(sources
codegen/ir/IRLValue.h
codegen/ir/IRVariable.cpp
codegen/ir/IRVariable.h
experimental/analysis/Analysis.cpp
experimental/analysis/Analysis.h
formal/ArraySlicePredicate.cpp
formal/ArraySlicePredicate.h
formal/BMC.cpp
@ -188,3 +186,4 @@ set(sources
add_library(solidity ${sources})
target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only Threads::Threads)

View File

@ -29,6 +29,7 @@
#include <limits>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::langutil;
@ -46,9 +47,9 @@ bool fitsPrecisionExp(bigint const& _base, bigint const& _exp)
solAssert(_base > 0, "");
std::size_t const bitsMax = 4096;
size_t const bitsMax = 4096;
std::size_t mostSignificantBaseBit = static_cast<std::size_t>(boost::multiprecision::msb(_base));
size_t mostSignificantBaseBit = static_cast<size_t>(boost::multiprecision::msb(_base));
if (mostSignificantBaseBit == 0) // _base == 1
return true;
if (mostSignificantBaseBit > bitsMax) // _base >= 2 ^ 4096
@ -67,7 +68,7 @@ bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2)
}
std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right)
optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right)
{
bool fractional = _left.denominator() != 1 || _right.denominator() != 1;
switch (_operator)
@ -75,17 +76,17 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
//bit operations will only be enabled for integers and fixed types that resemble integers
case Token::BitOr:
if (fractional)
return std::nullopt;
return nullopt;
else
return _left.numerator() | _right.numerator();
case Token::BitXor:
if (fractional)
return std::nullopt;
return nullopt;
else
return _left.numerator() ^ _right.numerator();
case Token::BitAnd:
if (fractional)
return std::nullopt;
return nullopt;
else
return _left.numerator() & _right.numerator();
case Token::Add: return _left + _right;
@ -93,12 +94,12 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
case Token::Mul: return _left * _right;
case Token::Div:
if (_right == rational(0))
return std::nullopt;
return nullopt;
else
return _left / _right;
case Token::Mod:
if (_right == rational(0))
return std::nullopt;
return nullopt;
else if (fractional)
{
rational tempValue = _left / _right;
@ -110,7 +111,7 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
case Token::Exp:
{
if (_right.denominator() != 1)
return std::nullopt;
return nullopt;
bigint const& exp = _right.numerator();
// x ** 0 = 1
@ -126,13 +127,13 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
}
else
{
if (abs(exp) > std::numeric_limits<uint32_t>::max())
return std::nullopt; // This will need too much memory to represent.
if (abs(exp) > numeric_limits<uint32_t>::max())
return nullopt; // This will need too much memory to represent.
uint32_t absExp = bigint(abs(exp)).convert_to<uint32_t>();
if (!fitsPrecisionExp(abs(_left.numerator()), absExp) || !fitsPrecisionExp(abs(_left.denominator()), absExp))
return std::nullopt;
return nullopt;
static auto const optimizedPow = [](bigint const& _base, uint32_t _exponent) -> bigint {
if (_base == 1)
@ -157,18 +158,18 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
case Token::SHL:
{
if (fractional)
return std::nullopt;
return nullopt;
else if (_right < 0)
return std::nullopt;
else if (_right > std::numeric_limits<uint32_t>::max())
return std::nullopt;
return nullopt;
else if (_right > numeric_limits<uint32_t>::max())
return nullopt;
if (_left.numerator() == 0)
return 0;
else
{
uint32_t exponent = _right.numerator().convert_to<uint32_t>();
if (!fitsPrecisionBase2(abs(_left.numerator()), exponent))
return std::nullopt;
return nullopt;
return _left.numerator() * boost::multiprecision::pow(bigint(2), exponent);
}
break;
@ -178,11 +179,11 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
case Token::SAR:
{
if (fractional)
return std::nullopt;
return nullopt;
else if (_right < 0)
return std::nullopt;
else if (_right > std::numeric_limits<uint32_t>::max())
return std::nullopt;
return nullopt;
else if (_right > numeric_limits<uint32_t>::max())
return nullopt;
if (_left.numerator() == 0)
return 0;
else
@ -208,60 +209,60 @@ std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operato
break;
}
default:
return std::nullopt;
return nullopt;
}
}
std::optional<rational> ConstantEvaluator::evaluateUnaryOperator(Token _operator, rational const& _input)
optional<rational> ConstantEvaluator::evaluateUnaryOperator(Token _operator, rational const& _input)
{
switch (_operator)
{
case Token::BitNot:
if (_input.denominator() != 1)
return std::nullopt;
return nullopt;
else
return ~_input.numerator();
case Token::Sub:
return -_input;
default:
return std::nullopt;
return nullopt;
}
}
namespace
{
std::optional<TypedRational> convertType(rational const& _value, Type const& _type)
optional<TypedRational> convertType(rational const& _value, Type const& _type)
{
if (_type.category() == Type::Category::RationalNumber)
return TypedRational{TypeProvider::rationalNumber(_value), _value};
else if (auto const* integerType = dynamic_cast<IntegerType const*>(&_type))
{
if (_value > integerType->maxValue() || _value < integerType->minValue())
return std::nullopt;
return nullopt;
else
return TypedRational{&_type, _value.numerator() / _value.denominator()};
}
else
return std::nullopt;
return nullopt;
}
std::optional<TypedRational> convertType(std::optional<TypedRational> const& _value, Type const& _type)
optional<TypedRational> convertType(optional<TypedRational> const& _value, Type const& _type)
{
return _value ? convertType(_value->value, _type) : std::nullopt;
return _value ? convertType(_value->value, _type) : nullopt;
}
std::optional<TypedRational> constantToTypedValue(Type const& _type)
optional<TypedRational> constantToTypedValue(Type const& _type)
{
if (_type.category() == Type::Category::RationalNumber)
return TypedRational{&_type, dynamic_cast<RationalNumberType const&>(_type).value()};
else
return std::nullopt;
return nullopt;
}
}
std::optional<TypedRational> ConstantEvaluator::evaluate(
optional<TypedRational> ConstantEvaluator::evaluate(
langutil::ErrorReporter& _errorReporter,
Expression const& _expr
)
@ -270,7 +271,7 @@ std::optional<TypedRational> ConstantEvaluator::evaluate(
}
std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
{
if (!m_values.count(&_node))
{
@ -279,7 +280,7 @@ std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
solAssert(varDecl->isConstant(), "");
// In some circumstances, we do not yet have a type for the variable.
if (!varDecl->value() || !varDecl->type())
m_values[&_node] = std::nullopt;
m_values[&_node] = nullopt;
else
{
m_depth++;
@ -297,7 +298,7 @@ std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
{
expression->accept(*this);
if (!m_values.count(&_node))
m_values[&_node] = std::nullopt;
m_values[&_node] = nullopt;
}
}
return m_values.at(&_node);
@ -305,7 +306,7 @@ std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
{
std::optional<TypedRational> value = evaluate(_operation.subExpression());
optional<TypedRational> value = evaluate(_operation.subExpression());
if (!value)
return;
@ -316,9 +317,9 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
if (!value)
return;
if (std::optional<rational> result = evaluateUnaryOperator(_operation.getOperator(), value->value))
if (optional<rational> result = evaluateUnaryOperator(_operation.getOperator(), value->value))
{
std::optional<TypedRational> convertedValue = convertType(*result, *resultType);
optional<TypedRational> convertedValue = convertType(*result, *resultType);
if (!convertedValue)
m_errorReporter.fatalTypeError(
3667_error,
@ -331,8 +332,8 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
{
std::optional<TypedRational> left = evaluate(_operation.leftExpression());
std::optional<TypedRational> right = evaluate(_operation.rightExpression());
optional<TypedRational> left = evaluate(_operation.leftExpression());
optional<TypedRational> right = evaluate(_operation.rightExpression());
if (!left || !right)
return;
@ -348,7 +349,7 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
6020_error,
_operation.location(),
"Operator " +
std::string(TokenTraits::toString(_operation.getOperator())) +
string(TokenTraits::toString(_operation.getOperator())) +
" not compatible with types " +
left->type->toString() +
" and " +
@ -362,9 +363,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
if (!left || !right)
return;
if (std::optional<rational> value = evaluateBinaryOperator(_operation.getOperator(), left->value, right->value))
if (optional<rational> value = evaluateBinaryOperator(_operation.getOperator(), left->value, right->value))
{
std::optional<TypedRational> convertedValue = convertType(*value, *resultType);
optional<TypedRational> convertedValue = convertType(*value, *resultType);
if (!convertedValue)
m_errorReporter.fatalTypeError(
2643_error,

View File

@ -32,6 +32,7 @@
#include <range/v3/view/reverse.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -48,10 +49,10 @@ bool hasEqualExternalCallableParameters(T const& _a, B const& _b)
}
template<typename T>
std::map<ASTString, std::vector<T const*>> filterDeclarations(
std::map<ASTString, std::vector<Declaration const*>> const& _declarations)
map<ASTString, vector<T const*>> filterDeclarations(
map<ASTString, vector<Declaration const*>> const& _declarations)
{
std::map<ASTString, std::vector<T const*>> filteredDeclarations;
map<ASTString, vector<T const*>> filteredDeclarations;
for (auto const& [name, overloads]: _declarations)
for (auto const* declaration: overloads)
if (auto typedDeclaration = dynamic_cast<T const*>(declaration))
@ -105,7 +106,7 @@ void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _co
{
/// Checks that two functions with the same name defined in this contract have different
/// argument types and that there is at most one constructor.
std::map<std::string, std::vector<FunctionDefinition const*>> functions;
map<string, vector<FunctionDefinition const*>> functions;
FunctionDefinition const* constructor = nullptr;
FunctionDefinition const* fallback = nullptr;
FunctionDefinition const* receive = nullptr;
@ -156,7 +157,7 @@ void ContractLevelChecker::checkDuplicateEvents(ContractDefinition const& _contr
{
/// Checks that two events with the same name defined in this contract have different
/// argument types
std::map<std::string, std::vector<EventDefinition const*>> events;
map<string, vector<EventDefinition const*>> events;
for (auto const* contract: _contract.annotation().linearizedBaseContracts)
for (EventDefinition const* event: contract->events())
events[event->name()].push_back(event);
@ -194,12 +195,12 @@ void ContractLevelChecker::checkReceiveFunction(ContractDefinition const& _contr
}
template <class T>
void ContractLevelChecker::findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions)
void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions)
{
for (auto const& it: _definitions)
{
std::vector<T> const& overloads = it.second;
std::set<size_t> reported;
vector<T> const& overloads = it.second;
set<size_t> reported;
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
{
SecondarySourceLocation ssl;
@ -227,15 +228,15 @@ void ContractLevelChecker::findDuplicateDefinitions(std::map<std::string, std::v
if (ssl.infos.size() > 0)
{
ErrorId error;
std::string message;
if constexpr (std::is_same_v<T, FunctionDefinition const*>)
string message;
if constexpr (is_same_v<T, FunctionDefinition const*>)
{
error = 1686_error;
message = "Function with same name and parameter types defined twice.";
}
else
{
static_assert(std::is_same_v<T, EventDefinition const*>, "Expected \"FunctionDefinition const*\" or \"EventDefinition const*\"");
static_assert(is_same_v<T, EventDefinition const*>, "Expected \"FunctionDefinition const*\" or \"EventDefinition const*\"");
error = 5883_error;
message = "Event with same name and parameter types defined twice.";
}
@ -257,7 +258,7 @@ void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _c
{
// Collects functions, static variable getters and modifiers. If they
// override (unimplemented) base class ones, they are replaced.
std::set<OverrideProxy, OverrideProxy::CompareBySignature> proxies;
set<OverrideProxy, OverrideProxy::CompareBySignature> proxies;
auto registerProxy = [&proxies](OverrideProxy const& _overrideProxy)
{
@ -322,7 +323,7 @@ void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _c
void ContractLevelChecker::checkBaseConstructorArguments(ContractDefinition const& _contract)
{
std::vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
// Determine the arguments that are used for the base constructors.
for (ContractDefinition const* contract: bases)
@ -429,7 +430,7 @@ void ContractLevelChecker::annotateBaseConstructorArguments(
void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _contract)
{
std::map<std::string, std::vector<std::pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
{
for (FunctionDefinition const* f: contract->definedFunctions())
@ -466,7 +467,7 @@ void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _c
void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contract)
{
std::set<util::FixedHash<4>> hashes;
set<util::FixedHash<4>> hashes;
for (auto const& it: _contract.interfaceFunctionList())
{
util::FixedHash<4> const& hash = it.first;
@ -474,7 +475,7 @@ void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contra
m_errorReporter.fatalTypeError(
1860_error,
_contract.location(),
std::string("Function signature hash collision for ") + it.second->externalSignature()
string("Function signature hash collision for ") + it.second->externalSignature()
);
hashes.insert(hash);
}

View File

@ -25,6 +25,7 @@
#include <functional>
using namespace std;
using namespace std::placeholders;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -43,7 +44,7 @@ void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractD
if (!_function.isImplemented())
return;
std::optional<std::string> mostDerivedContractName;
optional<string> mostDerivedContractName;
// The name of the most derived contract only required if it differs from
// the functions contract
@ -60,13 +61,13 @@ void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractD
}
void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNode const* _exit, bool _emptyBody, std::optional<std::string> _contractName)
void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNode const* _exit, bool _emptyBody, optional<string> _contractName)
{
struct NodeInfo
{
std::set<VariableDeclaration const*> unassignedVariablesAtEntry;
std::set<VariableDeclaration const*> unassignedVariablesAtExit;
std::set<VariableOccurrence const*> uninitializedVariableAccesses;
set<VariableDeclaration const*> unassignedVariablesAtEntry;
set<VariableDeclaration const*> unassignedVariablesAtExit;
set<VariableOccurrence const*> uninitializedVariableAccesses;
/// Propagate the information from another node to this node.
/// To be used to propagate information from a node to its exit nodes.
/// Returns true, if new variables were added and thus the current node has
@ -83,8 +84,8 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
;
}
};
std::map<CFGNode const*, NodeInfo> nodeInfos;
std::set<CFGNode const*> nodesToTraverse;
map<CFGNode const*, NodeInfo> nodeInfos;
set<CFGNode const*> nodesToTraverse;
nodesToTraverse.insert(_entry);
// Walk all paths starting from the nodes in ``nodesToTraverse`` until ``NodeInfo::propagateFrom``
@ -137,7 +138,7 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
auto const& exitInfo = nodeInfos[_exit];
if (!exitInfo.uninitializedVariableAccesses.empty())
{
std::vector<VariableOccurrence const*> uninitializedAccessesOrdered(
vector<VariableOccurrence const*> uninitializedAccessesOrdered(
exitInfo.uninitializedVariableAccesses.begin(),
exitInfo.uninitializedVariableAccesses.end()
);
@ -167,7 +168,7 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
varDecl.location(),
ssl,
"This variable is of " +
std::string(isStorage ? "storage" : "calldata") +
string(isStorage ? "storage" : "calldata") +
" pointer type and can be " +
(variableOccurrence->kind() == VariableOccurrence::Kind::Return ? "returned" : "accessed") +
" without prior assignment, which would lead to undefined behaviour."

View File

@ -21,8 +21,10 @@
#include <libyul/AST.h>
#include <libyul/backends/evm/EVMDialect.h>
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
using namespace std;
ControlFlowBuilder::ControlFlowBuilder(CFG::NodeContainer& _nodeContainer, FunctionFlow const& _functionFlow, ContractDefinition const* _contract):
m_nodeContainer(_nodeContainer),
@ -35,13 +37,13 @@ ControlFlowBuilder::ControlFlowBuilder(CFG::NodeContainer& _nodeContainer, Funct
}
std::unique_ptr<FunctionFlow> ControlFlowBuilder::createFunctionFlow(
unique_ptr<FunctionFlow> ControlFlowBuilder::createFunctionFlow(
CFG::NodeContainer& _nodeContainer,
FunctionDefinition const& _function,
ContractDefinition const* _contract
)
{
auto functionFlow = std::make_unique<FunctionFlow>();
auto functionFlow = make_unique<FunctionFlow>();
functionFlow->entry = _nodeContainer.newNode();
functionFlow->exit = _nodeContainer.newNode();
functionFlow->revert = _nodeContainer.newNode();

View File

@ -20,6 +20,7 @@
#include <libsolidity/analysis/ControlFlowBuilder.h>
using namespace std;
using namespace solidity::langutil;
using namespace solidity::frontend;

View File

@ -29,6 +29,7 @@
#include <range/v3/view/filter.hpp>
#include <range/v3/range/conversion.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
@ -40,7 +41,7 @@ Declaration const* DeclarationContainer::conflictingDeclaration(
if (!_name)
_name = &_declaration.name();
solAssert(!_name->empty(), "");
std::vector<Declaration const*> declarations;
vector<Declaration const*> declarations;
if (m_declarations.count(*_name))
declarations += m_declarations.at(*_name);
if (m_invisibleDeclarations.count(*_name))
@ -126,7 +127,7 @@ bool DeclarationContainer::registerDeclaration(
m_homonymCandidates.emplace_back(*_name, _location ? _location : &_declaration.location());
}
std::vector<Declaration const*>& decls = _invisible ? m_invisibleDeclarations[*_name] : m_declarations[*_name];
vector<Declaration const*>& decls = _invisible ? m_invisibleDeclarations[*_name] : m_declarations[*_name];
if (!util::contains(decls, &_declaration))
decls.push_back(&_declaration);
return true;
@ -141,13 +142,13 @@ bool DeclarationContainer::registerDeclaration(
return registerDeclaration(_declaration, nullptr, nullptr, _invisible, _update);
}
std::vector<Declaration const*> DeclarationContainer::resolveName(
vector<Declaration const*> DeclarationContainer::resolveName(
ASTString const& _name,
ResolvingSettings _settings
) const
{
solAssert(!_name.empty(), "Attempt to resolve empty name.");
std::vector<Declaration const*> result;
vector<Declaration const*> result;
if (m_declarations.count(_name))
{
@ -171,24 +172,24 @@ std::vector<Declaration const*> DeclarationContainer::resolveName(
return result;
}
std::vector<ASTString> DeclarationContainer::similarNames(ASTString const& _name) const
vector<ASTString> DeclarationContainer::similarNames(ASTString const& _name) const
{
// because the function below has quadratic runtime - it will not magically improve once a better algorithm is discovered ;)
// since 80 is the suggested line length limit, we use 80^2 as length threshold
static size_t const MAXIMUM_LENGTH_THRESHOLD = 80 * 80;
std::vector<ASTString> similar;
vector<ASTString> similar;
size_t maximumEditDistance = _name.size() > 3 ? 2 : _name.size() / 2;
for (auto const& declaration: m_declarations)
{
std::string const& declarationName = declaration.first;
string const& declarationName = declaration.first;
if (util::stringWithinDistance(_name, declarationName, maximumEditDistance, MAXIMUM_LENGTH_THRESHOLD))
similar.push_back(declarationName);
}
for (auto const& declaration: m_invisibleDeclarations)
{
std::string const& declarationName = declaration.first;
string const& declarationName = declaration.first;
if (util::stringWithinDistance(_name, declarationName, maximumEditDistance, MAXIMUM_LENGTH_THRESHOLD))
similar.push_back(declarationName);
}
@ -199,7 +200,7 @@ std::vector<ASTString> DeclarationContainer::similarNames(ASTString const& _name
return similar;
}
void DeclarationContainer::populateHomonyms(std::back_insert_iterator<Homonyms> _it) const
void DeclarationContainer::populateHomonyms(back_insert_iterator<Homonyms> _it) const
{
for (DeclarationContainer const* innerContainer: m_innerContainers)
innerContainer->populateHomonyms(_it);
@ -209,7 +210,7 @@ void DeclarationContainer::populateHomonyms(std::back_insert_iterator<Homonyms>
ResolvingSettings settings;
settings.recursive = true;
settings.alsoInvisible = true;
std::vector<Declaration const*> const& declarations = m_enclosingContainer->resolveName(name, std::move(settings));
vector<Declaration const*> const& declarations = m_enclosingContainer->resolveName(name, std::move(settings));
if (!declarations.empty())
_it = make_pair(location, declarations);
}

View File

@ -29,6 +29,7 @@
#include <range/v3/view/transform.hpp>
using namespace std;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -335,10 +336,10 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
if (Expression const* length = _typeName.length())
{
std::optional<rational> lengthValue;
optional<rational> lengthValue;
if (length->annotation().type && length->annotation().type->category() == Type::Category::RationalNumber)
lengthValue = dynamic_cast<RationalNumberType const&>(*length->annotation().type).value();
else if (std::optional<ConstantEvaluator::TypedRational> value = ConstantEvaluator::evaluate(m_errorReporter, *length))
else if (optional<ConstantEvaluator::TypedRational> value = ConstantEvaluator::evaluate(m_errorReporter, *length))
lengthValue = value->value;
if (!lengthValue)
@ -398,10 +399,10 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
Location varLoc = _variable.referenceLocation();
DataLocation typeLoc = DataLocation::Memory;
std::set<Location> allowedDataLocations = _variable.allowedDataLocations();
set<Location> allowedDataLocations = _variable.allowedDataLocations();
if (!allowedDataLocations.count(varLoc))
{
auto locationToString = [](VariableDeclaration::Location _location) -> std::string
auto locationToString = [](VariableDeclaration::Location _location) -> string
{
switch (_location)
{
@ -413,7 +414,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
return {};
};
std::string errorString;
string errorString;
if (!_variable.hasReferenceOrMappingType())
errorString = "Data location can only be specified for array, struct or mapping types";
else
@ -429,9 +430,9 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
else if (_variable.isCallableOrCatchParameter())
errorString +=
" for " +
std::string(_variable.isReturnParameter() ? "return " : "") +
string(_variable.isReturnParameter() ? "return " : "") +
"parameter in" +
std::string(_variable.isExternalCallableParameter() ? " external" : "") +
string(_variable.isExternalCallableParameter() ? " external" : "") +
" function";
else
errorString += " for variable";

View File

@ -30,6 +30,7 @@
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -37,7 +38,7 @@ using namespace solidity::frontend;
namespace
{
void copyMissingTags(std::set<CallableDeclaration const*> const& _baseFunctions, StructurallyDocumentedAnnotation& _target, FunctionType const* _functionType = nullptr)
void copyMissingTags(set<CallableDeclaration const*> const& _baseFunctions, StructurallyDocumentedAnnotation& _target, FunctionType const* _functionType = nullptr)
{
// Only copy if there is exactly one direct base function.
if (_baseFunctions.size() != 1)
@ -49,7 +50,7 @@ void copyMissingTags(std::set<CallableDeclaration const*> const& _baseFunctions,
for (auto it = sourceDoc.docTags.begin(); it != sourceDoc.docTags.end();)
{
std::string const& tag = it->first;
string const& tag = it->first;
// Don't copy tag "inheritdoc", custom tags or already existing tags
if (tag == "inheritdoc" || _target.docTags.count(tag) || boost::starts_with(tag, "custom"))
{
@ -67,7 +68,7 @@ void copyMissingTags(std::set<CallableDeclaration const*> const& _baseFunctions,
if (_functionType && tag == "return")
{
size_t docParaNameEndPos = content.content.find_first_of(" \t");
std::string const docParameterName = content.content.substr(0, docParaNameEndPos);
string const docParameterName = content.content.substr(0, docParaNameEndPos);
if (
_functionType->returnParameterNames().size() > n &&
@ -79,10 +80,10 @@ void copyMissingTags(std::set<CallableDeclaration const*> const& _baseFunctions,
baseFunction.returnParameters().size() > n &&
baseFunction.returnParameters().at(n)->name().empty();
std::string paramName = _functionType->returnParameterNames().at(n);
string paramName = _functionType->returnParameterNames().at(n);
content.content =
(paramName.empty() ? "" : std::move(paramName) + " ") + (
std::string::npos == docParaNameEndPos || baseHasNoName ?
string::npos == docParaNameEndPos || baseHasNoName ?
content.content :
content.content.substr(docParaNameEndPos + 1)
);
@ -94,7 +95,7 @@ void copyMissingTags(std::set<CallableDeclaration const*> const& _baseFunctions,
}
}
CallableDeclaration const* findBaseCallable(std::set<CallableDeclaration const*> const& _baseFunctions, int64_t _contractId)
CallableDeclaration const* findBaseCallable(set<CallableDeclaration const*> const& _baseFunctions, int64_t _contractId)
{
for (CallableDeclaration const* baseFuncCandidate: _baseFunctions)
if (baseFuncCandidate->annotation().contract->id() == _contractId)
@ -180,7 +181,7 @@ void DocStringAnalyser::handleCallable(
}
CallableDeclaration const* DocStringAnalyser::resolveInheritDoc(
std::set<CallableDeclaration const*> const& _baseFuncs,
set<CallableDeclaration const*> const& _baseFuncs,
StructurallyDocumented const& _node,
StructurallyDocumentedAnnotation& _annotation
)

View File

@ -37,6 +37,7 @@
#include <regex>
#include <string_view>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -66,7 +67,7 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
if (tagName == "return")
{
returnTagsVisited++;
std::vector<std::string> returnParameterNames;
vector<string> returnParameterNames;
if (auto const* varDecl = dynamic_cast<VariableDeclaration const*>(&_node))
{
@ -81,8 +82,8 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
else
continue;
std::string content = tagValue.content;
std::string firstWord = content.substr(0, content.find_first_of(" \t"));
string content = tagValue.content;
string firstWord = content.substr(0, content.find_first_of(" \t"));
if (returnTagsVisited > returnParameterNames.size())
m_errorReporter.docstringParsingError(
@ -93,7 +94,7 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
);
else
{
std::string const& parameter = returnParameterNames.at(returnTagsVisited - 1);
string const& parameter = returnParameterNames.at(returnTagsVisited - 1);
if (!parameter.empty() && parameter != firstWord)
m_errorReporter.docstringParsingError(
5856_error,
@ -112,7 +113,7 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
bool DocStringTagParser::visit(ContractDefinition const& _contract)
{
static std::set<std::string> const validTags = std::set<std::string>{"author", "title", "dev", "notice"};
static set<string> const validTags = set<string>{"author", "title", "dev", "notice"};
parseDocStrings(_contract, _contract.annotation(), validTags, "contracts");
return true;
@ -192,12 +193,12 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly)
{
if (tagName == "solidity")
{
std::vector<std::string> values;
vector<string> values;
boost::split(values, tagValue.content, isWhiteSpace);
std::set<std::string> valuesSeen;
std::set<std::string> duplicates;
for (auto const& value: values | ranges::views::filter(not_fn(&std::string::empty)))
set<string> valuesSeen;
set<string> duplicates;
for (auto const& value: values | ranges::views::filter(not_fn(&string::empty)))
if (valuesSeen.insert(value).second)
{
if (value == "memory-safe-assembly")
@ -243,7 +244,7 @@ void DocStringTagParser::checkParameters(
StructurallyDocumentedAnnotation& _annotation
)
{
std::set<std::string> validParams;
set<string> validParams;
for (auto const& p: _callable.parameters())
validParams.insert(p->name());
if (_callable.returnParameterList())
@ -267,7 +268,7 @@ void DocStringTagParser::handleConstructor(
StructurallyDocumentedAnnotation& _annotation
)
{
static std::set<std::string> const validTags = std::set<std::string>{"author", "dev", "notice", "param"};
static set<string> const validTags = set<string>{"author", "dev", "notice", "param"};
parseDocStrings(_node, _annotation, validTags, "constructor");
checkParameters(_callable, _node, _annotation);
}
@ -278,10 +279,10 @@ void DocStringTagParser::handleCallable(
StructurallyDocumentedAnnotation& _annotation
)
{
static std::set<std::string> const validEventTags = std::set<std::string>{"dev", "notice", "return", "param"};
static std::set<std::string> const validErrorTags = std::set<std::string>{"dev", "notice", "param"};
static std::set<std::string> const validModifierTags = std::set<std::string>{"dev", "notice", "param", "inheritdoc"};
static std::set<std::string> const validTags = std::set<std::string>{"dev", "notice", "return", "param", "inheritdoc"};
static set<string> const validEventTags = set<string>{"dev", "notice", "return", "param"};
static set<string> const validErrorTags = set<string>{"dev", "notice", "param"};
static set<string> const validModifierTags = set<string>{"dev", "notice", "param", "inheritdoc"};
static set<string> const validTags = set<string>{"dev", "notice", "return", "param", "inheritdoc"};
if (dynamic_cast<EventDefinition const*>(&_callable))
parseDocStrings(_node, _annotation, validEventTags, "events");
@ -298,8 +299,8 @@ void DocStringTagParser::handleCallable(
void DocStringTagParser::parseDocStrings(
StructurallyDocumented const& _node,
StructurallyDocumentedAnnotation& _annotation,
std::set<std::string> const& _validTags,
std::string const& _nodeName
set<string> const& _validTags,
string const& _nodeName
)
{
if (!_node.documentation())
@ -309,7 +310,7 @@ void DocStringTagParser::parseDocStrings(
for (auto const& [tagName, tagValue]: _annotation.docTags)
{
std::string_view static constexpr customPrefix("custom:");
string_view static constexpr customPrefix("custom:");
if (tagName == "custom" || tagName == "custom:")
m_errorReporter.docstringParsingError(
6564_error,
@ -318,7 +319,7 @@ void DocStringTagParser::parseDocStrings(
);
else if (boost::starts_with(tagName, customPrefix) && tagName.size() > customPrefix.size())
{
std::regex static const customRegex("^custom:[a-z][a-z-]*$");
regex static const customRegex("^custom:[a-z][a-z-]*$");
if (!regex_match(tagName, customRegex))
m_errorReporter.docstringParsingError(
2968_error,

View File

@ -24,6 +24,7 @@
#include <range/v3/view/reverse.hpp>
#include <range/v3/view/transform.hpp>
using namespace std;
using namespace solidity::frontend;
using namespace solidity::util;
@ -71,7 +72,7 @@ CallGraph FunctionCallGraphBuilder::buildDeployedGraph(
FunctionCallGraphBuilder builder(_contract);
solAssert(builder.m_currentNode == CallGraph::Node(CallGraph::SpecialNode::Entry), "");
auto getSecondElement = [](auto const& _tuple){ return std::get<1>(_tuple); };
auto getSecondElement = [](auto const& _tuple){ return get<1>(_tuple); };
// Create graph for all publicly reachable functions
for (FunctionTypePointer functionType: _contract.interfaceFunctionList() | ranges::views::transform(getSecondElement))
@ -95,14 +96,14 @@ CallGraph FunctionCallGraphBuilder::buildDeployedGraph(
// All functions present in internal dispatch at creation time could potentially be pointers
// assigned to state variables and as such may be reachable after deployment as well.
builder.m_currentNode = CallGraph::SpecialNode::InternalDispatch;
std::set<CallGraph::Node, CallGraph::CompareByID> defaultNode;
set<CallGraph::Node, CallGraph::CompareByID> defaultNode;
for (CallGraph::Node const& dispatchTarget: util::valueOrDefault(_creationGraph.edges, CallGraph::SpecialNode::InternalDispatch, defaultNode))
{
solAssert(!std::holds_alternative<CallGraph::SpecialNode>(dispatchTarget), "");
solAssert(std::get<CallableDeclaration const*>(dispatchTarget) != nullptr, "");
solAssert(!holds_alternative<CallGraph::SpecialNode>(dispatchTarget), "");
solAssert(get<CallableDeclaration const*>(dispatchTarget) != nullptr, "");
// Visit the callable to add not only it but also everything it calls too
builder.functionReferenced(*std::get<CallableDeclaration const*>(dispatchTarget), false);
builder.functionReferenced(*get<CallableDeclaration const*>(dispatchTarget), false);
}
builder.m_currentNode = CallGraph::SpecialNode::Entry;
@ -261,10 +262,10 @@ void FunctionCallGraphBuilder::processQueue()
while (!m_visitQueue.empty())
{
m_currentNode = m_visitQueue.front();
solAssert(std::holds_alternative<CallableDeclaration const*>(m_currentNode), "");
solAssert(holds_alternative<CallableDeclaration const*>(m_currentNode), "");
m_visitQueue.pop_front();
std::get<CallableDeclaration const*>(m_currentNode)->accept(*this);
get<CallableDeclaration const*>(m_currentNode)->accept(*this);
}
m_currentNode = CallGraph::SpecialNode::Entry;
@ -280,7 +281,7 @@ void FunctionCallGraphBuilder::functionReferenced(CallableDeclaration const& _ca
if (_calledDirectly)
{
solAssert(
std::holds_alternative<CallGraph::SpecialNode>(m_currentNode) || m_graph.edges.count(m_currentNode) > 0,
holds_alternative<CallGraph::SpecialNode>(m_currentNode) || m_graph.edges.count(m_currentNode) > 0,
"Adding an edge from a node that has not been visited yet."
);
@ -292,10 +293,10 @@ void FunctionCallGraphBuilder::functionReferenced(CallableDeclaration const& _ca
enqueueCallable(_callable);
}
std::ostream& solidity::frontend::operator<<(std::ostream& _out, CallGraph::Node const& _node)
ostream& solidity::frontend::operator<<(ostream& _out, CallGraph::Node const& _node)
{
if (std::holds_alternative<CallGraph::SpecialNode>(_node))
switch (std::get<CallGraph::SpecialNode>(_node))
if (holds_alternative<CallGraph::SpecialNode>(_node))
switch (get<CallGraph::SpecialNode>(_node))
{
case CallGraph::SpecialNode::InternalDispatch:
_out << "InternalDispatch";
@ -308,19 +309,19 @@ std::ostream& solidity::frontend::operator<<(std::ostream& _out, CallGraph::Node
}
else
{
solAssert(std::holds_alternative<CallableDeclaration const*>(_node), "");
solAssert(holds_alternative<CallableDeclaration const*>(_node), "");
auto const* callableDeclaration = std::get<CallableDeclaration const*>(_node);
auto const* callableDeclaration = get<CallableDeclaration const*>(_node);
solAssert(callableDeclaration, "");
auto const* function = dynamic_cast<FunctionDefinition const *>(callableDeclaration);
auto const* event = dynamic_cast<EventDefinition const *>(callableDeclaration);
auto const* modifier = dynamic_cast<ModifierDefinition const *>(callableDeclaration);
auto typeToString = [](auto const& _var) -> std::string { return _var->type()->toString(true); };
std::vector<std::string> parameters = callableDeclaration->parameters() | ranges::views::transform(typeToString) | ranges::to<std::vector<std::string>>();
auto typeToString = [](auto const& _var) -> string { return _var->type()->toString(true); };
vector<string> parameters = callableDeclaration->parameters() | ranges::views::transform(typeToString) | ranges::to<vector<string>>();
std::string scopeName;
string scopeName;
if (!function || !function->isFree())
{
solAssert(callableDeclaration->annotation().scope, "");

View File

@ -29,6 +29,8 @@
#include <libsolidity/ast/Types.h>
#include <memory>
using namespace std;
namespace solidity::frontend
{
@ -63,10 +65,10 @@ int magicVariableToID(std::string const& _name)
solAssert(false, "Unknown magic variable: \"" + _name + "\".");
}
inline std::vector<std::shared_ptr<MagicVariableDeclaration const>> constructMagicVariables()
inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariables()
{
static auto const magicVarDecl = [](std::string const& _name, Type const* _type) {
return std::make_shared<MagicVariableDeclaration>(magicVariableToID(_name), _name, _type);
static auto const magicVarDecl = [](string const& _name, Type const* _type) {
return make_shared<MagicVariableDeclaration>(magicVariableToID(_name), _name, _type);
};
return {
@ -114,9 +116,9 @@ void GlobalContext::setCurrentContract(ContractDefinition const& _contract)
m_currentContract = &_contract;
}
std::vector<Declaration const*> GlobalContext::declarations() const
vector<Declaration const*> GlobalContext::declarations() const
{
std::vector<Declaration const*> declarations;
vector<Declaration const*> declarations;
declarations.reserve(m_magicVariables.size());
for (ASTPointer<MagicVariableDeclaration const> const& variable: m_magicVariables)
declarations.push_back(variable.get());
@ -131,7 +133,7 @@ MagicVariableDeclaration const* GlobalContext::currentThis() const
if (m_currentContract)
type = TypeProvider::contract(*m_currentContract);
m_thisPointer[m_currentContract] =
std::make_shared<MagicVariableDeclaration>(magicVariableToID("this"), "this", type);
make_shared<MagicVariableDeclaration>(magicVariableToID("this"), "this", type);
}
return m_thisPointer[m_currentContract].get();
}
@ -144,7 +146,7 @@ MagicVariableDeclaration const* GlobalContext::currentSuper() const
if (m_currentContract)
type = TypeProvider::typeType(TypeProvider::contract(*m_currentContract, true));
m_superPointer[m_currentContract] =
std::make_shared<MagicVariableDeclaration>(magicVariableToID("super"), "super", type);
make_shared<MagicVariableDeclaration>(magicVariableToID("super"), "super", type);
}
return m_superPointer[m_currentContract].get();
}

View File

@ -30,6 +30,7 @@
#include <boost/algorithm/string.hpp>
#include <unordered_set>
using namespace std;
using namespace solidity::langutil;
namespace solidity::frontend
@ -44,7 +45,7 @@ NameAndTypeResolver::NameAndTypeResolver(
m_errorReporter(_errorReporter),
m_globalContext(_globalContext)
{
m_scopes[nullptr] = std::make_shared<DeclarationContainer>();
m_scopes[nullptr] = make_shared<DeclarationContainer>();
for (Declaration const* declaration: _globalContext.declarations())
{
solAssert(m_scopes[nullptr]->registerDeclaration(*declaration, false, false), "Unable to register global declaration.");
@ -67,14 +68,14 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode
return true;
}
bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, std::map<std::string, SourceUnit const*> const& _sourceUnits)
bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, SourceUnit const*> const& _sourceUnits)
{
DeclarationContainer& target = *m_scopes.at(&_sourceUnit);
bool error = false;
for (auto const& node: _sourceUnit.nodes())
if (auto imp = dynamic_cast<ImportDirective const*>(node.get()))
{
std::string const& path = *imp->annotation().absolutePath;
string const& path = *imp->annotation().absolutePath;
// The import resolution in CompilerStack enforces this.
solAssert(_sourceUnits.count(path), "");
auto scope = m_scopes.find(_sourceUnits.at(path));
@ -126,7 +127,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(SourceUnit& _source)
{
try
{
for (std::shared_ptr<ASTNode> const& node: _source.nodes())
for (shared_ptr<ASTNode> const& node: _source.nodes())
{
setScope(&_source);
if (!resolveNamesAndTypesInternal(*node, true))
@ -158,7 +159,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
return true;
}
void NameAndTypeResolver::activateVariable(std::string const& _name)
void NameAndTypeResolver::activateVariable(string const& _name)
{
solAssert(m_currentScope, "");
// Scoped local variables are invisible before activation.
@ -170,15 +171,15 @@ void NameAndTypeResolver::activateVariable(std::string const& _name)
m_currentScope->activateVariable(_name);
}
std::vector<Declaration const*> NameAndTypeResolver::resolveName(ASTString const& _name, ASTNode const* _scope) const
vector<Declaration const*> NameAndTypeResolver::resolveName(ASTString const& _name, ASTNode const* _scope) const
{
auto iterator = m_scopes.find(_scope);
if (iterator == end(m_scopes))
return std::vector<Declaration const*>({});
return vector<Declaration const*>({});
return iterator->second->resolveName(_name);
}
std::vector<Declaration const*> NameAndTypeResolver::nameFromCurrentScope(ASTString const& _name, bool _includeInvisibles) const
vector<Declaration const*> NameAndTypeResolver::nameFromCurrentScope(ASTString const& _name, bool _includeInvisibles) const
{
ResolvingSettings settings;
settings.recursive = true;
@ -186,7 +187,7 @@ std::vector<Declaration const*> NameAndTypeResolver::nameFromCurrentScope(ASTStr
return m_currentScope->resolveName(_name, std::move(settings));
}
Declaration const* NameAndTypeResolver::pathFromCurrentScope(std::vector<ASTString> const& _path) const
Declaration const* NameAndTypeResolver::pathFromCurrentScope(vector<ASTString> const& _path) const
{
if (auto declarations = pathFromCurrentScopeWithAllDeclarations(_path); !declarations.empty())
return declarations.back();
@ -200,13 +201,13 @@ std::vector<Declaration const*> NameAndTypeResolver::pathFromCurrentScopeWithAll
) const
{
solAssert(!_path.empty(), "");
std::vector<Declaration const*> pathDeclarations;
vector<Declaration const*> pathDeclarations;
ResolvingSettings settings;
settings.recursive = true;
settings.alsoInvisible = _includeInvisibles;
settings.onlyVisibleAsUnqualifiedNames = true;
std::vector<Declaration const*> candidates = m_currentScope->resolveName(_path.front(), settings);
vector<Declaration const*> candidates = m_currentScope->resolveName(_path.front(), settings);
// inside the loop, use default settings, except for alsoInvisible
settings.recursive = false;
@ -304,7 +305,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
if (success)
{
linearizeBaseContracts(*contract);
std::vector<ContractDefinition const*> properBases(
vector<ContractDefinition const*> properBases(
++contract->annotation().linearizedBaseContracts.begin(),
contract->annotation().linearizedBaseContracts.end()
);
@ -404,7 +405,7 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
{
// order in the lists is from derived to base
// list of lists to linearize, the last element is the list of direct bases
std::list<std::list<ContractDefinition const*>> input(1, std::list<ContractDefinition const*>{});
list<list<ContractDefinition const*>> input(1, list<ContractDefinition const*>{});
for (ASTPointer<InheritanceSpecifier> const& baseSpecifier: _contract.baseContracts())
{
IdentifierPath const& baseName = baseSpecifier->name();
@ -414,25 +415,25 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
// "push_front" has the effect that bases mentioned later can overwrite members of bases
// mentioned earlier
input.back().push_front(base);
std::vector<ContractDefinition const*> const& basesBases = base->annotation().linearizedBaseContracts;
vector<ContractDefinition const*> const& basesBases = base->annotation().linearizedBaseContracts;
if (basesBases.empty())
m_errorReporter.fatalTypeError(2449_error, baseName.location(), "Definition of base has to precede definition of derived contract");
input.push_front(std::list<ContractDefinition const*>(basesBases.begin(), basesBases.end()));
input.push_front(list<ContractDefinition const*>(basesBases.begin(), basesBases.end()));
}
input.back().push_front(&_contract);
std::vector<ContractDefinition const*> result = cThreeMerge(input);
vector<ContractDefinition const*> result = cThreeMerge(input);
if (result.empty())
m_errorReporter.fatalTypeError(5005_error, _contract.location(), "Linearization of inheritance graph impossible");
_contract.annotation().linearizedBaseContracts = result;
}
template <class T>
std::vector<T const*> NameAndTypeResolver::cThreeMerge(std::list<std::list<T const*>>& _toMerge)
vector<T const*> NameAndTypeResolver::cThreeMerge(list<list<T const*>>& _toMerge)
{
// returns true iff _candidate appears only as last element of the lists
auto appearsOnlyAtHead = [&](T const* _candidate) -> bool
{
for (std::list<T const*> const& bases: _toMerge)
for (list<T const*> const& bases: _toMerge)
{
solAssert(!bases.empty(), "");
if (find(++bases.begin(), bases.end(), _candidate) != bases.end())
@ -443,7 +444,7 @@ std::vector<T const*> NameAndTypeResolver::cThreeMerge(std::list<std::list<T con
// returns the next candidate to append to the linearized list or nullptr on failure
auto nextCandidate = [&]() -> T const*
{
for (std::list<T const*> const& bases: _toMerge)
for (list<T const*> const& bases: _toMerge)
{
solAssert(!bases.empty(), "");
if (appearsOnlyAtHead(bases.front()))
@ -464,26 +465,26 @@ std::vector<T const*> NameAndTypeResolver::cThreeMerge(std::list<std::list<T con
}
};
_toMerge.remove_if([](std::list<T const*> const& _bases) { return _bases.empty(); });
std::vector<T const*> result;
_toMerge.remove_if([](list<T const*> const& _bases) { return _bases.empty(); });
vector<T const*> result;
while (!_toMerge.empty())
{
T const* candidate = nextCandidate();
if (!candidate)
return std::vector<T const*>();
return vector<T const*>();
result.push_back(candidate);
removeCandidate(candidate);
}
return result;
}
std::string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const
string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const
{
return util::quotedAlternativesList(m_currentScope->similarNames(_name));
}
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot,
ErrorReporter& _errorReporter,
GlobalContext& _globalContext,
@ -501,7 +502,7 @@ DeclarationRegistrationHelper::DeclarationRegistrationHelper(
bool DeclarationRegistrationHelper::registerDeclaration(
DeclarationContainer& _container,
Declaration const& _declaration,
std::string const* _name,
string const* _name,
SourceLocation const* _errorLocation,
bool _inactive,
ErrorReporter& _errorReporter
@ -510,13 +511,13 @@ bool DeclarationRegistrationHelper::registerDeclaration(
if (!_errorLocation)
_errorLocation = &_declaration.location();
std::string name = _name ? *_name : _declaration.name();
string name = _name ? *_name : _declaration.name();
// We use "invisible" for both inactive variables in blocks and for members invisible in contracts.
// They cannot both be true at the same time.
solAssert(!(_inactive && !_declaration.isVisibleInContract()), "");
static std::set<std::string> illegalNames{"_", "super", "this"};
static set<string> illegalNames{"_", "super", "this"};
if (illegalNames.count(name))
{
@ -579,7 +580,7 @@ bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit)
{
if (!m_scopes[&_sourceUnit])
// By importing, it is possible that the container already exists.
m_scopes[&_sourceUnit] = std::make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get());
m_scopes[&_sourceUnit] = make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get());
return ASTVisitor::visit(_sourceUnit);
}
@ -593,7 +594,7 @@ bool DeclarationRegistrationHelper::visit(ImportDirective& _import)
SourceUnit const* importee = _import.annotation().sourceUnit;
solAssert(!!importee, "");
if (!m_scopes[importee])
m_scopes[importee] = std::make_shared<DeclarationContainer>(nullptr, m_scopes[nullptr].get());
m_scopes[importee] = make_shared<DeclarationContainer>(nullptr, m_scopes[nullptr].get());
m_scopes[&_import] = m_scopes[importee];
ASTVisitor::visit(_import);
return false; // Do not recurse into child nodes (Identifier for symbolAliases)
@ -640,7 +641,7 @@ bool DeclarationRegistrationHelper::visitNode(ASTNode& _node)
if (auto* annotation = dynamic_cast<TypeDeclarationAnnotation*>(&_node.annotation()))
{
std::string canonicalName = dynamic_cast<Declaration const&>(_node).name();
string canonicalName = dynamic_cast<Declaration const&>(_node).name();
solAssert(!canonicalName.empty(), "");
for (
@ -683,7 +684,7 @@ void DeclarationRegistrationHelper::enterNewSubScope(ASTNode& _subScope)
{
bool newlyAdded = m_scopes.emplace(
&_subScope,
std::make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get())
make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get())
).second;
solAssert(newlyAdded, "Unable to add new scope.");
}

View File

@ -31,6 +31,7 @@
#include <boost/algorithm/string/predicate.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::langutil;
@ -45,7 +46,7 @@ namespace
// Helper struct to do a search by name
struct MatchByName
{
std::string const& m_name;
string const& m_name;
bool operator()(OverrideProxy const& _item)
{
return _item.name() == m_name;
@ -60,7 +61,7 @@ struct MatchByName
*/
struct OverrideGraph
{
OverrideGraph(std::set<OverrideProxy> const& _baseCallables)
OverrideGraph(set<OverrideProxy> const& _baseCallables)
{
for (auto const& baseFunction: _baseCallables)
addEdge(0, visit(baseFunction));
@ -130,17 +131,17 @@ private:
run(vInd, _depth + 1);
if (m_low[vInd] >= m_depths[_u] && m_parent[_u] != -1)
m_cutVertices.insert(m_graph.nodeInv.at(static_cast<int>(_u)));
m_low[_u] = std::min(m_low[_u], m_low[vInd]);
m_low[_u] = min(m_low[_u], m_low[vInd]);
}
else if (v != m_parent[_u])
m_low[_u] = std::min(m_low[_u], m_depths[vInd]);
m_low[_u] = min(m_low[_u], m_depths[vInd]);
}
}
};
std::vector<ContractDefinition const*> resolveDirectBaseContracts(ContractDefinition const& _contract)
vector<ContractDefinition const*> resolveDirectBaseContracts(ContractDefinition const& _contract)
{
std::vector<ContractDefinition const*> resolvedContracts;
vector<ContractDefinition const*> resolvedContracts;
for (ASTPointer<InheritanceSpecifier> const& specifier: _contract.baseContracts())
{
@ -154,7 +155,7 @@ std::vector<ContractDefinition const*> resolveDirectBaseContracts(ContractDefini
return resolvedContracts;
}
std::vector<ASTPointer<IdentifierPath>> sortByContract(std::vector<ASTPointer<IdentifierPath>> const& _list)
vector<ASTPointer<IdentifierPath>> sortByContract(vector<ASTPointer<IdentifierPath>> const& _list)
{
auto sorted = _list;
@ -196,17 +197,17 @@ bool OverrideProxy::operator<(OverrideProxy const& _other) const
bool OverrideProxy::isVariable() const
{
return std::holds_alternative<VariableDeclaration const*>(m_item);
return holds_alternative<VariableDeclaration const*>(m_item);
}
bool OverrideProxy::isFunction() const
{
return std::holds_alternative<FunctionDefinition const*>(m_item);
return holds_alternative<FunctionDefinition const*>(m_item);
}
bool OverrideProxy::isModifier() const
{
return std::holds_alternative<ModifierDefinition const*>(m_item);
return holds_alternative<ModifierDefinition const*>(m_item);
}
bool OverrideProxy::CompareBySignature::operator()(OverrideProxy const& _a, OverrideProxy const& _b) const
@ -221,18 +222,18 @@ size_t OverrideProxy::id() const
}, m_item);
}
std::shared_ptr<OverrideSpecifier> OverrideProxy::overrides() const
shared_ptr<OverrideSpecifier> OverrideProxy::overrides() const
{
return std::visit(GenericVisitor{
[&](auto const* _item) { return _item->overrides(); }
}, m_item);
}
std::set<OverrideProxy> OverrideProxy::baseFunctions() const
set<OverrideProxy> OverrideProxy::baseFunctions() const
{
return std::visit(GenericVisitor{
[&](auto const* _item) -> std::set<OverrideProxy> {
std::set<OverrideProxy> ret;
[&](auto const* _item) -> set<OverrideProxy> {
set<OverrideProxy> ret;
for (auto const* f: _item->annotation().baseFunctions)
ret.insert(makeOverrideProxy(*f));
return ret;
@ -255,10 +256,10 @@ void OverrideProxy::storeBaseFunction(OverrideProxy const& _base) const
}, m_item);
}
std::string const& OverrideProxy::name() const
string const& OverrideProxy::name() const
{
return std::visit(GenericVisitor{
[&](auto const* _item) -> std::string const& { return _item->name(); }
[&](auto const* _item) -> string const& { return _item->name(); }
}, m_item);
}
@ -271,7 +272,7 @@ ContractDefinition const& OverrideProxy::contract() const
}, m_item);
}
std::string const& OverrideProxy::contractName() const
string const& OverrideProxy::contractName() const
{
return contract().name();
}
@ -356,7 +357,7 @@ SourceLocation const& OverrideProxy::location() const
}, m_item);
}
std::string OverrideProxy::astNodeName() const
string OverrideProxy::astNodeName() const
{
return std::visit(GenericVisitor{
[&](FunctionDefinition const*) { return "function"; },
@ -365,7 +366,7 @@ std::string OverrideProxy::astNodeName() const
}, m_item);
}
std::string OverrideProxy::astNodeNameCapitalized() const
string OverrideProxy::astNodeNameCapitalized() const
{
return std::visit(GenericVisitor{
[&](FunctionDefinition const*) { return "Function"; },
@ -374,7 +375,7 @@ std::string OverrideProxy::astNodeNameCapitalized() const
}, m_item);
}
std::string OverrideProxy::distinguishingProperty() const
string OverrideProxy::distinguishingProperty() const
{
return std::visit(GenericVisitor{
[&](FunctionDefinition const*) { return "name and parameter types"; },
@ -417,10 +418,10 @@ OverrideProxy::OverrideComparator const& OverrideProxy::overrideComparator() con
{
if (!m_comparator)
{
m_comparator = std::make_shared<OverrideComparator>(std::visit(GenericVisitor{
m_comparator = make_shared<OverrideComparator>(std::visit(GenericVisitor{
[&](FunctionDefinition const* _function)
{
std::vector<std::string> paramTypes;
vector<string> paramTypes;
for (Type const* t: externalFunctionType()->parameterTypes())
paramTypes.emplace_back(t->richIdentifier());
return OverrideComparator{
@ -431,7 +432,7 @@ OverrideProxy::OverrideComparator const& OverrideProxy::overrideComparator() con
},
[&](VariableDeclaration const* _var)
{
std::vector<std::string> paramTypes;
vector<string> paramTypes;
for (Type const* t: externalFunctionType()->parameterTypes())
paramTypes.emplace_back(t->richIdentifier());
return OverrideComparator{
@ -673,21 +674,21 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
void OverrideChecker::overrideListError(
OverrideProxy const& _item,
std::set<ContractDefinition const*, CompareByID> _secondary,
set<ContractDefinition const*, CompareByID> _secondary,
ErrorId _error,
std::string const& _message1,
std::string const& _message2
string const& _message1,
string const& _message2
)
{
// Using a set rather than a vector so the order is always the same
std::set<std::string> names;
set<string> names;
SecondarySourceLocation ssl;
for (Declaration const* c: _secondary)
{
ssl.append("This contract: ", c->location());
names.insert("\"" + c->name() + "\"");
}
std::string contractSingularPlural = "contract ";
string contractSingularPlural = "contract ";
if (_secondary.size() > 1)
contractSingularPlural = "contracts ";
@ -707,8 +708,8 @@ void OverrideChecker::overrideError(
OverrideProxy const& _overriding,
OverrideProxy const& _super,
ErrorId _error,
std::string const& _message,
std::optional<std::string> const& _secondaryMsg
string const& _message,
optional<string> const& _secondaryMsg
)
{
m_errorReporter.typeError(
@ -765,7 +766,7 @@ void OverrideChecker::checkAmbiguousOverrides(ContractDefinition const& _contrac
}
}
void OverrideChecker::checkAmbiguousOverridesInternal(std::set<OverrideProxy> _baseCallables, SourceLocation const& _location) const
void OverrideChecker::checkAmbiguousOverridesInternal(set<OverrideProxy> _baseCallables, SourceLocation const& _location) const
{
if (_baseCallables.size() <= 1)
return;
@ -798,17 +799,17 @@ void OverrideChecker::checkAmbiguousOverridesInternal(std::set<OverrideProxy> _b
for (OverrideProxy const& baseFunction: _baseCallables)
ssl.append("Definition in \"" + baseFunction.contractName() + "\": ", baseFunction.location());
std::string callableName = _baseCallables.begin()->astNodeName();
string callableName = _baseCallables.begin()->astNodeName();
if (_baseCallables.begin()->isVariable())
callableName = "function";
std::string distinguishigProperty = _baseCallables.begin()->distinguishingProperty();
string distinguishigProperty = _baseCallables.begin()->distinguishingProperty();
bool foundVariable = false;
for (auto const& base: _baseCallables)
if (base.isVariable())
foundVariable = true;
std::string message =
string message =
"Derived contract must override " + callableName + " \"" +
_baseCallables.begin()->name() +
"\". Two or more base classes define " + callableName + " with same " + distinguishigProperty + ".";
@ -821,9 +822,9 @@ void OverrideChecker::checkAmbiguousOverridesInternal(std::set<OverrideProxy> _b
m_errorReporter.typeError(6480_error, _location, ssl, message);
}
std::set<ContractDefinition const*, OverrideChecker::CompareByID> OverrideChecker::resolveOverrideList(OverrideSpecifier const& _overrides) const
set<ContractDefinition const*, OverrideChecker::CompareByID> OverrideChecker::resolveOverrideList(OverrideSpecifier const& _overrides) const
{
std::set<ContractDefinition const*, CompareByID> resolved;
set<ContractDefinition const*, CompareByID> resolved;
for (ASTPointer<IdentifierPath> const& override: _overrides.overrides())
{
@ -841,7 +842,7 @@ std::set<ContractDefinition const*, OverrideChecker::CompareByID> OverrideChecke
void OverrideChecker::checkOverrideList(OverrideProxy _item, OverrideProxyBySignatureMultiSet const& _inherited)
{
std::set<ContractDefinition const*, CompareByID> specifiedContracts =
set<ContractDefinition const*, CompareByID> specifiedContracts =
_item.overrides() ?
resolveOverrideList(*_item.overrides()) :
decltype(specifiedContracts){};
@ -850,7 +851,7 @@ void OverrideChecker::checkOverrideList(OverrideProxy _item, OverrideProxyBySign
if (_item.overrides() && specifiedContracts.size() != _item.overrides()->overrides().size())
{
// Sort by contract id to find duplicate for error reporting
std::vector<ASTPointer<IdentifierPath>> list =
vector<ASTPointer<IdentifierPath>> list =
sortByContract(_item.overrides()->overrides());
// Find duplicates and output error
@ -879,7 +880,7 @@ void OverrideChecker::checkOverrideList(OverrideProxy _item, OverrideProxyBySign
}
}
std::set<ContractDefinition const*, CompareByID> expectedContracts;
set<ContractDefinition const*, CompareByID> expectedContracts;
// Build list of expected contracts
for (auto [begin, end] = _inherited.equal_range(_item); begin != end; begin++)
@ -897,7 +898,7 @@ void OverrideChecker::checkOverrideList(OverrideProxy _item, OverrideProxyBySign
_item.astNodeNameCapitalized() + " has override specified but does not override anything."
);
std::set<ContractDefinition const*, CompareByID> missingContracts;
set<ContractDefinition const*, CompareByID> missingContracts;
// If we expect only one contract, no contract needs to be specified
if (expectedContracts.size() > 1)
missingContracts = expectedContracts - specifiedContracts;
@ -930,7 +931,7 @@ OverrideChecker::OverrideProxyBySignatureMultiSet const& OverrideChecker::inheri
for (auto const* base: resolveDirectBaseContracts(_contract))
{
std::set<OverrideProxy, OverrideProxy::CompareBySignature> functionsInBase;
set<OverrideProxy, OverrideProxy::CompareBySignature> functionsInBase;
for (FunctionDefinition const* fun: base->definedFunctions())
if (!fun->isConstructor())
functionsInBase.emplace(OverrideProxy{fun});
@ -959,7 +960,7 @@ OverrideChecker::OverrideProxyBySignatureMultiSet const& OverrideChecker::inheri
for (auto const* base: resolveDirectBaseContracts(_contract))
{
std::set<OverrideProxy, OverrideProxy::CompareBySignature> modifiersInBase;
set<OverrideProxy, OverrideProxy::CompareBySignature> modifiersInBase;
for (ModifierDefinition const* mod: base->functionModifiers())
modifiersInBase.emplace(OverrideProxy{mod});

View File

@ -27,6 +27,7 @@
#include <memory>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -203,7 +204,7 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker
// Iterating through the dependencies needs to be deterministic and thus cannot
// depend on the memory layout.
// Because of that, we sort by AST node id.
std::vector<VariableDeclaration const*> dependencies(
vector<VariableDeclaration const*> dependencies(
m_constVariableDependencies[&_variable].begin(),
m_constVariableDependencies[&_variable].end()
);
@ -426,10 +427,10 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker
PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter)
{
m_checkers.push_back(std::make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
m_checkers.push_back(std::make_shared<OverrideSpecifierChecker>(_errorReporter));
m_checkers.push_back(std::make_shared<ModifierContextChecker>(_errorReporter));
m_checkers.push_back(std::make_shared<EventOutsideEmitErrorOutsideRevertChecker>(_errorReporter));
m_checkers.push_back(std::make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
m_checkers.push_back(std::make_shared<ReservedErrorSelector>(_errorReporter));
m_checkers.push_back(make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter));
m_checkers.push_back(make_shared<ModifierContextChecker>(_errorReporter));
m_checkers.push_back(make_shared<EventOutsideEmitErrorOutsideRevertChecker>(_errorReporter));
m_checkers.push_back(make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
m_checkers.push_back(make_shared<ReservedErrorSelector>(_errorReporter));
}

View File

@ -26,6 +26,7 @@
#include <libsolutil/FunctionSelector.h>
#include <liblangutil/ErrorReporter.h>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -47,10 +48,10 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract)
""
);
std::map<uint32_t, std::map<std::string, SourceLocation>> errorHashes;
map<uint32_t, map<string, SourceLocation>> errorHashes;
for (ErrorDefinition const* error: _contract.interfaceErrors())
{
std::string signature = error->functionType(true)->externalSignature();
string signature = error->functionType(true)->externalSignature();
uint32_t hash = util::selectorFromSignatureU32(signature);
// Fail if there is a different signature for the same hash.
if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature))

View File

@ -39,6 +39,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -120,8 +121,8 @@ bool ReferencesResolver::visit(Identifier const& _identifier)
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name());
if (declarations.empty())
{
std::string suggestions = m_resolver.similarNameSuggestions(_identifier.name());
std::string errorMessage = "Undeclared identifier.";
string suggestions = m_resolver.similarNameSuggestions(_identifier.name());
string errorMessage = "Undeclared identifier.";
if (!suggestions.empty())
{
if ("\"" + _identifier.name() + "\"" == suggestions)
@ -191,10 +192,10 @@ bool ReferencesResolver::visit(UsingForDirective const& _usingFor)
// _includeInvisibles is enabled here because external library functions are marked invisible.
// As unintended side-effects other invisible names (eg.: super, this) may be returned as well.
// DeclarationTypeChecker should detect and report such situations.
std::vector<Declaration const*> declarations = m_resolver.pathFromCurrentScopeWithAllDeclarations(path->path(), true /* _includeInvisibles */);
vector<Declaration const*> declarations = m_resolver.pathFromCurrentScopeWithAllDeclarations(path->path(), true /* _includeInvisibles */);
if (declarations.empty())
{
std::string libraryOrFunctionNameErrorMessage =
string libraryOrFunctionNameErrorMessage =
_usingFor.usesBraces() ?
"Identifier is not a function name or not unique." :
"Identifier is not a library name.";
@ -252,9 +253,9 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
{
solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), "");
static std::set<std::string> suffixes{"slot", "offset", "length", "address", "selector"};
std::string suffix;
for (std::string const& s: suffixes)
static set<string> suffixes{"slot", "offset", "length", "address", "selector"};
string suffix;
for (string const& s: suffixes)
if (boost::algorithm::ends_with(_identifier.name.str(), "." + s))
suffix = s;
@ -268,7 +269,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
if (!declarations.empty())
// the special identifier exists itself, we should not allow that.
return;
std::string realName = _identifier.name.str().substr(0, _identifier.name.str().size() - suffix.size() - 1);
string realName = _identifier.name.str().substr(0, _identifier.name.str().size() - suffix.size() - 1);
solAssert(!realName.empty(), "Empty name.");
declarations = m_resolver.nameFromCurrentScope(realName);
if (!declarations.empty())
@ -349,7 +350,7 @@ void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _docum
break;
case 1:
{
std::string const& name = _annotation.docTags.find("inheritdoc")->second.content;
string const& name = _annotation.docTags.find("inheritdoc")->second.content;
if (name.empty())
{
m_errorReporter.docstringParsingError(
@ -360,7 +361,7 @@ void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _docum
return;
}
std::vector<std::string> path;
vector<string> path;
boost::split(path, name, boost::is_any_of("."));
if (any_of(path.begin(), path.end(), [](auto& _str) { return _str.empty(); }))
{
@ -420,7 +421,7 @@ void ReferencesResolver::validateYulIdentifierName(yul::YulString _name, SourceL
"User-defined identifiers in inline assembly cannot contain '.'."
);
if (std::set<std::string>{"this", "super", "_"}.count(_name.str()))
if (set<string>{"this", "super", "_"}.count(_name.str()))
m_errorReporter.declarationError(
4113_error,
_location,

View File

@ -20,6 +20,7 @@
#include <libsolidity/ast/AST.h>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;

View File

@ -28,6 +28,7 @@
#include <liblangutil/ErrorReporter.h>
#include <memory>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -70,7 +71,7 @@ private:
return m_usesAssembly[&_contract];
}
std::map<ContractDefinition const*, bool> m_usesAssembly;
map<ContractDefinition const*, bool> m_usesAssembly;
};
StaticAnalyzer::StaticAnalyzer(ErrorReporter& _errorReporter):
@ -123,7 +124,7 @@ void StaticAnalyzer::endVisit(FunctionDefinition const&)
5667_error,
var.first.second->location(),
"Unused " +
std::string(var.first.second->isTryCatchParameter() ? "try/catch" : "function") +
string(var.first.second->isTryCatchParameter() ? "try/catch" : "function") +
" parameter. Remove or comment out the variable name to silence this warning."
);
else
@ -141,7 +142,7 @@ bool StaticAnalyzer::visit(Identifier const& _identifier)
{
solAssert(!var->name().empty(), "");
if (var->isLocalVariable())
m_localVarUseCount[std::make_pair(var->id(), var)] += 1;
m_localVarUseCount[make_pair(var->id(), var)] += 1;
}
return true;
}
@ -153,7 +154,7 @@ bool StaticAnalyzer::visit(VariableDeclaration const& _variable)
solAssert(_variable.isLocalVariable(), "");
if (_variable.name() != "")
// This is not a no-op, the entry might pre-exist.
m_localVarUseCount[std::make_pair(_variable.id(), &_variable)] += 0;
m_localVarUseCount[make_pair(_variable.id(), &_variable)] += 0;
}
if (_variable.isStateVariable() || _variable.referenceLocation() == VariableDeclaration::Location::Storage)
@ -161,7 +162,7 @@ bool StaticAnalyzer::visit(VariableDeclaration const& _variable)
for (Type const* type: varType->fullDecomposition())
if (type->storageSizeUpperBound() >= (bigint(1) << 64))
{
std::string message = "Type " + type->toString(true) +
string message = "Type " + type->toString(true) +
" covers a large part of storage and thus makes collisions likely."
" Either use mappings or dynamic arrays and allow their size to be increased only"
" in small quantities per transaction.";
@ -178,7 +179,7 @@ bool StaticAnalyzer::visit(Return const& _return)
if (m_currentFunction && _return.expression())
for (auto const& var: m_currentFunction->returnParameters())
if (!var->name().empty())
m_localVarUseCount[std::make_pair(var->id(), var.get())] += 1;
m_localVarUseCount[make_pair(var->id(), var.get())] += 1;
return true;
}
@ -213,7 +214,7 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
else if (type->kind() == MagicType::Kind::MetaType && _memberAccess.memberName() == "runtimeCode")
{
if (!m_constructorUsesAssembly)
m_constructorUsesAssembly = std::make_unique<ConstructorUsesAssembly>();
m_constructorUsesAssembly = make_unique<ConstructorUsesAssembly>();
ContractType const& contract = dynamic_cast<ContractType const&>(*type->typeArgument());
if (m_constructorUsesAssembly->check(contract.contractDefinition()))
m_errorReporter.warning(
@ -287,7 +288,7 @@ bool StaticAnalyzer::visit(InlineAssembly const& _inlineAssembly)
{
solAssert(!var->name().empty(), "");
if (var->isLocalVariable())
m_localVarUseCount[std::make_pair(var->id(), var)] += 1;
m_localVarUseCount[make_pair(var->id(), var)] += 1;
}
}

View File

@ -32,6 +32,7 @@
#include <string>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -54,17 +55,17 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
{
if (!m_versionPragmaFound)
{
std::string errorString("Source file does not specify required compiler version!");
SemVerVersion recommendedVersion{std::string(VersionString)};
string errorString("Source file does not specify required compiler version!");
SemVerVersion recommendedVersion{string(VersionString)};
if (!recommendedVersion.isPrerelease())
errorString +=
" Consider adding \"pragma solidity ^" +
std::to_string(recommendedVersion.major()) +
std::string(".") +
std::to_string(recommendedVersion.minor()) +
std::string(".") +
std::to_string(recommendedVersion.patch()) +
std::string(";\"");
to_string(recommendedVersion.major()) +
string(".") +
to_string(recommendedVersion.minor()) +
string(".") +
to_string(recommendedVersion.patch()) +
string(";\"");
// when reporting the warning, print the source name only
m_errorReporter.warning(3420_error, {-1, -1, _sourceUnit.location().sourceName}, errorString);
@ -83,7 +84,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
else if (_pragma.literals()[0] == "experimental")
{
solAssert(m_sourceUnit, "");
std::vector<std::string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
vector<string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
if (literals.empty())
m_errorReporter.syntaxError(
9679_error,
@ -98,7 +99,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
);
else
{
std::string const literal = literals[0];
string const literal = literals[0];
if (literal.empty())
m_errorReporter.syntaxError(3250_error, _pragma.location(), "Empty experimental feature name is invalid.");
else if (!ExperimentalFeatureNames.count(literal))
@ -134,7 +135,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
solAssert(m_sourceUnit, "");
if (
_pragma.literals().size() != 2 ||
!std::set<std::string>{"v1", "v2"}.count(_pragma.literals()[1])
!set<string>{"v1", "v2"}.count(_pragma.literals()[1])
)
m_errorReporter.syntaxError(
2745_error,
@ -154,12 +155,19 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
{
try
{
std::vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
std::vector<std::string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
vector<string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
SemVerMatchExpressionParser parser(tokens, literals);
SemVerMatchExpression matchExpression = parser.parse();
static SemVerVersion const currentVersion{std::string(VersionString)};
solAssert(matchExpression.matches(currentVersion));
static SemVerVersion const currentVersion{string(VersionString)};
if (!matchExpression.matches(currentVersion))
m_errorReporter.syntaxError(
3997_error,
_pragma.location(),
"Source file requires different compiler version (current compiler is " +
string(VersionString) + ") - note that nightly builds are considered to be "
"strictly less than the released version"
);
m_versionPragmaFound = true;
}
catch (SemVerError const&)
@ -404,7 +412,7 @@ bool SyntaxChecker::visit(UsingForDirective const& _usingFor)
if (!_usingFor.usesBraces())
solAssert(
_usingFor.functionsAndOperators().size() == 1 &&
!std::get<1>(_usingFor.functionsAndOperators().front())
!get<1>(_usingFor.functionsAndOperators().front())
);
if (!m_currentContractKind && !_usingFor.typeName())
@ -447,7 +455,7 @@ bool SyntaxChecker::visit(FunctionDefinition const& _function)
if (!_function.isFree() && !_function.isConstructor() && _function.noVisibilitySpecified())
{
std::string suggestedVisibility =
string suggestedVisibility =
_function.isFallback() ||
_function.isReceive() ||
m_currentContractKind == ContractKind::Interface

View File

@ -51,6 +51,7 @@
#include <memory>
#include <vector>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::langutil;
@ -204,7 +205,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2)
{
std::vector<ASTPointer<Expression const>> arguments = _functionCall.arguments();
vector<ASTPointer<Expression const>> arguments = _functionCall.arguments();
if (arguments.size() != 2)
m_errorReporter.typeError(
5782_error,
@ -295,7 +296,7 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c
TypePointers TypeChecker::typeCheckMetaTypeFunctionAndRetrieveReturnType(FunctionCall const& _functionCall)
{
std::vector<ASTPointer<Expression const>> arguments = _functionCall.arguments();
vector<ASTPointer<Expression const>> arguments = _functionCall.arguments();
if (arguments.size() != 1)
m_errorReporter.fatalTypeError(
8885_error,
@ -441,7 +442,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
m_errorReporter.typeError(5587_error, _function.location(), "\"internal\" and \"private\" functions cannot be payable.");
}
std::vector<VariableDeclaration const*> internalParametersInConstructor;
vector<VariableDeclaration const*> internalParametersInConstructor;
auto checkArgumentAndReturnParameter = [&](VariableDeclaration const& _var) {
if (type(_var)->containsNestedMapping())
@ -471,7 +472,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (!iType)
{
std::string message = iType.message();
string message = iType.message();
solAssert(!message.empty(), "Expected detailed error message!");
if (_function.isConstructor())
message += " You can make the contract abstract to avoid this problem.";
@ -482,7 +483,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
!typeSupportedByOldABIEncoder(*type(_var), _function.libraryFunction())
)
{
std::string message =
string message =
"This type is only supported in ABI coder v2. "
"Use \"pragma abicoder v2;\" to enable the feature.";
if (_function.isConstructor())
@ -508,10 +509,10 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
var->accept(*this);
}
std::set<Declaration const*> modifiers;
set<Declaration const*> modifiers;
for (ASTPointer<ModifierInvocation> const& modifier: _function.modifiers())
{
std::vector<ContractDefinition const*> baseContracts;
vector<ContractDefinition const*> baseContracts;
if (auto contract = dynamic_cast<ContractDefinition const*>(_function.scope()))
{
baseContracts = contract->annotation().linearizedBaseContracts;
@ -521,7 +522,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
visitManually(
*modifier,
_function.isConstructor() ? baseContracts : std::vector<ContractDefinition const*>()
_function.isConstructor() ? baseContracts : vector<ContractDefinition const*>()
);
Declaration const* decl = &dereference(modifier->name());
if (modifiers.count(decl))
@ -641,7 +642,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
FunctionType getter(_variable);
if (!useABICoderV2())
{
std::vector<std::string> unsupportedTypes;
vector<string> unsupportedTypes;
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
if (!typeSupportedByOldABIEncoder(*param, false /* isLibrary */))
unsupportedTypes.emplace_back(param->humanReadableName());
@ -712,7 +713,7 @@ void TypeChecker::endVisit(StructDefinition const& _struct)
void TypeChecker::visitManually(
ModifierInvocation const& _modifier,
std::vector<ContractDefinition const*> const& _bases
vector<ContractDefinition const*> const& _bases
)
{
std::vector<ASTPointer<Expression>> const& arguments =
@ -723,8 +724,8 @@ void TypeChecker::visitManually(
_modifier.name().accept(*this);
auto const* declaration = &dereference(_modifier.name());
std::vector<ASTPointer<VariableDeclaration>> emptyParameterList;
std::vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
vector<ASTPointer<VariableDeclaration>> emptyParameterList;
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
if (auto modifierDecl = dynamic_cast<ModifierDefinition const*>(declaration))
{
parameters = &modifierDecl->parameters();
@ -919,8 +920,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (!identifierInfo.suffix.empty())
{
std::string const& suffix = identifierInfo.suffix;
solAssert((std::set<std::string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
string const& suffix = identifierInfo.suffix;
solAssert((set<string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
if (!var->isConstant() && (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage)))
{
if (suffix != "slot" && suffix != "offset")
@ -1041,7 +1042,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
return true;
};
solAssert(!_inlineAssembly.annotation().analysisInfo, "");
_inlineAssembly.annotation().analysisInfo = std::make_shared<yul::AsmAnalysisInfo>();
_inlineAssembly.annotation().analysisInfo = make_shared<yul::AsmAnalysisInfo>();
yul::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo,
m_errorReporter,
@ -1112,9 +1113,9 @@ void TypeChecker::endVisit(TryStatement const& _tryStatement)
2800_error,
successClause.location(),
"Function returns " +
std::to_string(functionType.returnParameterTypes().size()) +
to_string(functionType.returnParameterTypes().size()) +
" values, but returns clause has " +
std::to_string(parameters.size()) +
to_string(parameters.size()) +
" variables."
);
for (auto&& [parameter, returnType]: ranges::views::zip(parameters, returnTypes))
@ -1362,7 +1363,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
else
valueTypes = TypePointers{type(*_statement.initialValue())};
std::vector<ASTPointer<VariableDeclaration>> const& variables = _statement.declarations();
vector<ASTPointer<VariableDeclaration>> const& variables = _statement.declarations();
if (variables.empty())
// We already have an error for this in the SyntaxChecker.
solAssert(m_errorReporter.hasErrors(), "");
@ -1377,7 +1378,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
")."
);
for (size_t i = 0; i < std::min(variables.size(), valueTypes.size()); ++i)
for (size_t i = 0; i < min(variables.size(), valueTypes.size()); ++i)
{
if (!variables[i])
continue;
@ -1534,14 +1535,14 @@ void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const&
m_errorReporter.typeError(5547_error, _expression.location(), "Empty tuple on the left hand side.");
auto const* tupleType = dynamic_cast<TupleType const*>(&_type);
auto const& types = tupleType && tupleExpression->components().size() != 1 ? tupleType->components() : std::vector<Type const*> { &_type };
auto const& types = tupleType && tupleExpression->components().size() != 1 ? tupleType->components() : vector<Type const*> { &_type };
solAssert(
tupleExpression->components().size() == types.size() || m_errorReporter.hasErrors(),
"Array sizes don't match and no errors generated."
);
for (size_t i = 0; i < std::min(tupleExpression->components().size(), types.size()); i++)
for (size_t i = 0; i < min(tupleExpression->components().size(), types.size()); i++)
if (types[i])
{
solAssert(!!tupleExpression->components()[i], "");
@ -1606,7 +1607,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
7366_error,
_assignment.location(),
"Operator " +
std::string(TokenTraits::friendlyName(_assignment.assignmentOperator())) +
string(TokenTraits::friendlyName(_assignment.assignmentOperator())) +
" not compatible with types " +
t->humanReadableName() +
" and " +
@ -1620,7 +1621,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
bool TypeChecker::visit(TupleExpression const& _tuple)
{
_tuple.annotation().isConstant = false;
std::vector<ASTPointer<Expression>> const& components = _tuple.components();
vector<ASTPointer<Expression>> const& components = _tuple.components();
TypePointers types;
if (_tuple.annotation().willBeWrittenTo)
@ -1733,7 +1734,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
// Check if the operator is built-in or user-defined.
TypeResult builtinResult = operandType->unaryOperatorResult(op);
std::set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = operandType->operatorDefinitions(
set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = operandType->operatorDefinitions(
op,
*currentDefinitionScope(),
true // _unary
@ -1759,7 +1760,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
}
else
{
std::string description = fmt::format(
string description = fmt::format(
"Built-in unary operator {} cannot be applied to type {}.",
TokenTraits::friendlyName(op),
operandType->humanReadableName()
@ -1801,7 +1802,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
// Check if the operator is built-in or user-defined.
TypeResult builtinResult = leftType->binaryOperatorResult(_operation.getOperator(), rightType);
std::set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = leftType->operatorDefinitions(
set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = leftType->operatorDefinitions(
_operation.getOperator(),
*currentDefinitionScope(),
false // _unary
@ -1827,7 +1828,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
}
else
{
std::string description = fmt::format(
string description = fmt::format(
"Built-in binary operator {} cannot be applied to types {} and {}.",
TokenTraits::friendlyName(_operation.getOperator()),
leftType->humanReadableName(),
@ -1892,7 +1893,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
if (_operation.getOperator() == Token::Exp || _operation.getOperator() == Token::SHL)
{
std::string operation = _operation.getOperator() == Token::Exp ? "exponentiation" : "shift";
string operation = _operation.getOperator() == Token::Exp ? "exponentiation" : "shift";
if (
leftType->category() == Type::Category::RationalNumber &&
rightType->category() != Type::Category::RationalNumber
@ -1932,7 +1933,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
solAssert(*_functionCall.annotation().kind == FunctionCallKind::TypeConversion, "");
Type const* expressionType = type(_functionCall.expression());
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
bool const isPositionalCall = _functionCall.names().empty();
Type const* resultType = dynamic_cast<TypeType const&>(*expressionType).actualType();
@ -2214,7 +2215,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
}
// Check additional arguments for variadic functions
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
for (size_t i = 0; i < arguments.size(); ++i)
{
auto const& argType = type(*arguments[i]);
@ -2273,7 +2274,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCall)
{
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
// Expecting first argument to be the function pointer and second to be a tuple.
if (arguments.size() != 2)
@ -2310,7 +2311,7 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
externalFunctionType->kind() != FunctionType::Kind::Declaration
)
{
std::string msg = "Expected regular external function type, or external view on public function.";
string msg = "Expected regular external function type, or external view on public function.";
switch (externalFunctionType->kind())
{
@ -2359,7 +2360,7 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
}
solAssert(!externalFunctionType->takesArbitraryParameters(), "Function must have fixed parameters.");
// Tuples with only one component become that component
std::vector<ASTPointer<Expression const>> callArguments;
vector<ASTPointer<Expression const>> callArguments;
auto const* tupleType = dynamic_cast<TupleType const*>(type(*arguments[1]));
if (tupleType)
@ -2386,9 +2387,9 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
7788_error,
_functionCall.location(),
"Expected " +
std::to_string(externalFunctionType->parameterTypes().size()) +
to_string(externalFunctionType->parameterTypes().size()) +
" instead of " +
std::to_string(callArguments.size()) +
to_string(callArguments.size()) +
" components for the tuple parameter."
);
else
@ -2396,13 +2397,13 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
7515_error,
_functionCall.location(),
"Expected a tuple with " +
std::to_string(externalFunctionType->parameterTypes().size()) +
to_string(externalFunctionType->parameterTypes().size()) +
" components instead of a single non-tuple parameter."
);
}
// Use min() to check as much as we can before failing fatally
size_t const numParameters = std::min(callArguments.size(), externalFunctionType->parameterTypes().size());
size_t const numParameters = min(callArguments.size(), externalFunctionType->parameterTypes().size());
for (size_t i = 0; i < numParameters; i++)
{
@ -2413,7 +2414,7 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
5407_error,
callArguments[i]->location(),
"Cannot implicitly convert component at position " +
std::to_string(i) +
to_string(i) +
" from \"" +
argType.humanReadableName() +
"\" to \"" +
@ -2436,7 +2437,7 @@ void TypeChecker::typeCheckStringConcatFunction(
typeCheckFunctionGeneralChecks(_functionCall, _functionType);
for (std::shared_ptr<Expression const> const& argument: _functionCall.arguments())
for (shared_ptr<Expression const> const& argument: _functionCall.arguments())
{
Type const* argumentType = type(*argument);
bool notConvertibleToString = !argumentType->isImplicitlyConvertibleTo(*TypeProvider::stringMemory());
@ -2463,7 +2464,7 @@ void TypeChecker::typeCheckBytesConcatFunction(
typeCheckFunctionGeneralChecks(_functionCall, _functionType);
for (std::shared_ptr<Expression const> const& argument: _functionCall.arguments())
for (shared_ptr<Expression const> const& argument: _functionCall.arguments())
{
Type const* argumentType = type(*argument);
bool notConvertibleToBytes =
@ -2503,8 +2504,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
);
TypePointers const& parameterTypes = _functionType->parameterTypes();
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
std::vector<ASTPointer<ASTString>> const& argumentNames = _functionCall.names();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
vector<ASTPointer<ASTString>> const& argumentNames = _functionCall.names();
// Check number of passed in arguments
if (
@ -2515,22 +2516,22 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
bool const isStructConstructorCall =
functionCallKind == FunctionCallKind::StructConstructorCall;
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
std::string msg = isVariadic ?
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
string msg = isVariadic ?
"Need at least " +
toString(parameterTypes.size()) +
" arguments for " +
std::string(isStructConstructorCall ? "struct constructor" : "function call") +
string(isStructConstructorCall ? "struct constructor" : "function call") +
", but provided only " +
toString(arguments.size()) +
"."
:
"Wrong argument count for " +
std::string(isStructConstructorCall ? "struct constructor" : "function call") +
string(isStructConstructorCall ? "struct constructor" : "function call") +
": " +
toString(arguments.size()) +
" arguments given but " +
std::string(isVariadic ? "need at least " : "expected ") +
string(isVariadic ? "need at least " : "expected ") +
toString(parameterTypes.size()) +
".";
@ -2658,8 +2659,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
BoolResult result = type(*paramArgMap[i])->isImplicitlyConvertibleTo(*parameterTypes[i]);
if (!result)
{
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
std::string msg =
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
string msg =
"Invalid type for argument in function call. "
"Invalid implicit conversion from " +
type(*paramArgMap[i])->humanReadableName() +
@ -2750,7 +2751,7 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
bool TypeChecker::visit(FunctionCall const& _functionCall)
{
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
bool argumentsArePure = true;
// We need to check arguments' type first as they will be needed for overload resolution.
@ -2990,7 +2991,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
"{...}-option."
);
auto setCheckOption = [&](bool& _option, std::string const& _name)
auto setCheckOption = [&](bool& _option, string const& _name)
{
if (_option)
m_errorReporter.typeError(
@ -3004,7 +3005,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
for (size_t i = 0; i < _functionCallOptions.names().size(); ++i)
{
std::string const& name = *(_functionCallOptions.names()[i]);
string const& name = *(_functionCallOptions.names()[i]);
if (name == "salt")
{
if (kind == FunctionType::Kind::Creation)
@ -3184,8 +3185,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
);
}
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
std::string errorMsg = "Member \"" + memberName + "\" not found or not visible "
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
string errorMsg = "Member \"" + memberName + "\" not found or not visible "
"after argument-dependent lookup in " + exprType->humanReadableName() + ".";
if (auto const* funType = dynamic_cast<FunctionType const*>(exprType))
@ -3221,7 +3222,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
if (addressMember.name == memberName)
{
auto const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression());
std::string varName = var ? var->name() : "...";
string varName = var ? var->name() : "...";
errorMsg += " Use \"address(" + varName + ")." + memberName + "\" to access this address member.";
return { 3125_error, errorMsg };
}
@ -3605,13 +3606,13 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
return false;
}
std::vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
Identifier const& _identifier,
std::vector<Declaration const*> const& _candidates
vector<Declaration const*> const& _candidates
)
{
solAssert(_candidates.size() > 1, "");
std::vector<Declaration const*> uniqueDeclarations;
vector<Declaration const*> uniqueDeclarations;
for (Declaration const* declaration: _candidates)
{
@ -3664,7 +3665,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
else if (!annotation.arguments)
{
// The identifier should be a public state variable shadowing other functions
std::vector<Declaration const*> candidates;
vector<Declaration const*> candidates;
for (Declaration const* declaration: annotation.overloadedDeclarations)
{
@ -3680,7 +3681,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
}
else
{
std::vector<Declaration const*> candidates;
vector<Declaration const*> candidates;
for (Declaration const* declaration: annotation.overloadedDeclarations)
{
@ -3699,7 +3700,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
if (!declaration->location().isValid())
{
// Try to re-construct function definition
std::string description;
string description;
for (auto const& param: declaration->functionType(true)->parameterTypes())
description += (description.empty() ? "" : ", ") + param->humanReadableName();
description = "function " + _identifier.name() + "(" + description + ")";
@ -3815,12 +3816,12 @@ void TypeChecker::endVisit(Literal const& _literal)
// Assign type here if it even looks like an address. This prevents double errors for invalid addresses
_literal.annotation().type = TypeProvider::address();
std::string msg;
string msg;
if (_literal.valueWithoutUnderscores().length() != 42) // "0x" + 40 hex digits
// looksLikeAddress enforces that it is a hex literal starting with "0x"
msg =
"This looks like an address but is not exactly 40 hex digits. It is " +
std::to_string(_literal.valueWithoutUnderscores().length() - 2) +
to_string(_literal.valueWithoutUnderscores().length() - 2) +
" hex digits.";
else if (!_literal.passesAddressChecksum())
{
@ -4033,7 +4034,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
bool isBinaryOnlyOperator = (TokenTraits::isBinaryOp(operator_.value()) && !TokenTraits::isUnaryOp(operator_.value()));
bool firstParameterMatchesUsingFor = parameterCount == 0 || *usingForType == *parameterTypes.front();
std::optional<std::string> wrongParametersMessage;
optional<string> wrongParametersMessage;
if (isBinaryOnlyOperator && (parameterCount != 2 || !identicalFirstTwoParameters))
wrongParametersMessage = fmt::format("two parameters of type {} and the same data location", usingForType->canonicalName());
else if (isUnaryOnlyOperator && (parameterCount != 1 || !firstParameterMatchesUsingFor))
@ -4064,7 +4065,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
TypePointers const& returnParameterTypes = functionType->returnParameterTypes();
size_t const returnParameterCount = returnParameterTypes.size();
std::optional<std::string> wrongReturnParametersMessage;
optional<string> wrongReturnParametersMessage;
if (!TokenTraits::isCompareOp(operator_.value()) && operator_.value() != Token::Not)
{
if (returnParameterCount != 1 || *usingForType != *returnParameterTypes.front())
@ -4099,7 +4100,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
{
// TODO: This is pretty inefficient. For every operator binding we find, we're
// traversing all bindings in all `using for` directives in the current scope.
std::set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = usingForType->operatorDefinitions(
set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = usingForType->operatorDefinitions(
operator_.value(),
*currentDefinitionScope(),
parameterCount == 1 // _unary
@ -4132,7 +4133,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
void TypeChecker::checkErrorAndEventParameters(CallableDeclaration const& _callable)
{
std::string kind = dynamic_cast<EventDefinition const*>(&_callable) ? "event" : "error";
string kind = dynamic_cast<EventDefinition const*>(&_callable) ? "event" : "error";
for (ASTPointer<VariableDeclaration> const& var: _callable.parameters())
{
if (type(*var)->containsNestedMapping())
@ -4222,7 +4223,7 @@ void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAss
if (*_expression.annotation().isLValue)
return;
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
if (*_expression.annotation().isConstant)
return { 6520_error, "Cannot assign to a constant variable." };

View File

@ -27,6 +27,7 @@
#include <utility>
#include <variant>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -311,13 +312,13 @@ ViewPureChecker::MutabilityAndLocation const& ViewPureChecker::modifierMutabilit
{
MutabilityAndLocation bestMutabilityAndLocation{};
FunctionDefinition const* currentFunction = nullptr;
std::swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
std::swap(currentFunction, m_currentFunction);
swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
swap(currentFunction, m_currentFunction);
_modifier.accept(*this);
std::swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
std::swap(currentFunction, m_currentFunction);
swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
swap(currentFunction, m_currentFunction);
}
return m_inferredMutability.at(&_modifier);
}
@ -383,8 +384,8 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
break;
case Type::Category::Magic:
{
using MagicMember = std::pair<MagicType::Kind, std::string>;
std::set<MagicMember> static const pureMembers{
using MagicMember = pair<MagicType::Kind, string>;
set<MagicMember> static const pureMembers{
{MagicType::Kind::ABI, "decode"},
{MagicType::Kind::ABI, "encode"},
{MagicType::Kind::ABI, "encodePacked"},
@ -400,7 +401,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
{MagicType::Kind::MetaType, "min"},
{MagicType::Kind::MetaType, "max"},
};
std::set<MagicMember> static const payableMembers{
set<MagicMember> static const payableMembers{
{MagicType::Kind::Message, "value"}
};

View File

@ -39,12 +39,13 @@
#include <functional>
#include <utility>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
namespace
{
TryCatchClause const* findClause(std::vector<ASTPointer<TryCatchClause>> const& _clauses, std::optional<std::string> _errorName = {})
TryCatchClause const* findClause(vector<ASTPointer<TryCatchClause>> const& _clauses, optional<string> _errorName = {})
{
for (auto const& clause: ranges::views::tail(_clauses))
if (_errorName.has_value() ? clause->errorName() == _errorName : clause->errorName().empty())
@ -118,7 +119,7 @@ FunctionDefinition const* ASTNode::resolveFunctionCall(FunctionCall const& _func
ASTAnnotation& ASTNode::annotation() const
{
if (!m_annotation)
m_annotation = std::make_unique<ASTAnnotation>();
m_annotation = make_unique<ASTAnnotation>();
return *m_annotation;
}
@ -127,9 +128,9 @@ SourceUnitAnnotation& SourceUnit::annotation() const
return initAnnotation<SourceUnitAnnotation>();
}
std::set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, std::set<SourceUnit const*> _skipList) const
set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, set<SourceUnit const*> _skipList) const
{
std::set<SourceUnit const*> sourceUnits;
set<SourceUnit const*> sourceUnits;
for (ImportDirective const* importDirective: filteredNodes<ImportDirective>(nodes()))
{
auto const& sourceUnit = importDirective->annotation().sourceUnit;
@ -160,11 +161,11 @@ bool ContractDefinition::derivesFrom(ContractDefinition const& _base) const
return util::contains(annotation().linearizedBaseContracts, &_base);
}
std::map<util::FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions(bool _includeInheritedFunctions) const
map<util::FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions(bool _includeInheritedFunctions) const
{
auto exportedFunctionList = interfaceFunctionList(_includeInheritedFunctions);
std::map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions;
map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions;
for (auto const& it: exportedFunctionList)
exportedFunctions.insert(it);
@ -207,11 +208,11 @@ FunctionDefinition const* ContractDefinition::receiveFunction() const
return nullptr;
}
std::vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
{
return m_interfaceEvents.init([&]{
std::set<std::string> eventsSeen;
std::vector<EventDefinition const*> interfaceEvents;
set<string> eventsSeen;
vector<EventDefinition const*> interfaceEvents;
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
for (EventDefinition const* e: contract->events())
@ -221,7 +222,7 @@ std::vector<EventDefinition const*> const& ContractDefinition::definedInterfaceE
/// and not to function encoding (jump vs. call)
FunctionType const* functionType = e->functionType(true);
solAssert(functionType, "");
std::string eventSignature = functionType->externalSignature();
string eventSignature = functionType->externalSignature();
if (eventsSeen.count(eventSignature) == 0)
{
eventsSeen.insert(eventSignature);
@ -232,7 +233,7 @@ std::vector<EventDefinition const*> const& ContractDefinition::definedInterfaceE
});
}
std::vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvents() const
vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvents() const
{
solAssert(annotation().creationCallGraph.set(), "");
@ -242,9 +243,9 @@ std::vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvent
);
}
std::vector<EventDefinition const*> ContractDefinition::interfaceEvents(bool _requireCallGraph) const
vector<EventDefinition const*> ContractDefinition::interfaceEvents(bool _requireCallGraph) const
{
std::set<EventDefinition const*, CompareByID> result;
set<EventDefinition const*, CompareByID> result;
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
result += contract->events();
solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set());
@ -254,12 +255,12 @@ std::vector<EventDefinition const*> ContractDefinition::interfaceEvents(bool _re
result += usedInterfaceEvents();
// We could filter out all events that do not have an external interface
// if _requireCallGraph is false.
return util::convertContainer<std::vector<EventDefinition const*>>(std::move(result));
return util::convertContainer<vector<EventDefinition const*>>(std::move(result));
}
std::vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
{
std::set<ErrorDefinition const*, CompareByID> result;
set<ErrorDefinition const*, CompareByID> result;
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
result += filteredNodes<ErrorDefinition>(contract->m_subNodes);
solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set(), "");
@ -269,20 +270,20 @@ std::vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _re
result +=
(*annotation().creationCallGraph)->usedErrors +
(*annotation().deployedCallGraph)->usedErrors;
return util::convertContainer<std::vector<ErrorDefinition const*>>(std::move(result));
return util::convertContainer<vector<ErrorDefinition const*>>(std::move(result));
}
std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList(bool _includeInheritedFunctions) const
vector<pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList(bool _includeInheritedFunctions) const
{
return m_interfaceFunctionList[_includeInheritedFunctions].init([&]{
std::set<std::string> signaturesSeen;
std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList;
set<string> signaturesSeen;
vector<pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList;
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
{
if (_includeInheritedFunctions == false && contract != this)
continue;
std::vector<FunctionTypePointer> functions;
vector<FunctionTypePointer> functions;
for (FunctionDefinition const* f: contract->definedFunctions())
if (f->isPartOfExternalInterface())
functions.push_back(TypeProvider::function(*f, FunctionType::Kind::External));
@ -294,7 +295,7 @@ std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractD
if (!fun->interfaceFunctionType())
// Fails hopefully because we already registered the error
continue;
std::string functionSignature = fun->externalSignature();
string functionSignature = fun->externalSignature();
if (signaturesSeen.count(functionSignature) == 0)
{
signaturesSeen.insert(functionSignature);
@ -356,7 +357,7 @@ FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition
return nullptr;
}
std::multimap<std::string, FunctionDefinition const*> const& ContractDefinition::definedFunctionsByName() const
multimap<std::string, FunctionDefinition const*> const& ContractDefinition::definedFunctionsByName() const
{
return m_definedFunctionsByName.init([&]{
std::multimap<std::string, FunctionDefinition const*> result;
@ -385,7 +386,7 @@ TypeDeclarationAnnotation& UserDefinedValueTypeDefinition::annotation() const
std::vector<std::pair<ASTPointer<IdentifierPath>, std::optional<Token>>> UsingForDirective::functionsAndOperators() const
{
return ranges::zip_view(m_functionsOrLibrary, m_operators) | ranges::to<std::vector>;
return ranges::zip_view(m_functionsOrLibrary, m_operators) | ranges::to<vector>;
}
Type const* StructDefinition::type() const
@ -483,12 +484,12 @@ Type const* FunctionDefinition::typeViaContractName() const
return TypeProvider::function(*this, FunctionType::Kind::Declaration);
}
std::string FunctionDefinition::externalSignature() const
string FunctionDefinition::externalSignature() const
{
return TypeProvider::function(*this)->externalSignature();
}
std::string FunctionDefinition::externalIdentifierHex() const
string FunctionDefinition::externalIdentifierHex() const
{
return TypeProvider::function(*this)->externalIdentifierHex();
}
@ -638,7 +639,7 @@ CallableDeclaration const* Scopable::functionOrModifierDefinition() const
return nullptr;
}
std::string Scopable::sourceUnitName() const
string Scopable::sourceUnitName() const
{
return *sourceUnit().annotation().path;
}
@ -700,7 +701,7 @@ bool VariableDeclaration::isCallableOrCatchParameter() const
if (isReturnParameter() || isTryCatchParameter())
return true;
std::vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
parameters = &funTypeName->parameterTypes();
@ -721,7 +722,7 @@ bool VariableDeclaration::isLocalOrReturn() const
bool VariableDeclaration::isReturnParameter() const
{
std::vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr;
vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr;
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
returnParameters = &funTypeName->returnParameterTypes();
@ -812,15 +813,15 @@ bool VariableDeclaration::isFileLevelVariable() const
return dynamic_cast<SourceUnit const*>(scope());
}
std::set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
{
using Location = VariableDeclaration::Location;
if (!hasReferenceOrMappingType() || isStateVariable() || isEventOrErrorParameter())
return std::set<Location>{ Location::Unspecified };
return set<Location>{ Location::Unspecified };
else if (isCallableOrCatchParameter())
{
std::set<Location> locations{ Location::Memory };
set<Location> locations{ Location::Memory };
if (
isConstructorParameter() ||
isInternalCallableParameter() ||
@ -834,13 +835,13 @@ std::set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocation
}
else if (isLocalVariable())
// Further restrictions will be imposed later on.
return std::set<Location>{ Location::Memory, Location::Storage, Location::CallData };
return set<Location>{ Location::Memory, Location::Storage, Location::CallData };
else
// Struct members etc.
return std::set<Location>{ Location::Unspecified };
return set<Location>{ Location::Unspecified };
}
std::string VariableDeclaration::externalIdentifierHex() const
string VariableDeclaration::externalIdentifierHex() const
{
solAssert(isStateVariable() && isPublic(), "Can only be called for public state variables");
return TypeProvider::function(*this)->externalIdentifierHex();
@ -957,7 +958,7 @@ FunctionCallAnnotation& FunctionCall::annotation() const
return initAnnotation<FunctionCallAnnotation>();
}
std::vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
{
// normal arguments
if (m_names.empty())
@ -974,7 +975,7 @@ std::vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
else
functionType = dynamic_cast<FunctionType const*>(m_expression->annotation().type);
std::vector<ASTPointer<Expression const>> sorted;
vector<ASTPointer<Expression const>> sorted;
for (auto const& parameterName: functionType->parameterNames())
{
bool found = false;
@ -1029,13 +1030,13 @@ bool Literal::passesAddressChecksum() const
return util::passesAddressChecksum(valueWithoutUnderscores(), true);
}
std::string Literal::getChecksummedAddress() const
string Literal::getChecksummedAddress() const
{
solAssert(isHexNumber(), "Expected hex number");
/// Pad literal to be a proper hex address.
std::string address = valueWithoutUnderscores().substr(2);
string address = valueWithoutUnderscores().substr(2);
if (address.length() > 40)
return std::string();
return string();
address.insert(address.begin(), 40 - address.size(), '0');
return util::getChecksummedAddress(address);
}

View File

@ -87,20 +87,16 @@ public:
static void listAccept(std::vector<T> const& _list, ASTVisitor& _visitor)
{
for (T const& element: _list)
{
solAssert(element);
if (element)
element->accept(_visitor);
}
}
template <class T>
static void listAccept(std::vector<T> const& _list, ASTConstVisitor& _visitor)
{
for (T const& element: _list)
{
solAssert(element);
if (element)
element->accept(_visitor);
}
}
/// @returns a copy of the vector containing only the nodes which derive from T.
template <class T>

View File

@ -23,6 +23,7 @@
#include <libsolidity/ast/ASTAnnotations.h>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;

View File

@ -44,6 +44,7 @@
#include <type_traits>
#include <range/v3/view/map.hpp>
using namespace std;
using namespace std::string_literals;
using namespace solidity::langutil;
@ -51,14 +52,14 @@ namespace
{
template<typename V, template<typename> typename C>
void addIfSet(std::vector<std::pair<std::string, Json::Value>>& _attributes, std::string const& _name, C<V> const& _value)
void addIfSet(std::vector<pair<string, Json::Value>>& _attributes, string const& _name, C<V> const& _value)
{
if constexpr (std::is_same_v<C<V>, solidity::util::SetOnce<V>>)
{
if (!_value.set())
return;
}
else if constexpr (std::is_same_v<C<V>, std::optional<V>>)
else if constexpr (std::is_same_v<C<V>, optional<V>>)
{
if (!_value.has_value())
return;
@ -72,7 +73,7 @@ void addIfSet(std::vector<std::pair<std::string, Json::Value>>& _attributes, std
namespace solidity::frontend
{
ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, std::map<std::string, unsigned> _sourceIndices):
ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, map<string, unsigned> _sourceIndices):
m_stackState(_stackState),
m_sourceIndices(std::move(_sourceIndices))
{
@ -81,21 +82,21 @@ ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, std::map<std:
void ASTJsonExporter::setJsonNode(
ASTNode const& _node,
std::string const& _nodeName,
std::initializer_list<std::pair<std::string, Json::Value>>&& _attributes
string const& _nodeName,
initializer_list<pair<string, Json::Value>>&& _attributes
)
{
ASTJsonExporter::setJsonNode(
_node,
_nodeName,
std::vector<std::pair<std::string, Json::Value>>(std::move(_attributes))
std::vector<pair<string, Json::Value>>(std::move(_attributes))
);
}
void ASTJsonExporter::setJsonNode(
ASTNode const& _node,
std::string const& _nodeType,
std::vector<std::pair<std::string, Json::Value>>&& _attributes
string const& _nodeType,
std::vector<pair<string, Json::Value>>&& _attributes
)
{
m_currentValue = Json::objectValue;
@ -109,24 +110,24 @@ void ASTJsonExporter::setJsonNode(
m_currentValue[e.first] = std::move(e.second);
}
std::optional<size_t> ASTJsonExporter::sourceIndexFromLocation(SourceLocation const& _location) const
optional<size_t> ASTJsonExporter::sourceIndexFromLocation(SourceLocation const& _location) const
{
if (_location.sourceName && m_sourceIndices.count(*_location.sourceName))
return m_sourceIndices.at(*_location.sourceName);
else
return std::nullopt;
return nullopt;
}
std::string ASTJsonExporter::sourceLocationToString(SourceLocation const& _location) const
string ASTJsonExporter::sourceLocationToString(SourceLocation const& _location) const
{
std::optional<size_t> sourceIndexOpt = sourceIndexFromLocation(_location);
optional<size_t> sourceIndexOpt = sourceIndexFromLocation(_location);
int length = -1;
if (_location.start >= 0 && _location.end >= 0)
length = _location.end - _location.start;
return std::to_string(_location.start) + ":" + std::to_string(length) + ":" + (sourceIndexOpt.has_value() ? std::to_string(sourceIndexOpt.value()) : "-1");
return to_string(_location.start) + ":" + to_string(length) + ":" + (sourceIndexOpt.has_value() ? to_string(sourceIndexOpt.value()) : "-1");
}
Json::Value ASTJsonExporter::sourceLocationsToJson(std::vector<SourceLocation> const& _sourceLocations) const
Json::Value ASTJsonExporter::sourceLocationsToJson(vector<SourceLocation> const& _sourceLocations) const
{
Json::Value locations = Json::arrayValue;
@ -136,7 +137,7 @@ Json::Value ASTJsonExporter::sourceLocationsToJson(std::vector<SourceLocation> c
return locations;
}
std::string ASTJsonExporter::namePathToString(std::vector<ASTString> const& _namePath)
string ASTJsonExporter::namePathToString(std::vector<ASTString> const& _namePath)
{
return boost::algorithm::join(_namePath, "."s);
}
@ -163,13 +164,13 @@ Json::Value ASTJsonExporter::typePointerToJson(std::optional<FuncCallArguments>
}
void ASTJsonExporter::appendExpressionAttributes(
std::vector<std::pair<std::string, Json::Value>>& _attributes,
std::vector<pair<string, Json::Value>>& _attributes,
ExpressionAnnotation const& _annotation
)
{
std::vector<std::pair<std::string, Json::Value>> exprAttributes = {
std::make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
std::make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
std::vector<pair<string, Json::Value>> exprAttributes = {
make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
};
addIfSet(exprAttributes, "isLValue", _annotation.isLValue);
@ -182,7 +183,7 @@ void ASTJsonExporter::appendExpressionAttributes(
_attributes += exprAttributes;
}
Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(pair<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
{
Json::Value tuple(Json::objectValue);
tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first));
@ -198,7 +199,7 @@ Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair<yul::Ident
return tuple;
}
void ASTJsonExporter::print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format)
void ASTJsonExporter::print(ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format)
{
_stream << util::jsonPrint(toJson(_node), _format);
}
@ -211,9 +212,9 @@ Json::Value ASTJsonExporter::toJson(ASTNode const& _node)
bool ASTJsonExporter::visit(SourceUnit const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
std::make_pair("nodes", toJson(_node.nodes())),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
make_pair("nodes", toJson(_node.nodes())),
};
if (_node.experimentalSolidity())
@ -245,17 +246,17 @@ bool ASTJsonExporter::visit(PragmaDirective const& _node)
for (auto const& literal: _node.literals())
literals.append(literal);
setJsonNode(_node, "PragmaDirective", {
std::make_pair("literals", std::move(literals))
make_pair("literals", std::move(literals))
});
return false;
}
bool ASTJsonExporter::visit(ImportDirective const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("file", _node.path()),
std::make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
std::make_pair("scope", idOrNull(_node.scope()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("file", _node.path()),
make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
make_pair("scope", idOrNull(_node.scope()))
};
addIfSet(attributes, "absolutePath", _node.annotation().absolutePath);
@ -280,19 +281,19 @@ bool ASTJsonExporter::visit(ImportDirective const& _node)
bool ASTJsonExporter::visit(ContractDefinition const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("contractKind", contractKind(_node.contractKind())),
std::make_pair("abstract", _node.abstract()),
std::make_pair("baseContracts", toJson(_node.baseContracts())),
std::make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies | ranges::views::keys)),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("contractKind", contractKind(_node.contractKind())),
make_pair("abstract", _node.abstract()),
make_pair("baseContracts", toJson(_node.baseContracts())),
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies | ranges::views::keys)),
// Do not require call graph because the AST is also created for incorrect sources.
std::make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))),
std::make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))),
std::make_pair("nodes", toJson(_node.subNodes())),
std::make_pair("scope", idOrNull(_node.scope()))
make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))),
make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))),
make_pair("nodes", toJson(_node.subNodes())),
make_pair("scope", idOrNull(_node.scope()))
};
addIfSet(attributes, "canonicalName", _node.annotation().canonicalName);
@ -305,7 +306,7 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node)
{
Json::Value internalFunctionIDs(Json::objectValue);
for (auto const& [functionDefinition, internalFunctionID]: _node.annotation().internalFunctionIDs)
internalFunctionIDs[std::to_string(functionDefinition->id())] = internalFunctionID;
internalFunctionIDs[to_string(functionDefinition->id())] = internalFunctionID;
attributes.emplace_back("internalFunctionIDs", std::move(internalFunctionIDs));
}
@ -321,9 +322,9 @@ bool ASTJsonExporter::visit(IdentifierPath const& _node)
nameLocations.append(sourceLocationToString(location));
setJsonNode(_node, "IdentifierPath", {
std::make_pair("name", namePathToString(_node.path())),
std::make_pair("nameLocations", nameLocations),
std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration))
make_pair("name", namePathToString(_node.path())),
make_pair("nameLocations", nameLocations),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration))
});
return false;
}
@ -331,16 +332,16 @@ bool ASTJsonExporter::visit(IdentifierPath const& _node)
bool ASTJsonExporter::visit(InheritanceSpecifier const& _node)
{
setJsonNode(_node, "InheritanceSpecifier", {
std::make_pair("baseName", toJson(_node.name())),
std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
make_pair("baseName", toJson(_node.name())),
make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
});
return false;
}
bool ASTJsonExporter::visit(UsingForDirective const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue)
vector<pair<string, Json::Value>> attributes = {
make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue)
};
if (_node.usesBraces())
@ -354,7 +355,7 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node)
else
{
functionNode["definition"] = toJson(*function);
functionNode["operator"] = std::string(TokenTraits::toString(*op));
functionNode["operator"] = string(TokenTraits::toString(*op));
}
functionList.append(std::move(functionNode));
}
@ -376,13 +377,13 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node)
bool ASTJsonExporter::visit(StructDefinition const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
std::make_pair("members", toJson(_node.members())),
std::make_pair("scope", idOrNull(_node.scope()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("members", toJson(_node.members())),
make_pair("scope", idOrNull(_node.scope()))
};
addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
@ -394,11 +395,11 @@ bool ASTJsonExporter::visit(StructDefinition const& _node)
bool ASTJsonExporter::visit(EnumDefinition const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("members", toJson(_node.members()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("members", toJson(_node.members()))
};
addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
@ -411,8 +412,8 @@ bool ASTJsonExporter::visit(EnumDefinition const& _node)
bool ASTJsonExporter::visit(EnumValue const& _node)
{
setJsonNode(_node, "EnumValue", {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
});
return false;
}
@ -420,10 +421,10 @@ bool ASTJsonExporter::visit(EnumValue const& _node)
bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node)
{
solAssert(_node.underlyingType(), "");
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("underlyingType", toJson(*_node.underlyingType()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("underlyingType", toJson(*_node.underlyingType()))
};
addIfSet(attributes, "canonicalName", _node.annotation().canonicalName);
@ -435,7 +436,7 @@ bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node)
bool ASTJsonExporter::visit(ParameterList const& _node)
{
setJsonNode(_node, "ParameterList", {
std::make_pair("parameters", toJson(_node.parameters()))
make_pair("parameters", toJson(_node.parameters()))
});
return false;
}
@ -443,30 +444,30 @@ bool ASTJsonExporter::visit(ParameterList const& _node)
bool ASTJsonExporter::visit(OverrideSpecifier const& _node)
{
setJsonNode(_node, "OverrideSpecifier", {
std::make_pair("overrides", toJson(_node.overrides()))
make_pair("overrides", toJson(_node.overrides()))
});
return false;
}
bool ASTJsonExporter::visit(FunctionDefinition const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())),
std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
std::make_pair("virtual", _node.markedVirtual()),
std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
std::make_pair("parameters", toJson(_node.parameterList())),
std::make_pair("returnParameters", toJson(*_node.returnParameterList())),
std::make_pair("modifiers", toJson(_node.modifiers())),
std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue),
std::make_pair("implemented", _node.isImplemented()),
std::make_pair("scope", idOrNull(_node.scope()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())),
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
make_pair("virtual", _node.markedVirtual()),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
make_pair("parameters", toJson(_node.parameterList())),
make_pair("returnParameters", toJson(*_node.returnParameterList())),
make_pair("modifiers", toJson(_node.modifiers())),
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue),
make_pair("implemented", _node.isImplemented()),
make_pair("scope", idOrNull(_node.scope()))
};
std::optional<Visibility> visibility;
optional<Visibility> visibility;
if (_node.isConstructor())
{
if (_node.annotation().contract)
@ -481,7 +482,7 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node)
if (_node.isPartOfExternalInterface() && m_stackState > CompilerStack::State::ParsedAndImported)
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
if (!_node.annotation().baseFunctions.empty())
attributes.emplace_back(std::make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
setJsonNode(_node, "FunctionDefinition", std::move(attributes));
return false;
@ -489,19 +490,19 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node)
bool ASTJsonExporter::visit(VariableDeclaration const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("typeName", toJson(_node.typeName())),
std::make_pair("constant", _node.isConstant()),
std::make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
std::make_pair("stateVariable", _node.isStateVariable()),
std::make_pair("storageLocation", location(_node.referenceLocation())),
std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue),
std::make_pair("scope", idOrNull(_node.scope())),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("typeName", toJson(_node.typeName())),
make_pair("constant", _node.isConstant()),
make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
make_pair("stateVariable", _node.isStateVariable()),
make_pair("storageLocation", location(_node.referenceLocation())),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue),
make_pair("scope", idOrNull(_node.scope())),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
};
if (_node.isStateVariable() && _node.isPublic())
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
@ -510,34 +511,34 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node)
if (m_inEvent)
attributes.emplace_back("indexed", _node.isIndexed());
if (!_node.annotation().baseFunctions.empty())
attributes.emplace_back(std::make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
setJsonNode(_node, "VariableDeclaration", std::move(attributes));
return false;
}
bool ASTJsonExporter::visit(ModifierDefinition const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
std::make_pair("parameters", toJson(_node.parameterList())),
std::make_pair("virtual", _node.markedVirtual()),
std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue)
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("parameters", toJson(_node.parameterList())),
make_pair("virtual", _node.markedVirtual()),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue)
};
if (!_node.annotation().baseFunctions.empty())
attributes.emplace_back(std::make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true)));
attributes.emplace_back(make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true)));
setJsonNode(_node, "ModifierDefinition", std::move(attributes));
return false;
}
bool ASTJsonExporter::visit(ModifierInvocation const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes{
std::make_pair("modifierName", toJson(_node.name())),
std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
std::vector<pair<string, Json::Value>> attributes{
make_pair("modifierName", toJson(_node.name())),
make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
};
if (Declaration const* declaration = _node.name().annotation().referencedDeclaration)
{
@ -553,16 +554,16 @@ bool ASTJsonExporter::visit(ModifierInvocation const& _node)
bool ASTJsonExporter::visit(EventDefinition const& _node)
{
m_inEvent = true;
std::vector<std::pair<std::string, Json::Value>> _attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("parameters", toJson(_node.parameterList())),
std::make_pair("anonymous", _node.isAnonymous())
std::vector<pair<string, Json::Value>> _attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("parameters", toJson(_node.parameterList())),
make_pair("anonymous", _node.isAnonymous())
};
if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
if (m_stackState >= CompilerStack::State::AnalysisPerformed)
_attributes.emplace_back(
std::make_pair(
make_pair(
"eventSelector",
toHex(u256(util::h256::Arith(util::keccak256(_node.functionType(true)->externalSignature()))))
));
@ -573,14 +574,14 @@ bool ASTJsonExporter::visit(EventDefinition const& _node)
bool ASTJsonExporter::visit(ErrorDefinition const& _node)
{
std::vector<std::pair<std::string, Json::Value>> _attributes = {
std::make_pair("name", _node.name()),
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
std::make_pair("parameters", toJson(_node.parameterList()))
std::vector<pair<string, Json::Value>> _attributes = {
make_pair("name", _node.name()),
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
make_pair("parameters", toJson(_node.parameterList()))
};
if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
_attributes.emplace_back(std::make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
if (m_stackState >= CompilerStack::State::AnalysisPerformed)
_attributes.emplace_back(make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
setJsonNode(_node, "ErrorDefinition", std::move(_attributes));
return false;
@ -588,13 +589,13 @@ bool ASTJsonExporter::visit(ErrorDefinition const& _node)
bool ASTJsonExporter::visit(ElementaryTypeName const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("name", _node.typeName().toString()),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.typeName().toString()),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
};
if (_node.stateMutability())
attributes.emplace_back(std::make_pair("stateMutability", stateMutabilityToString(*_node.stateMutability())));
attributes.emplace_back(make_pair("stateMutability", stateMutabilityToString(*_node.stateMutability())));
setJsonNode(_node, "ElementaryTypeName", std::move(attributes));
return false;
@ -603,9 +604,9 @@ bool ASTJsonExporter::visit(ElementaryTypeName const& _node)
bool ASTJsonExporter::visit(UserDefinedTypeName const& _node)
{
setJsonNode(_node, "UserDefinedTypeName", {
std::make_pair("pathNode", toJson(_node.pathNode())),
std::make_pair("referencedDeclaration", idOrNull(_node.pathNode().annotation().referencedDeclaration)),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
make_pair("pathNode", toJson(_node.pathNode())),
make_pair("referencedDeclaration", idOrNull(_node.pathNode().annotation().referencedDeclaration)),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
});
return false;
}
@ -613,11 +614,11 @@ bool ASTJsonExporter::visit(UserDefinedTypeName const& _node)
bool ASTJsonExporter::visit(FunctionTypeName const& _node)
{
setJsonNode(_node, "FunctionTypeName", {
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
std::make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
std::make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
});
return false;
}
@ -625,13 +626,13 @@ bool ASTJsonExporter::visit(FunctionTypeName const& _node)
bool ASTJsonExporter::visit(Mapping const& _node)
{
setJsonNode(_node, "Mapping", {
std::make_pair("keyType", toJson(_node.keyType())),
std::make_pair("keyName", _node.keyName()),
std::make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())),
std::make_pair("valueType", toJson(_node.valueType())),
std::make_pair("valueName", _node.valueName()),
std::make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
make_pair("keyType", toJson(_node.keyType())),
make_pair("keyName", _node.keyName()),
make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())),
make_pair("valueType", toJson(_node.valueType())),
make_pair("valueName", _node.valueName()),
make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
});
return false;
}
@ -639,20 +640,20 @@ bool ASTJsonExporter::visit(Mapping const& _node)
bool ASTJsonExporter::visit(ArrayTypeName const& _node)
{
setJsonNode(_node, "ArrayTypeName", {
std::make_pair("baseType", toJson(_node.baseType())),
std::make_pair("length", toJsonOrNull(_node.length())),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
make_pair("baseType", toJson(_node.baseType())),
make_pair("length", toJsonOrNull(_node.length())),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
});
return false;
}
bool ASTJsonExporter::visit(InlineAssembly const& _node)
{
std::vector<std::pair<std::string, Json::Value>> externalReferences;
vector<pair<string, Json::Value>> externalReferences;
for (auto const& it: _node.annotation().externalReferences)
if (it.first)
externalReferences.emplace_back(std::make_pair(
externalReferences.emplace_back(make_pair(
it.first->name.str(),
inlineAssemblyIdentifierToJson(it)
));
@ -663,10 +664,10 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
for (Json::Value& it: externalReferences | ranges::views::values)
externalReferencesJson.append(std::move(it));
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
std::make_pair("externalReferences", std::move(externalReferencesJson)),
std::make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
std::vector<pair<string, Json::Value>> attributes = {
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
make_pair("externalReferences", std::move(externalReferencesJson)),
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
};
if (_node.flags())
@ -677,7 +678,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
flags.append(*flag);
else
flags.append(Json::nullValue);
attributes.emplace_back(std::make_pair("flags", std::move(flags)));
attributes.emplace_back(make_pair("flags", std::move(flags)));
}
setJsonNode(_node, "InlineAssembly", std::move(attributes));
@ -687,7 +688,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
bool ASTJsonExporter::visit(Block const& _node)
{
setJsonNode(_node, _node.unchecked() ? "UncheckedBlock" : "Block", {
std::make_pair("statements", toJson(_node.statements()))
make_pair("statements", toJson(_node.statements()))
});
return false;
}
@ -701,9 +702,9 @@ bool ASTJsonExporter::visit(PlaceholderStatement const& _node)
bool ASTJsonExporter::visit(IfStatement const& _node)
{
setJsonNode(_node, "IfStatement", {
std::make_pair("condition", toJson(_node.condition())),
std::make_pair("trueBody", toJson(_node.trueStatement())),
std::make_pair("falseBody", toJsonOrNull(_node.falseStatement()))
make_pair("condition", toJson(_node.condition())),
make_pair("trueBody", toJson(_node.trueStatement())),
make_pair("falseBody", toJsonOrNull(_node.falseStatement()))
});
return false;
}
@ -711,9 +712,9 @@ bool ASTJsonExporter::visit(IfStatement const& _node)
bool ASTJsonExporter::visit(TryCatchClause const& _node)
{
setJsonNode(_node, "TryCatchClause", {
std::make_pair("errorName", _node.errorName()),
std::make_pair("parameters", toJsonOrNull(_node.parameters())),
std::make_pair("block", toJson(_node.block()))
make_pair("errorName", _node.errorName()),
make_pair("parameters", toJsonOrNull(_node.parameters())),
make_pair("block", toJson(_node.block()))
});
return false;
}
@ -721,8 +722,8 @@ bool ASTJsonExporter::visit(TryCatchClause const& _node)
bool ASTJsonExporter::visit(TryStatement const& _node)
{
setJsonNode(_node, "TryStatement", {
std::make_pair("externalCall", toJson(_node.externalCall())),
std::make_pair("clauses", toJson(_node.clauses()))
make_pair("externalCall", toJson(_node.externalCall())),
make_pair("clauses", toJson(_node.clauses()))
});
return false;
}
@ -733,8 +734,8 @@ bool ASTJsonExporter::visit(WhileStatement const& _node)
_node,
_node.isDoWhile() ? "DoWhileStatement" : "WhileStatement",
{
std::make_pair("condition", toJson(_node.condition())),
std::make_pair("body", toJson(_node.body()))
make_pair("condition", toJson(_node.condition())),
make_pair("body", toJson(_node.body()))
}
);
return false;
@ -743,10 +744,10 @@ bool ASTJsonExporter::visit(WhileStatement const& _node)
bool ASTJsonExporter::visit(ForStatement const& _node)
{
setJsonNode(_node, "ForStatement", {
std::make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())),
std::make_pair("condition", toJsonOrNull(_node.condition())),
std::make_pair("loopExpression", toJsonOrNull(_node.loopExpression())),
std::make_pair("body", toJson(_node.body()))
make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())),
make_pair("condition", toJsonOrNull(_node.condition())),
make_pair("loopExpression", toJsonOrNull(_node.loopExpression())),
make_pair("body", toJson(_node.body()))
});
return false;
}
@ -766,8 +767,8 @@ bool ASTJsonExporter::visit(Break const& _node)
bool ASTJsonExporter::visit(Return const& _node)
{
setJsonNode(_node, "Return", {
std::make_pair("expression", toJsonOrNull(_node.expression())),
std::make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters))
make_pair("expression", toJsonOrNull(_node.expression())),
make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters))
});
return false;
}
@ -781,7 +782,7 @@ bool ASTJsonExporter::visit(Throw const& _node)
bool ASTJsonExporter::visit(EmitStatement const& _node)
{
setJsonNode(_node, "EmitStatement", {
std::make_pair("eventCall", toJson(_node.eventCall()))
make_pair("eventCall", toJson(_node.eventCall()))
});
return false;
}
@ -789,7 +790,7 @@ bool ASTJsonExporter::visit(EmitStatement const& _node)
bool ASTJsonExporter::visit(RevertStatement const& _node)
{
setJsonNode(_node, "RevertStatement", {
std::make_pair("errorCall", toJson(_node.errorCall()))
make_pair("errorCall", toJson(_node.errorCall()))
});
return false;
}
@ -800,9 +801,9 @@ bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node)
for (auto const& v: _node.declarations())
appendMove(varDecs, idOrNull(v.get()));
setJsonNode(_node, "VariableDeclarationStatement", {
std::make_pair("assignments", std::move(varDecs)),
std::make_pair("declarations", toJson(_node.declarations())),
std::make_pair("initialValue", toJsonOrNull(_node.initialValue()))
make_pair("assignments", std::move(varDecs)),
make_pair("declarations", toJson(_node.declarations())),
make_pair("initialValue", toJsonOrNull(_node.initialValue()))
});
return false;
}
@ -810,17 +811,17 @@ bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node)
bool ASTJsonExporter::visit(ExpressionStatement const& _node)
{
setJsonNode(_node, "ExpressionStatement", {
std::make_pair("expression", toJson(_node.expression()))
make_pair("expression", toJson(_node.expression()))
});
return false;
}
bool ASTJsonExporter::visit(Conditional const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("condition", toJson(_node.condition())),
std::make_pair("trueExpression", toJson(_node.trueExpression())),
std::make_pair("falseExpression", toJson(_node.falseExpression()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("condition", toJson(_node.condition())),
make_pair("trueExpression", toJson(_node.trueExpression())),
make_pair("falseExpression", toJson(_node.falseExpression()))
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "Conditional", std::move(attributes));
@ -829,10 +830,10 @@ bool ASTJsonExporter::visit(Conditional const& _node)
bool ASTJsonExporter::visit(Assignment const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("operator", TokenTraits::toString(_node.assignmentOperator())),
std::make_pair("leftHandSide", toJson(_node.leftHandSide())),
std::make_pair("rightHandSide", toJson(_node.rightHandSide()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("operator", TokenTraits::toString(_node.assignmentOperator())),
make_pair("leftHandSide", toJson(_node.leftHandSide())),
make_pair("rightHandSide", toJson(_node.rightHandSide()))
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "Assignment", std::move(attributes));
@ -841,9 +842,9 @@ bool ASTJsonExporter::visit(Assignment const& _node)
bool ASTJsonExporter::visit(TupleExpression const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("isInlineArray", Json::Value(_node.isInlineArray())),
std::make_pair("components", toJson(_node.components())),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("isInlineArray", Json::Value(_node.isInlineArray())),
make_pair("components", toJson(_node.components())),
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "TupleExpression", std::move(attributes));
@ -852,10 +853,10 @@ bool ASTJsonExporter::visit(TupleExpression const& _node)
bool ASTJsonExporter::visit(UnaryOperation const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("prefix", _node.isPrefixOperation()),
std::make_pair("operator", TokenTraits::toString(_node.getOperator())),
std::make_pair("subExpression", toJson(_node.subExpression()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("prefix", _node.isPrefixOperation()),
make_pair("operator", TokenTraits::toString(_node.getOperator())),
make_pair("subExpression", toJson(_node.subExpression()))
};
// NOTE: This annotation is guaranteed to be set but only if we didn't stop at the parsing stage.
if (_node.annotation().userDefinedFunction.set() && *_node.annotation().userDefinedFunction != nullptr)
@ -867,11 +868,11 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node)
bool ASTJsonExporter::visit(BinaryOperation const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("operator", TokenTraits::toString(_node.getOperator())),
std::make_pair("leftExpression", toJson(_node.leftExpression())),
std::make_pair("rightExpression", toJson(_node.rightExpression())),
std::make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("operator", TokenTraits::toString(_node.getOperator())),
make_pair("leftExpression", toJson(_node.leftExpression())),
make_pair("rightExpression", toJson(_node.rightExpression())),
make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
};
// NOTE: This annotation is guaranteed to be set but only if we didn't stop at the parsing stage.
if (_node.annotation().userDefinedFunction.set() && *_node.annotation().userDefinedFunction != nullptr)
@ -886,12 +887,12 @@ bool ASTJsonExporter::visit(FunctionCall const& _node)
Json::Value names(Json::arrayValue);
for (auto const& name: _node.names())
names.append(Json::Value(*name));
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("expression", toJson(_node.expression())),
std::make_pair("names", std::move(names)),
std::make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
std::make_pair("arguments", toJson(_node.arguments())),
std::make_pair("tryCall", _node.annotation().tryCall)
std::vector<pair<string, Json::Value>> attributes = {
make_pair("expression", toJson(_node.expression())),
make_pair("names", std::move(names)),
make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
make_pair("arguments", toJson(_node.arguments())),
make_pair("tryCall", _node.annotation().tryCall)
};
if (_node.annotation().kind.set())
@ -911,10 +912,10 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
for (auto const& name: _node.names())
names.append(Json::Value(*name));
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("expression", toJson(_node.expression())),
std::make_pair("names", std::move(names)),
std::make_pair("options", toJson(_node.options())),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("expression", toJson(_node.expression())),
make_pair("names", std::move(names)),
make_pair("options", toJson(_node.options())),
};
appendExpressionAttributes(attributes, _node.annotation());
@ -924,8 +925,8 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
bool ASTJsonExporter::visit(NewExpression const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("typeName", toJson(_node.typeName()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("typeName", toJson(_node.typeName()))
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "NewExpression", std::move(attributes));
@ -934,11 +935,11 @@ bool ASTJsonExporter::visit(NewExpression const& _node)
bool ASTJsonExporter::visit(MemberAccess const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("memberName", _node.memberName()),
std::make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))),
std::make_pair("expression", toJson(_node.expression())),
std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("memberName", _node.memberName()),
make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))),
make_pair("expression", toJson(_node.expression())),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "MemberAccess", std::move(attributes));
@ -947,9 +948,9 @@ bool ASTJsonExporter::visit(MemberAccess const& _node)
bool ASTJsonExporter::visit(IndexAccess const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("baseExpression", toJson(_node.baseExpression())),
std::make_pair("indexExpression", toJsonOrNull(_node.indexExpression())),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("baseExpression", toJson(_node.baseExpression())),
make_pair("indexExpression", toJsonOrNull(_node.indexExpression())),
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "IndexAccess", std::move(attributes));
@ -958,10 +959,10 @@ bool ASTJsonExporter::visit(IndexAccess const& _node)
bool ASTJsonExporter::visit(IndexRangeAccess const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("baseExpression", toJson(_node.baseExpression())),
std::make_pair("startExpression", toJsonOrNull(_node.startExpression())),
std::make_pair("endExpression", toJsonOrNull(_node.endExpression())),
std::vector<pair<string, Json::Value>> attributes = {
make_pair("baseExpression", toJson(_node.baseExpression())),
make_pair("startExpression", toJsonOrNull(_node.startExpression())),
make_pair("endExpression", toJsonOrNull(_node.endExpression())),
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "IndexRangeAccess", std::move(attributes));
@ -974,19 +975,19 @@ bool ASTJsonExporter::visit(Identifier const& _node)
for (auto const& dec: _node.annotation().overloadedDeclarations)
overloads.append(nodeId(*dec));
setJsonNode(_node, "Identifier", {
std::make_pair("name", _node.name()),
std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
std::make_pair("overloadedDeclarations", overloads),
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
std::make_pair("argumentTypes", typePointerToJson(_node.annotation().arguments))
make_pair("name", _node.name()),
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
make_pair("overloadedDeclarations", overloads),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
make_pair("argumentTypes", typePointerToJson(_node.annotation().arguments))
});
return false;
}
bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node)
{
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("typeName", toJson(_node.type()))
std::vector<pair<string, Json::Value>> attributes = {
make_pair("typeName", toJson(_node.type()))
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes));
@ -999,11 +1000,11 @@ bool ASTJsonExporter::visit(Literal const& _node)
if (!util::validateUTF8(_node.value()))
value = Json::nullValue;
Token subdenomination = Token(_node.subDenomination());
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("kind", literalTokenKind(_node.token())),
std::make_pair("value", value),
std::make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
std::make_pair(
std::vector<pair<string, Json::Value>> attributes = {
make_pair("kind", literalTokenKind(_node.token())),
make_pair("value", value),
make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
make_pair(
"subdenomination",
subdenomination == Token::Illegal ?
Json::nullValue :
@ -1018,8 +1019,8 @@ bool ASTJsonExporter::visit(Literal const& _node)
bool ASTJsonExporter::visit(StructuredDocumentation const& _node)
{
Json::Value text{*_node.text()};
std::vector<std::pair<std::string, Json::Value>> attributes = {
std::make_pair("text", text)
std::vector<pair<string, Json::Value>> attributes = {
make_pair("text", text)
};
setJsonNode(_node, "StructuredDocumentation", std::move(attributes));
return false;
@ -1032,7 +1033,7 @@ void ASTJsonExporter::endVisit(EventDefinition const&)
m_inEvent = false;
}
std::string ASTJsonExporter::location(VariableDeclaration::Location _location)
string ASTJsonExporter::location(VariableDeclaration::Location _location)
{
switch (_location)
{
@ -1049,7 +1050,7 @@ std::string ASTJsonExporter::location(VariableDeclaration::Location _location)
return {};
}
std::string ASTJsonExporter::contractKind(ContractKind _kind)
string ASTJsonExporter::contractKind(ContractKind _kind)
{
switch (_kind)
{
@ -1065,7 +1066,7 @@ std::string ASTJsonExporter::contractKind(ContractKind _kind)
return {};
}
std::string ASTJsonExporter::functionCallKind(FunctionCallKind _kind)
string ASTJsonExporter::functionCallKind(FunctionCallKind _kind)
{
switch (_kind)
{
@ -1080,7 +1081,7 @@ std::string ASTJsonExporter::functionCallKind(FunctionCallKind _kind)
}
}
std::string ASTJsonExporter::literalTokenKind(Token _token)
string ASTJsonExporter::literalTokenKind(Token _token)
{
switch (_token)
{
@ -1100,12 +1101,12 @@ std::string ASTJsonExporter::literalTokenKind(Token _token)
}
}
std::string ASTJsonExporter::type(Expression const& _expression)
string ASTJsonExporter::type(Expression const& _expression)
{
return _expression.annotation().type ? _expression.annotation().type->toString() : "Unknown";
}
std::string ASTJsonExporter::type(VariableDeclaration const& _varDecl)
string ASTJsonExporter::type(VariableDeclaration const& _varDecl)
{
return _varDecl.annotation().type ? _varDecl.annotation().type->toString() : "Unknown";
}

View File

@ -37,6 +37,8 @@
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
using namespace std;
namespace solidity::frontend
{
@ -48,16 +50,16 @@ ASTPointer<T> ASTJsonImporter::nullOrCast(Json::Value const& _json)
if (_json.isNull())
return nullptr;
else
return std::dynamic_pointer_cast<T>(convertJsonToASTNode(_json));
return dynamic_pointer_cast<T>(convertJsonToASTNode(_json));
}
// ============ public ===========================
std::map<std::string, ASTPointer<SourceUnit>> ASTJsonImporter::jsonToSourceUnit(std::map<std::string, Json::Value> const& _sourceList)
map<string, ASTPointer<SourceUnit>> ASTJsonImporter::jsonToSourceUnit(map<string, Json::Value> const& _sourceList)
{
for (auto const& src: _sourceList)
m_sourceNames.emplace_back(std::make_shared<std::string const>(src.first));
m_sourceNames.emplace_back(make_shared<string const>(src.first));
for (auto const& srcPair: _sourceList)
{
astAssert(!srcPair.second.isNull());
@ -79,7 +81,7 @@ ASTPointer<T> ASTJsonImporter::createASTNode(Json::Value const& _node, Args&&...
astAssert(m_usedIDs.insert(id).second, "Found duplicate node ID!");
auto n = std::make_shared<T>(
auto n = make_shared<T>(
id,
createSourceLocation(_node),
std::forward<Args>(_args)...
@ -94,9 +96,9 @@ SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _n
return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_sourceNames);
}
std::optional<std::vector<SourceLocation>> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const
optional<vector<SourceLocation>> ASTJsonImporter::createSourceLocations(Json::Value const& _node) const
{
std::vector<SourceLocation> locations;
vector<SourceLocation> locations;
if (_node.isMember("nameLocations") && _node["nameLocations"].isArray())
{
@ -105,7 +107,7 @@ std::optional<std::vector<SourceLocation>> ASTJsonImporter::createSourceLocation
return locations;
}
return std::nullopt;
return nullopt;
}
SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _node)
@ -132,7 +134,7 @@ SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json::Value const&
template<class T>
ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node)
{
ASTPointer<T> ret = std::dynamic_pointer_cast<T>(convertJsonToASTNode(_node));
ASTPointer<T> ret = dynamic_pointer_cast<T>(convertJsonToASTNode(_node));
astAssert(ret, "cast of converted json-node must not be nullptr");
return ret;
}
@ -141,7 +143,7 @@ ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node)
ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _json)
{
astAssert(_json["nodeType"].isString() && _json.isMember("id"), "JSON-Node needs to have 'nodeType' and 'id' fields.");
std::string nodeType = _json["nodeType"].asString();
string nodeType = _json["nodeType"].asString();
if (nodeType == "PragmaDirective")
return createPragmaDirective(_json);
if (nodeType == "ImportDirective")
@ -263,9 +265,9 @@ ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js
// ============ functions to instantiate the AST-Nodes from Json-Nodes ==============
ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _node, std::string const& _srcName)
ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _node, string const& _srcName)
{
std::optional<std::string> license;
optional<string> license;
if (_node.isMember("license") && !_node["license"].isNull())
license = _node["license"].asString();
@ -273,7 +275,7 @@ ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _nod
if (_node.isMember("experimentalSolidity") && !_node["experimentalSolidity"].isNull())
experimentalSolidity = _node["experimentalSolidity"].asBool();
std::vector<ASTPointer<ASTNode>> nodes;
vector<ASTPointer<ASTNode>> nodes;
for (auto& child: member(_node, "nodes"))
nodes.emplace_back(convertJsonToASTNode(child));
@ -284,11 +286,11 @@ ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _nod
ASTPointer<PragmaDirective> ASTJsonImporter::createPragmaDirective(Json::Value const& _node)
{
std::vector<Token> tokens;
std::vector<ASTString> literals;
vector<Token> tokens;
vector<ASTString> literals;
for (auto const& lit: member(_node, "literals"))
{
std::string l = lit.asString();
string l = lit.asString();
literals.push_back(l);
tokens.push_back(scanSingleToken(l));
}
@ -307,7 +309,7 @@ ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value c
symbolAliases.push_back({
createIdentifier(tuple["foreign"]),
tuple["local"].isNull() ? nullptr : std::make_shared<ASTString>(tuple["local"].asString()),
tuple["local"].isNull() ? nullptr : make_shared<ASTString>(tuple["local"].asString()),
createSourceLocation(tuple["foreign"])}
);
}
@ -341,7 +343,7 @@ ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::V
return createASTNode<ContractDefinition>(
_node,
std::make_shared<ASTString>(_node["name"].asString()),
make_shared<ASTString>(_node["name"].asString()),
createNameSourceLocation(_node),
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
baseContracts,
@ -355,13 +357,13 @@ ASTPointer<IdentifierPath> ASTJsonImporter::createIdentifierPath(Json::Value con
{
astAssert(_node["name"].isString(), "Expected 'name' to be a string!");
std::vector<ASTString> namePath;
std::vector<SourceLocation> namePathLocations;
std::vector<std::string> strs;
std::string nameString = member(_node, "name").asString();
vector<ASTString> namePath;
vector<SourceLocation> namePathLocations;
vector<string> strs;
string nameString = member(_node, "name").asString();
boost::algorithm::split(strs, nameString, boost::is_any_of("."));
astAssert(!strs.empty(), "Expected at least one element in IdentifierPath.");
for (std::string s: strs)
for (string s: strs)
{
astAssert(!s.empty(), "Expected non-empty string for IdentifierPath element.");
namePath.emplace_back(s);
@ -393,20 +395,20 @@ ASTPointer<InheritanceSpecifier> ASTJsonImporter::createInheritanceSpecifier(Jso
return createASTNode<InheritanceSpecifier>(
_node,
createIdentifierPath(member(_node, "baseName")),
member(_node, "arguments").isNull() ? nullptr : std::make_unique<std::vector<ASTPointer<Expression>>>(arguments)
member(_node, "arguments").isNull() ? nullptr : make_unique<std::vector<ASTPointer<Expression>>>(arguments)
);
}
ASTPointer<UsingForDirective> ASTJsonImporter::createUsingForDirective(Json::Value const& _node)
{
std::vector<ASTPointer<IdentifierPath>> functions;
std::vector<std::optional<Token>> operators;
vector<ASTPointer<IdentifierPath>> functions;
vector<optional<Token>> operators;
if (_node.isMember("libraryName"))
{
astAssert(!_node["libraryName"].isArray());
astAssert(!_node["libraryName"]["operator"]);
functions.emplace_back(createIdentifierPath(_node["libraryName"]));
operators.emplace_back(std::nullopt);
operators.emplace_back(nullopt);
}
else if (_node.isMember("functionList"))
for (Json::Value const& function: _node["functionList"])
@ -417,7 +419,7 @@ ASTPointer<UsingForDirective> ASTJsonImporter::createUsingForDirective(Json::Val
astAssert(!function.isMember("definition"));
functions.emplace_back(createIdentifierPath(function["function"]));
operators.emplace_back(std::nullopt);
operators.emplace_back(nullopt);
}
else
{
@ -518,7 +520,7 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
Token kind;
bool freeFunction = false;
std::string kindStr = member(_node, "kind").asString();
string kindStr = member(_node, "kind").asString();
if (kindStr == "constructor")
kind = Token::Constructor;
@ -570,7 +572,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
VariableDeclaration::Mutability mutability{};
astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string.");
std::string const mutabilityStr = member(_node, "mutability").asString();
string const mutabilityStr = member(_node, "mutability").asString();
if (mutabilityStr == "constant")
{
mutability = VariableDeclaration::Mutability::Constant;
@ -590,7 +592,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
return createASTNode<VariableDeclaration>(
_node,
nullOrCast<TypeName>(member(_node, "typeName")),
std::make_shared<ASTString>(member(_node, "name").asString()),
make_shared<ASTString>(member(_node, "name").asString()),
createNameSourceLocation(_node),
nullOrCast<Expression>(member(_node, "value")),
visibility(_node),
@ -624,7 +626,7 @@ ASTPointer<ModifierInvocation> ASTJsonImporter::createModifierInvocation(Json::V
return createASTNode<ModifierInvocation>(
_node,
createIdentifierPath(member(_node, "modifierName")),
member(_node, "arguments").isNull() ? nullptr : std::make_unique<std::vector<ASTPointer<Expression>>>(arguments)
member(_node, "arguments").isNull() ? nullptr : make_unique<std::vector<ASTPointer<Expression>>>(arguments)
);
}
@ -658,9 +660,9 @@ ASTPointer<ElementaryTypeName> ASTJsonImporter::createElementaryTypeName(Json::V
astAssert(_node["name"].isString(), "Expected 'name' to be a string!");
std::string name = member(_node, "name").asString();
string name = member(_node, "name").asString();
Token token;
std::tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name);
tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name);
ElementaryTypeNameToken elem(token, firstNum, secondNum);
std::optional<StateMutability> mutability = {};
@ -719,19 +721,19 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json::Value con
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
ASTPointer<std::vector<ASTPointer<ASTString>>> flags;
ASTPointer<vector<ASTPointer<ASTString>>> flags;
if (_node.isMember("flags"))
{
flags = std::make_shared<std::vector<ASTPointer<ASTString>>>();
flags = make_shared<vector<ASTPointer<ASTString>>>();
Json::Value const& flagsNode = _node["flags"];
astAssert(flagsNode.isArray(), "Assembly flags must be an array.");
for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i)
{
astAssert(flagsNode[i].isString(), "Assembly flag must be a string.");
flags->emplace_back(std::make_shared<ASTString>(flagsNode[i].asString()));
flags->emplace_back(make_shared<ASTString>(flagsNode[i].asString()));
}
}
std::shared_ptr<yul::Block> operations = std::make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST")));
shared_ptr<yul::Block> operations = make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST")));
return createASTNode<InlineAssembly>(
_node,
nullOrASTString(_node, "documentation"),
@ -785,7 +787,7 @@ ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json::Value con
ASTPointer<TryStatement> ASTJsonImporter::createTryStatement(Json::Value const& _node)
{
std::vector<ASTPointer<TryCatchClause>> clauses;
vector<ASTPointer<TryCatchClause>> clauses;
for (auto& param: _node["clauses"])
clauses.emplace_back(createTryCatchClause(param));
@ -955,10 +957,10 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
for (auto& name: member(_node, "names"))
{
astAssert(name.isString(), "Expected 'names' members to be strings!");
names.push_back(std::make_shared<ASTString>(name.asString()));
names.push_back(make_shared<ASTString>(name.asString()));
}
std::optional<std::vector<SourceLocation>> sourceLocations = createSourceLocations(_node);
optional<vector<SourceLocation>> sourceLocations = createSourceLocations(_node);
return createASTNode<FunctionCall>(
_node,
@ -967,7 +969,7 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
names,
sourceLocations ?
*sourceLocations :
std::vector<SourceLocation>(names.size())
vector<SourceLocation>(names.size())
);
}
@ -980,7 +982,7 @@ ASTPointer<FunctionCallOptions> ASTJsonImporter::createFunctionCallOptions(Json:
for (auto& name: member(_node, "names"))
{
astAssert(name.isString(), "Expected 'names' members to be strings!");
names.push_back(std::make_shared<ASTString>(name.asString()));
names.push_back(make_shared<ASTString>(name.asString()));
}
return createASTNode<FunctionCallOptions>(
@ -1047,14 +1049,14 @@ ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNa
ASTPointer<ASTNode> ASTJsonImporter::createLiteral(Json::Value const& _node)
{
static std::string const valStr = "value";
static std::string const hexValStr = "hexValue";
static string const valStr = "value";
static string const hexValStr = "hexValue";
astAssert(member(_node, valStr).isString() || member(_node, hexValStr).isString(), "Literal-value is unset.");
ASTPointer<ASTString> value = _node.isMember(hexValStr) ?
std::make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].asString()))) :
std::make_shared<ASTString>(_node[valStr].asString());
make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].asString()))) :
make_shared<ASTString>(_node[valStr].asString());
return createASTNode<Literal>(
_node,
@ -1066,19 +1068,19 @@ ASTPointer<ASTNode> ASTJsonImporter::createLiteral(Json::Value const& _node)
ASTPointer<StructuredDocumentation> ASTJsonImporter::createDocumentation(Json::Value const& _node)
{
static std::string const textString = "text";
static string const textString = "text";
astAssert(member(_node, textString).isString(), "'text' must be a string");
return createASTNode<StructuredDocumentation>(
_node,
std::make_shared<ASTString>(_node[textString].asString())
make_shared<ASTString>(_node[textString].asString())
);
}
// ===== helper functions ==========
Json::Value ASTJsonImporter::member(Json::Value const& _node, std::string const& _name)
Json::Value ASTJsonImporter::member(Json::Value const& _node, string const& _name)
{
if (!_node.isMember(_name))
return Json::nullValue;
@ -1093,19 +1095,19 @@ Token ASTJsonImporter::scanSingleToken(Json::Value const& _node)
return scanner.currentToken();
}
ASTPointer<ASTString> ASTJsonImporter::nullOrASTString(Json::Value const& _json, std::string const& _name)
ASTPointer<ASTString> ASTJsonImporter::nullOrASTString(Json::Value const& _json, string const& _name)
{
return _json[_name].isString() ? memberAsASTString(_json, _name) : nullptr;
}
ASTPointer<ASTString> ASTJsonImporter::memberAsASTString(Json::Value const& _node, std::string const& _name)
ASTPointer<ASTString> ASTJsonImporter::memberAsASTString(Json::Value const& _node, string const& _name)
{
Json::Value value = member(_node, _name);
astAssert(value.isString(), "field " + _name + " must be of type string.");
return std::make_shared<ASTString>(_node[_name].asString());
return make_shared<ASTString>(_node[_name].asString());
}
bool ASTJsonImporter::memberAsBool(Json::Value const& _node, std::string const& _name)
bool ASTJsonImporter::memberAsBool(Json::Value const& _node, string const& _name)
{
Json::Value value = member(_node, _name);
astAssert(value.isBool(), "field " + _name + " must be of type boolean.");
@ -1154,7 +1156,7 @@ Visibility ASTJsonImporter::visibility(Json::Value const& _node)
Json::Value visibility = member(_node, "visibility");
astAssert(visibility.isString(), "'visibility' expected to be a string.");
std::string const visibilityStr = visibility.asString();
string const visibilityStr = visibility.asString();
if (visibilityStr == "default")
return Visibility::Default;
@ -1178,7 +1180,7 @@ VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node
Json::Value storageLoc = member(_node, "storageLocation");
astAssert(storageLoc.isString(), "'storageLocation' expected to be a string.");
std::string const storageLocStr = storageLoc.asString();
string const storageLocStr = storageLoc.asString();
if (storageLocStr == "default")
return VariableDeclaration::Location::Unspecified;
@ -1204,7 +1206,7 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
astAssert(subDen.isString(), "'subDenomination' expected to be string.");
std::string const subDenStr = subDen.asString();
string const subDenStr = subDen.asString();
if (subDenStr == "wei")
return Literal::SubDenomination::Wei;
@ -1234,7 +1236,7 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
StateMutability ASTJsonImporter::stateMutability(Json::Value const& _node)
{
astAssert(member(_node, "stateMutability").isString(), "StateMutability' expected to be string.");
std::string const mutabilityStr = member(_node, "stateMutability").asString();
string const mutabilityStr = member(_node, "stateMutability").asString();
if (mutabilityStr == "pure")
return StateMutability::Pure;

View File

@ -18,6 +18,7 @@
#include <libsolidity/ast/CallGraph.h>
using namespace std;
using namespace solidity::frontend;
bool CallGraph::CompareByID::operator()(Node const& _lhs, Node const& _rhs) const
@ -25,21 +26,21 @@ bool CallGraph::CompareByID::operator()(Node const& _lhs, Node const& _rhs) cons
if (_lhs.index() != _rhs.index())
return _lhs.index() < _rhs.index();
if (std::holds_alternative<SpecialNode>(_lhs))
return std::get<SpecialNode>(_lhs) < std::get<SpecialNode>(_rhs);
return std::get<CallableDeclaration const*>(_lhs)->id() < std::get<CallableDeclaration const*>(_rhs)->id();
if (holds_alternative<SpecialNode>(_lhs))
return get<SpecialNode>(_lhs) < get<SpecialNode>(_rhs);
return get<CallableDeclaration const*>(_lhs)->id() < get<CallableDeclaration const*>(_rhs)->id();
}
bool CallGraph::CompareByID::operator()(Node const& _lhs, int64_t _rhs) const
{
solAssert(!std::holds_alternative<SpecialNode>(_lhs), "");
solAssert(!holds_alternative<SpecialNode>(_lhs), "");
return std::get<CallableDeclaration const*>(_lhs)->id() < _rhs;
return get<CallableDeclaration const*>(_lhs)->id() < _rhs;
}
bool CallGraph::CompareByID::operator()(int64_t _lhs, Node const& _rhs) const
{
solAssert(!std::holds_alternative<SpecialNode>(_rhs), "");
solAssert(!holds_alternative<SpecialNode>(_rhs), "");
return _lhs < std::get<CallableDeclaration const*>(_rhs)->id();
return _lhs < get<CallableDeclaration const*>(_rhs)->id();
}

View File

@ -21,6 +21,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::util;
@ -30,126 +31,126 @@ InaccessibleDynamicType const TypeProvider::m_inaccessibleDynamic{};
/// The string and bytes unique_ptrs are initialized when they are first used because
/// they rely on `byte` being available which we cannot guarantee in the static init context.
std::unique_ptr<ArrayType> TypeProvider::m_bytesStorage;
std::unique_ptr<ArrayType> TypeProvider::m_bytesMemory;
std::unique_ptr<ArrayType> TypeProvider::m_bytesCalldata;
std::unique_ptr<ArrayType> TypeProvider::m_stringStorage;
std::unique_ptr<ArrayType> TypeProvider::m_stringMemory;
unique_ptr<ArrayType> TypeProvider::m_bytesStorage;
unique_ptr<ArrayType> TypeProvider::m_bytesMemory;
unique_ptr<ArrayType> TypeProvider::m_bytesCalldata;
unique_ptr<ArrayType> TypeProvider::m_stringStorage;
unique_ptr<ArrayType> TypeProvider::m_stringMemory;
TupleType const TypeProvider::m_emptyTuple{};
AddressType const TypeProvider::m_payableAddress{StateMutability::Payable};
AddressType const TypeProvider::m_address{StateMutability::NonPayable};
std::array<std::unique_ptr<IntegerType>, 32> const TypeProvider::m_intM{{
{std::make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Signed)},
{std::make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Signed)}
array<unique_ptr<IntegerType>, 32> const TypeProvider::m_intM{{
{make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Signed)},
{make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Signed)}
}};
std::array<std::unique_ptr<IntegerType>, 32> const TypeProvider::m_uintM{{
{std::make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Unsigned)},
{std::make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Unsigned)}
array<unique_ptr<IntegerType>, 32> const TypeProvider::m_uintM{{
{make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Unsigned)},
{make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Unsigned)}
}};
std::array<std::unique_ptr<FixedBytesType>, 32> const TypeProvider::m_bytesM{{
{std::make_unique<FixedBytesType>(1)},
{std::make_unique<FixedBytesType>(2)},
{std::make_unique<FixedBytesType>(3)},
{std::make_unique<FixedBytesType>(4)},
{std::make_unique<FixedBytesType>(5)},
{std::make_unique<FixedBytesType>(6)},
{std::make_unique<FixedBytesType>(7)},
{std::make_unique<FixedBytesType>(8)},
{std::make_unique<FixedBytesType>(9)},
{std::make_unique<FixedBytesType>(10)},
{std::make_unique<FixedBytesType>(11)},
{std::make_unique<FixedBytesType>(12)},
{std::make_unique<FixedBytesType>(13)},
{std::make_unique<FixedBytesType>(14)},
{std::make_unique<FixedBytesType>(15)},
{std::make_unique<FixedBytesType>(16)},
{std::make_unique<FixedBytesType>(17)},
{std::make_unique<FixedBytesType>(18)},
{std::make_unique<FixedBytesType>(19)},
{std::make_unique<FixedBytesType>(20)},
{std::make_unique<FixedBytesType>(21)},
{std::make_unique<FixedBytesType>(22)},
{std::make_unique<FixedBytesType>(23)},
{std::make_unique<FixedBytesType>(24)},
{std::make_unique<FixedBytesType>(25)},
{std::make_unique<FixedBytesType>(26)},
{std::make_unique<FixedBytesType>(27)},
{std::make_unique<FixedBytesType>(28)},
{std::make_unique<FixedBytesType>(29)},
{std::make_unique<FixedBytesType>(30)},
{std::make_unique<FixedBytesType>(31)},
{std::make_unique<FixedBytesType>(32)}
array<unique_ptr<FixedBytesType>, 32> const TypeProvider::m_bytesM{{
{make_unique<FixedBytesType>(1)},
{make_unique<FixedBytesType>(2)},
{make_unique<FixedBytesType>(3)},
{make_unique<FixedBytesType>(4)},
{make_unique<FixedBytesType>(5)},
{make_unique<FixedBytesType>(6)},
{make_unique<FixedBytesType>(7)},
{make_unique<FixedBytesType>(8)},
{make_unique<FixedBytesType>(9)},
{make_unique<FixedBytesType>(10)},
{make_unique<FixedBytesType>(11)},
{make_unique<FixedBytesType>(12)},
{make_unique<FixedBytesType>(13)},
{make_unique<FixedBytesType>(14)},
{make_unique<FixedBytesType>(15)},
{make_unique<FixedBytesType>(16)},
{make_unique<FixedBytesType>(17)},
{make_unique<FixedBytesType>(18)},
{make_unique<FixedBytesType>(19)},
{make_unique<FixedBytesType>(20)},
{make_unique<FixedBytesType>(21)},
{make_unique<FixedBytesType>(22)},
{make_unique<FixedBytesType>(23)},
{make_unique<FixedBytesType>(24)},
{make_unique<FixedBytesType>(25)},
{make_unique<FixedBytesType>(26)},
{make_unique<FixedBytesType>(27)},
{make_unique<FixedBytesType>(28)},
{make_unique<FixedBytesType>(29)},
{make_unique<FixedBytesType>(30)},
{make_unique<FixedBytesType>(31)},
{make_unique<FixedBytesType>(32)}
}};
std::array<std::unique_ptr<MagicType>, 4> const TypeProvider::m_magics{{
{std::make_unique<MagicType>(MagicType::Kind::Block)},
{std::make_unique<MagicType>(MagicType::Kind::Message)},
{std::make_unique<MagicType>(MagicType::Kind::Transaction)},
{std::make_unique<MagicType>(MagicType::Kind::ABI)}
array<unique_ptr<MagicType>, 4> const TypeProvider::m_magics{{
{make_unique<MagicType>(MagicType::Kind::Block)},
{make_unique<MagicType>(MagicType::Kind::Message)},
{make_unique<MagicType>(MagicType::Kind::Transaction)},
{make_unique<MagicType>(MagicType::Kind::ABI)}
// MetaType is stored separately
}};
@ -159,7 +160,7 @@ inline void clearCache(Type const& type)
}
template <typename T>
inline void clearCache(std::unique_ptr<T> const& type)
inline void clearCache(unique_ptr<T> const& type)
{
// Some lazy-initialized types might not exist yet.
if (type)
@ -199,7 +200,7 @@ void TypeProvider::reset()
template <typename T, typename... Args>
inline T const* TypeProvider::createAndGet(Args&& ... _args)
{
instance().m_generalTypes.emplace_back(std::make_unique<T>(std::forward<Args>(_args)...));
instance().m_generalTypes.emplace_back(make_unique<T>(std::forward<Args>(_args)...));
return static_cast<T const*>(instance().m_generalTypes.back().get());
}
@ -258,15 +259,15 @@ Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const&
}
}
Type const* TypeProvider::fromElementaryTypeName(std::string const& _name)
Type const* TypeProvider::fromElementaryTypeName(string const& _name)
{
std::vector<std::string> nameParts;
vector<string> nameParts;
boost::split(nameParts, _name, boost::is_any_of(" "));
solAssert(nameParts.size() == 1 || nameParts.size() == 2, "Cannot parse elementary type: " + _name);
Token token;
unsigned short firstNum, secondNum;
std::tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(nameParts[0]);
tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(nameParts[0]);
auto t = fromElementaryTypeName(ElementaryTypeNameToken(token, firstNum, secondNum));
if (auto* ref = dynamic_cast<ReferenceType const*>(t))
@ -306,35 +307,35 @@ Type const* TypeProvider::fromElementaryTypeName(std::string const& _name)
ArrayType const* TypeProvider::bytesStorage()
{
if (!m_bytesStorage)
m_bytesStorage = std::make_unique<ArrayType>(DataLocation::Storage, false);
m_bytesStorage = make_unique<ArrayType>(DataLocation::Storage, false);
return m_bytesStorage.get();
}
ArrayType const* TypeProvider::bytesMemory()
{
if (!m_bytesMemory)
m_bytesMemory = std::make_unique<ArrayType>(DataLocation::Memory, false);
m_bytesMemory = make_unique<ArrayType>(DataLocation::Memory, false);
return m_bytesMemory.get();
}
ArrayType const* TypeProvider::bytesCalldata()
{
if (!m_bytesCalldata)
m_bytesCalldata = std::make_unique<ArrayType>(DataLocation::CallData, false);
m_bytesCalldata = make_unique<ArrayType>(DataLocation::CallData, false);
return m_bytesCalldata.get();
}
ArrayType const* TypeProvider::stringStorage()
{
if (!m_stringStorage)
m_stringStorage = std::make_unique<ArrayType>(DataLocation::Storage, true);
m_stringStorage = make_unique<ArrayType>(DataLocation::Storage, true);
return m_stringStorage.get();
}
ArrayType const* TypeProvider::stringMemory()
{
if (!m_stringMemory)
m_stringMemory = std::make_unique<ArrayType>(DataLocation::Memory, true);
m_stringMemory = make_unique<ArrayType>(DataLocation::Memory, true);
return m_stringMemory.get();
}
@ -375,30 +376,30 @@ RationalNumberType const* TypeProvider::rationalNumber(Literal const& _literal)
return nullptr;
}
StringLiteralType const* TypeProvider::stringLiteral(std::string const& literal)
StringLiteralType const* TypeProvider::stringLiteral(string const& literal)
{
auto i = instance().m_stringLiteralTypes.find(literal);
if (i != instance().m_stringLiteralTypes.end())
return i->second.get();
else
return instance().m_stringLiteralTypes.emplace(literal, std::make_unique<StringLiteralType>(literal)).first->second.get();
return instance().m_stringLiteralTypes.emplace(literal, make_unique<StringLiteralType>(literal)).first->second.get();
}
FixedPointType const* TypeProvider::fixedPoint(unsigned m, unsigned n, FixedPointType::Modifier _modifier)
{
auto& map = _modifier == FixedPointType::Modifier::Unsigned ? instance().m_ufixedMxN : instance().m_fixedMxN;
auto i = map.find(std::make_pair(m, n));
auto i = map.find(make_pair(m, n));
if (i != map.end())
return i->second.get();
return map.emplace(
std::make_pair(m, n),
std::make_unique<FixedPointType>(m, n, _modifier)
make_pair(m, n),
make_unique<FixedPointType>(m, n, _modifier)
).first->second.get();
}
TupleType const* TypeProvider::tuple(std::vector<Type const*> members)
TupleType const* TypeProvider::tuple(vector<Type const*> members)
{
if (members.empty())
return &m_emptyTuple;

File diff suppressed because it is too large Load Diff

View File

@ -30,11 +30,12 @@
#include <boost/algorithm/string/join.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
std::string ABIFunctions::tupleEncoder(
string ABIFunctions::tupleEncoder(
TypePointers const& _givenTypes,
TypePointers _targetTypes,
bool _encodeAsLibraryTypes,
@ -55,7 +56,7 @@ std::string ABIFunctions::tupleEncoder(
solAssert(t, "");
}
std::string functionName = std::string("abi_encode_tuple_");
string functionName = string("abi_encode_tuple_");
for (auto const& t: _givenTypes)
functionName += t->identifier() + "_";
functionName += "_to_";
@ -75,8 +76,8 @@ std::string ABIFunctions::tupleEncoder(
)");
templ("functionName", functionName);
size_t const headSize_ = headSize(_targetTypes);
templ("headSize", std::to_string(headSize_));
std::string encodeElements;
templ("headSize", to_string(headSize_));
string encodeElements;
size_t headPos = 0;
size_t stackPos = 0;
for (size_t i = 0; i < _givenTypes.size(); ++i)
@ -87,24 +88,24 @@ std::string ABIFunctions::tupleEncoder(
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
Whiskers elementTempl(
dynamic ?
std::string(R"(
string(R"(
mstore(add(headStart, <pos>), sub(tail, headStart))
tail := <abiEncode>(<values> tail)
)") :
std::string(R"(
string(R"(
<abiEncode>(<values> add(headStart, <pos>))
)")
);
std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
elementTempl("values", values.empty() ? "" : values + ", ");
elementTempl("pos", std::to_string(headPos));
elementTempl("pos", to_string(headPos));
elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options));
encodeElements += elementTempl.render();
headPos += _targetTypes[i]->calldataHeadSize();
stackPos += sizeOnStack;
}
solAssert(headPos == headSize_, "");
std::string valueParams =
string valueParams =
_reversed ?
suffixedVariableNameList("value", stackPos, 0) :
suffixedVariableNameList("value", 0, stackPos);
@ -115,7 +116,7 @@ std::string ABIFunctions::tupleEncoder(
});
}
std::string ABIFunctions::tupleEncoderPacked(
string ABIFunctions::tupleEncoderPacked(
TypePointers const& _givenTypes,
TypePointers _targetTypes,
bool _reversed
@ -134,7 +135,7 @@ std::string ABIFunctions::tupleEncoderPacked(
solAssert(t, "");
}
std::string functionName = std::string("abi_encode_tuple_packed_");
string functionName = string("abi_encode_tuple_packed_");
for (auto const& t: _givenTypes)
functionName += t->identifier() + "_";
functionName += "_to_";
@ -153,7 +154,7 @@ std::string ABIFunctions::tupleEncoderPacked(
}
)");
templ("functionName", functionName);
std::string encodeElements;
string encodeElements;
size_t stackPos = 0;
for (size_t i = 0; i < _givenTypes.size(); ++i)
{
@ -163,23 +164,23 @@ std::string ABIFunctions::tupleEncoderPacked(
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
Whiskers elementTempl(
dynamic ?
std::string(R"(
string(R"(
pos := <abiEncode>(<values> pos)
)") :
std::string(R"(
string(R"(
<abiEncode>(<values> pos)
pos := add(pos, <calldataEncodedSize>)
)")
);
std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
elementTempl("values", values.empty() ? "" : values + ", ");
if (!dynamic)
elementTempl("calldataEncodedSize", std::to_string(_targetTypes[i]->calldataEncodedSize(false)));
elementTempl("calldataEncodedSize", to_string(_targetTypes[i]->calldataEncodedSize(false)));
elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options));
encodeElements += elementTempl.render();
stackPos += sizeOnStack;
}
std::string valueParams =
string valueParams =
_reversed ?
suffixedVariableNameList("value", stackPos, 0) :
suffixedVariableNameList("value", 0, stackPos);
@ -189,9 +190,9 @@ std::string ABIFunctions::tupleEncoderPacked(
return templ.render();
});
}
std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
{
std::string functionName = std::string("abi_decode_tuple_");
string functionName = string("abi_decode_tuple_");
for (auto const& t: _types)
functionName += t->identifier();
if (_fromMemory)
@ -210,10 +211,10 @@ std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMem
)");
templ("functionName", functionName);
templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short"));
templ("minimumSize", std::to_string(headSize(decodingTypes)));
templ("minimumSize", to_string(headSize(decodingTypes)));
std::string decodeElements;
std::vector<std::string> valueReturnParams;
string decodeElements;
vector<string> valueReturnParams;
size_t headPos = 0;
size_t stackPos = 0;
for (size_t i = 0; i < _types.size(); ++i)
@ -223,11 +224,11 @@ std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMem
size_t sizeOnStack = _types[i]->sizeOnStack();
solAssert(sizeOnStack == decodingTypes[i]->sizeOnStack(), "");
solAssert(sizeOnStack > 0, "");
std::vector<std::string> valueNamesLocal;
vector<string> valueNamesLocal;
for (size_t j = 0; j < sizeOnStack; j++)
{
valueNamesLocal.emplace_back("value" + std::to_string(stackPos));
valueReturnParams.emplace_back("value" + std::to_string(stackPos));
valueNamesLocal.emplace_back("value" + to_string(stackPos));
valueReturnParams.emplace_back("value" + to_string(stackPos));
stackPos++;
}
Whiskers elementTempl(R"(
@ -246,7 +247,7 @@ std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMem
elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset"));
elementTempl("load", _fromMemory ? "mload" : "calldataload");
elementTempl("values", boost::algorithm::join(valueNamesLocal, ", "));
elementTempl("pos", std::to_string(headPos));
elementTempl("pos", to_string(headPos));
elementTempl("abiDecode", abiDecodingFunction(*_types[i], _fromMemory, true));
decodeElements += elementTempl.render();
headPos += decodingTypes[i]->calldataHeadSize();
@ -259,9 +260,9 @@ std::string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMem
});
}
std::string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
{
std::string suffix;
string suffix;
if (!padded)
suffix += "_nonPadded";
if (dynamicInplace)
@ -273,7 +274,7 @@ std::string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
return suffix;
}
std::string ABIFunctions::abiEncodingFunction(
string ABIFunctions::abiEncodingFunction(
Type const& _from,
Type const& _to,
EncodingOptions const& _options
@ -348,7 +349,7 @@ std::string ABIFunctions::abiEncodingFunction(
solAssert(_from.sizeOnStack() == 1, "");
solAssert(to.isValueType(), "");
solAssert(to.calldataEncodedSize() == 32, "");
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -375,7 +376,7 @@ std::string ABIFunctions::abiEncodingFunction(
}
else
{
std::string cleanupConvert;
string cleanupConvert;
if (_from == to)
cleanupConvert = m_utils.cleanupFunction(_from) + "(value)";
else
@ -388,21 +389,21 @@ std::string ABIFunctions::abiEncodingFunction(
});
}
std::string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
Type const& _givenType,
Type const& _targetType,
ABIFunctions::EncodingOptions const& _options
)
{
std::string functionName =
string functionName =
"abi_encodeUpdatedPos_" +
_givenType.identifier() +
"_to_" +
_targetType.identifier() +
_options.toFunctionNameSuffix();
return createFunction(functionName, [&]() {
std::string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options));
std::string encoder = abiEncodingFunction(_givenType, _targetType, _options);
string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options));
string encoder = abiEncodingFunction(_givenType, _targetType, _options);
Type const* targetEncoding = _targetType.fullEncodingType(_options.encodeAsLibraryTypes, true, false);
solAssert(targetEncoding, "");
if (targetEncoding->isDynamicallyEncoded())
@ -434,7 +435,7 @@ std::string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
});
}
std::string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
Type const& _from,
Type const& _to,
EncodingOptions const& _options
@ -460,7 +461,7 @@ std::string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
""
);
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -521,13 +522,13 @@ std::string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
});
}
std::string ABIFunctions::abiEncodingFunctionSimpleArray(
string ABIFunctions::abiEncodingFunctionSimpleArray(
ArrayType const& _from,
ArrayType const& _to,
EncodingOptions const& _options
)
{
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -547,7 +548,7 @@ std::string ABIFunctions::abiEncodingFunctionSimpleArray(
EncodingOptions subOptions(_options);
subOptions.encodeFunctionFromStack = false;
subOptions.padded = true;
std::string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions));
string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions));
Whiskers templ(
usesTail ?
R"(
@ -631,13 +632,13 @@ std::string ABIFunctions::abiEncodingFunctionSimpleArray(
});
}
std::string ABIFunctions::abiEncodingFunctionMemoryByteArray(
string ABIFunctions::abiEncodingFunctionMemoryByteArray(
ArrayType const& _from,
ArrayType const& _to,
EncodingOptions const& _options
)
{
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -668,13 +669,13 @@ std::string ABIFunctions::abiEncodingFunctionMemoryByteArray(
});
}
std::string ABIFunctions::abiEncodingFunctionCompactStorageArray(
string ABIFunctions::abiEncodingFunctionCompactStorageArray(
ArrayType const& _from,
ArrayType const& _to,
EncodingOptions const& _options
)
{
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -790,13 +791,13 @@ std::string ABIFunctions::abiEncodingFunctionCompactStorageArray(
templ("useSpill", "1");
else
templ("useSpill", "0");
templ("itemsPerSlot", std::to_string(itemsPerSlot));
templ("itemsPerSlot", to_string(itemsPerSlot));
templ("stride", toCompactHexWithPrefix(_to.calldataStride()));
EncodingOptions subOptions(_options);
subOptions.encodeFunctionFromStack = false;
subOptions.padded = true;
std::string encodeToMemoryFun = abiEncodingFunction(
string encodeToMemoryFun = abiEncodingFunction(
*_from.baseType(),
*_to.baseType(),
subOptions
@ -819,13 +820,13 @@ std::string ABIFunctions::abiEncodingFunctionCompactStorageArray(
});
}
std::string ABIFunctions::abiEncodingFunctionStruct(
string ABIFunctions::abiEncodingFunctionStruct(
StructType const& _from,
StructType const& _to,
EncodingOptions const& _options
)
{
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -866,7 +867,7 @@ std::string ABIFunctions::abiEncodingFunctionStruct(
templ("init", _from.dataStoredIn(DataLocation::Storage) ? "let slotValue := 0" : "");
u256 previousSlotOffset(-1);
u256 encodingOffset = 0;
std::vector<std::map<std::string, std::string>> members;
vector<map<string, string>> members;
for (auto const& member: _to.members(nullptr))
{
solAssert(member.type, "");
@ -889,7 +890,7 @@ std::string ABIFunctions::abiEncodingFunctionStruct(
solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), "");
u256 storageSlotOffset;
size_t intraSlotOffset;
std::tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name);
tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name);
if (memberTypeFrom->isValueType())
{
if (storageSlotOffset != previousSlotOffset)
@ -909,13 +910,13 @@ std::string ABIFunctions::abiEncodingFunctionStruct(
}
case DataLocation::Memory:
{
std::string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name));
string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name));
members.back()["retrieveValue"] = "mload(add(value, " + sourceOffset + "))";
break;
}
case DataLocation::CallData:
{
std::string sourceOffset = toCompactHexWithPrefix(_from.calldataOffsetOfMember(member.name));
string sourceOffset = toCompactHexWithPrefix(_from.calldataOffsetOfMember(member.name));
members.back()["retrieveValue"] = calldataAccessFunction(*memberTypeFrom) + "(value, add(value, " + sourceOffset + "))";
break;
}
@ -928,10 +929,10 @@ std::string ABIFunctions::abiEncodingFunctionStruct(
// Like with arrays, struct members are always padded.
subOptions.padded = true;
std::string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions));
string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions));
members.back()["memberValues"] = memberValues;
std::string encode;
string encode;
if (_options.dynamicInplace)
encode = Whiskers{"pos := <encode>(<memberValues>, pos)"}
("encode", abiEncodeAndReturnUpdatedPosFunction(*memberTypeFrom, *memberTypeTo, subOptions))
@ -941,7 +942,7 @@ std::string ABIFunctions::abiEncodingFunctionStruct(
{
Whiskers encodeTempl(
dynamicMember ?
std::string(R"(
string(R"(
mstore(add(pos, <encodingOffset>), sub(tail, pos))
tail := <abiEncode>(<memberValues>, tail)
)") :
@ -965,7 +966,7 @@ std::string ABIFunctions::abiEncodingFunctionStruct(
});
}
std::string ABIFunctions::abiEncodingFunctionStringLiteral(
string ABIFunctions::abiEncodingFunctionStringLiteral(
Type const& _from,
Type const& _to,
EncodingOptions const& _options
@ -973,7 +974,7 @@ std::string ABIFunctions::abiEncodingFunctionStringLiteral(
{
solAssert(_from.category() == Type::Category::StringLiteral, "");
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -981,7 +982,7 @@ std::string ABIFunctions::abiEncodingFunctionStringLiteral(
_options.toFunctionNameSuffix();
return createFunction(functionName, [&]() {
auto const& strType = dynamic_cast<StringLiteralType const&>(_from);
std::string const& value = strType.value();
string const& value = strType.value();
solAssert(_from.sizeOnStack() == 0, "");
if (_to.isDynamicallySized())
@ -997,12 +998,12 @@ std::string ABIFunctions::abiEncodingFunctionStringLiteral(
templ("functionName", functionName);
// TODO this can make use of CODECOPY for large strings once we have that in Yul
templ("length", std::to_string(value.size()));
templ("length", to_string(value.size()));
templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options));
if (_options.padded)
templ("overallSize", std::to_string(((value.size() + 31) / 32) * 32));
templ("overallSize", to_string(((value.size() + 31) / 32) * 32));
else
templ("overallSize", std::to_string(value.size()));
templ("overallSize", to_string(value.size()));
templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value));
return templ.render();
}
@ -1022,7 +1023,7 @@ std::string ABIFunctions::abiEncodingFunctionStringLiteral(
});
}
std::string ABIFunctions::abiEncodingFunctionFunctionType(
string ABIFunctions::abiEncodingFunctionFunctionType(
FunctionType const& _from,
Type const& _to,
EncodingOptions const& _options
@ -1035,7 +1036,7 @@ std::string ABIFunctions::abiEncodingFunctionFunctionType(
"Invalid function type conversion requested"
);
std::string functionName =
string functionName =
"abi_encode_" +
_from.identifier() +
"_to_" +
@ -1068,7 +1069,7 @@ std::string ABIFunctions::abiEncodingFunctionFunctionType(
});
}
std::string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack)
string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack)
{
// The decoding function has to perform bounds checks unless it decodes a value type.
// Conversely, bounds checks have to be performed before the decoding function
@ -1103,7 +1104,7 @@ std::string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemor
return abiDecodingFunctionValueType(_type, _fromMemory);
}
std::string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
{
Type const* decodingType = _type.decodingType();
solAssert(decodingType, "");
@ -1112,7 +1113,7 @@ std::string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _
solAssert(!decodingType->isDynamicallyEncoded(), "");
solAssert(decodingType->calldataEncodedSize() == 32, "");
std::string functionName =
string functionName =
"abi_decode_" +
_type.identifier() +
(_fromMemory ? "_fromMemory" : "");
@ -1133,17 +1134,17 @@ std::string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _
}
std::string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _fromMemory)
string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _fromMemory)
{
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
std::string functionName =
string functionName =
"abi_decode_" +
_type.identifier() +
(_fromMemory ? "_fromMemory" : "");
return createFunction(functionName, [&]() {
std::string load = _fromMemory ? "mload" : "calldataload";
string load = _fromMemory ? "mload" : "calldataload";
Whiskers templ(
R"(
// <readableTypeName>
@ -1165,14 +1166,14 @@ std::string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool
});
}
std::string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
{
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
if (_type.isByteArrayOrString())
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
solAssert(_type.calldataStride() > 0, "");
std::string functionName =
string functionName =
"abi_decode_available_length_" +
_type.identifier() +
(_fromMemory ? "_fromMemory" : "");
@ -1223,7 +1224,7 @@ std::string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType cons
});
}
std::string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
{
solAssert(_type.dataStoredIn(DataLocation::CallData), "");
if (!_type.isDynamicallySized())
@ -1231,7 +1232,7 @@ std::string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _typ
solAssert(_type.calldataStride() > 0, "");
solAssert(_type.calldataStride() < u256("0xffffffffffffffff"), "");
std::string functionName =
string functionName =
"abi_decode_" +
_type.identifier();
return createFunction(functionName, [&]() {
@ -1272,12 +1273,12 @@ std::string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _typ
});
}
std::string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const& _type, bool _fromMemory)
{
solAssert(_type.dataStoredIn(DataLocation::Memory), "");
solAssert(_type.isByteArrayOrString(), "");
std::string functionName =
string functionName =
"abi_decode_available_length_" +
_type.identifier() +
(_fromMemory ? "_fromMemory" : "");
@ -1301,10 +1302,10 @@ std::string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType
});
}
std::string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
{
solAssert(_type.dataStoredIn(DataLocation::CallData), "");
std::string functionName =
string functionName =
"abi_decode_" +
_type.identifier();
@ -1320,15 +1321,15 @@ std::string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _t
w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short"));
w("functionName", functionName);
w("readableTypeName", _type.toString(true));
w("minimumSize", std::to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true)));
w("minimumSize", to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true)));
return w.render();
});
}
std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory)
string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory)
{
solAssert(!_type.dataStoredIn(DataLocation::CallData), "");
std::string functionName =
string functionName =
"abi_decode_" +
_type.identifier() +
(_fromMemory ? "_fromMemory" : "");
@ -1355,7 +1356,7 @@ std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, boo
solAssert(_type.memoryDataSize() < u256("0xffffffffffffffff"), "");
templ("memorySize", toCompactHexWithPrefix(_type.memoryDataSize()));
size_t headPos = 0;
std::vector<std::map<std::string, std::string>> members;
vector<map<string, string>> members;
for (auto const& member: _type.members(nullptr))
{
solAssert(member.type, "");
@ -1375,7 +1376,7 @@ std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, boo
// TODO add test
memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset"));
memberTempl("load", _fromMemory ? "mload" : "calldataload");
memberTempl("pos", std::to_string(headPos));
memberTempl("pos", to_string(headPos));
memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name)));
memberTempl("abiDecode", abiDecodingFunction(*member.type, _fromMemory, false));
@ -1390,11 +1391,11 @@ std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, boo
});
}
std::string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack)
string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack)
{
solAssert(_type.kind() == FunctionType::Kind::External, "");
std::string functionName =
string functionName =
"abi_decode_" +
_type.identifier() +
(_fromMemory ? "_fromMemory" : "") +
@ -1429,10 +1430,10 @@ std::string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _t
});
}
std::string ABIFunctions::calldataAccessFunction(Type const& _type)
string ABIFunctions::calldataAccessFunction(Type const& _type)
{
solAssert(_type.isValueType() || _type.dataStoredIn(DataLocation::CallData), "");
std::string functionName = "calldata_access_" + _type.identifier();
string functionName = "calldata_access_" + _type.identifier();
return createFunction(functionName, [&]() {
if (_type.isDynamicallyEncoded())
{
@ -1476,7 +1477,7 @@ std::string ABIFunctions::calldataAccessFunction(Type const& _type)
}
else if (_type.isValueType())
{
std::string decodingFunction;
string decodingFunction;
if (auto const* functionType = dynamic_cast<FunctionType const*>(&_type))
decodingFunction = abiDecodingFunctionFunctionType(*functionType, false, false);
else
@ -1509,9 +1510,9 @@ std::string ABIFunctions::calldataAccessFunction(Type const& _type)
});
}
std::string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, EncodingOptions const& _options)
string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type, EncodingOptions const& _options)
{
std::string functionName = "array_storeLengthForEncoding_" + _type.identifier() + _options.toFunctionNameSuffix();
string functionName = "array_storeLengthForEncoding_" + _type.identifier() + _options.toFunctionNameSuffix();
return createFunction(functionName, [&]() {
if (_type.isDynamicallySized() && !_options.dynamicInplace)
return Whiskers(R"(
@ -1533,7 +1534,7 @@ std::string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _
});
}
std::string ABIFunctions::createFunction(std::string const& _name, std::function<std::string ()> const& _creator)
string ABIFunctions::createFunction(string const& _name, function<string ()> const& _creator)
{
return m_functionCollector.createFunction(_name, _creator);
}

View File

@ -36,6 +36,7 @@
#include <libevmasm/Instruction.h>
#include <liblangutil/Exceptions.h>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::frontend;
@ -313,7 +314,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
if (!_sourceType.isByteArrayOrString())
convertLengthToSize(_sourceType);
std::string routine = "calldatacopy(target, source, len)\n";
string routine = "calldatacopy(target, source, len)\n";
if (_padToWordBoundaries)
routine += R"(
// Set padding suffix to zero
@ -889,7 +890,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
sstore(ref, slot_value)
})");
code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str());
code("emptyArrayPop", std::to_string(unsigned(util::PanicCode::EmptyArrayPop)));
code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop)));
m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"});
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
}

View File

@ -26,12 +26,13 @@
#include <libsolidity/codegen/ContractCompiler.h>
#include <libevmasm/Assembly.h>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
void Compiler::compileContract(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers,
std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers,
bytes const& _metadata
)
{

View File

@ -55,6 +55,7 @@
#undef SOL_OUTPUT_ASM
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::evmasm;
@ -67,7 +68,7 @@ void CompilerContext::addStateVariable(
unsigned _byteOffset
)
{
m_stateVariables[&_declaration] = std::make_pair(_storageOffset, _byteOffset);
m_stateVariables[&_declaration] = make_pair(_storageOffset, _byteOffset);
}
void CompilerContext::addImmutable(VariableDeclaration const& _variable)
@ -87,14 +88,14 @@ size_t CompilerContext::immutableMemoryOffset(VariableDeclaration const& _variab
return m_immutableVariables.at(&_variable);
}
std::vector<std::string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable)
vector<string> CompilerContext::immutableVariableSlotNames(VariableDeclaration const& _variable)
{
std::string baseName = std::to_string(_variable.id());
string baseName = to_string(_variable.id());
solAssert(_variable.annotation().type->sizeOnStack() > 0, "");
if (_variable.annotation().type->sizeOnStack() == 1)
return {baseName};
std::vector<std::string> names;
auto collectSlotNames = [&](std::string const& _baseName, Type const* type, auto const& _recurse) -> void {
vector<string> names;
auto collectSlotNames = [&](string const& _baseName, Type const* type, auto const& _recurse) -> void {
for (auto const& [slot, type]: type->stackItems())
if (type)
_recurse(_baseName + " " + slot, type, _recurse);
@ -120,10 +121,10 @@ void CompilerContext::startFunction(Declaration const& _function)
}
void CompilerContext::callLowLevelFunction(
std::string const& _name,
string const& _name,
unsigned _inArgs,
unsigned _outArgs,
std::function<void(CompilerContext&)> const& _generator
function<void(CompilerContext&)> const& _generator
)
{
evmasm::AssemblyItem retTag = pushNewTag();
@ -137,7 +138,7 @@ void CompilerContext::callLowLevelFunction(
}
void CompilerContext::callYulFunction(
std::string const& _name,
string const& _name,
unsigned _inArgs,
unsigned _outArgs
)
@ -151,10 +152,10 @@ void CompilerContext::callYulFunction(
}
evmasm::AssemblyItem CompilerContext::lowLevelFunctionTag(
std::string const& _name,
string const& _name,
unsigned _inArgs,
unsigned _outArgs,
std::function<void(CompilerContext&)> const& _generator
function<void(CompilerContext&)> const& _generator
)
{
auto it = m_lowLevelFunctions.find(_name);
@ -173,10 +174,10 @@ void CompilerContext::appendMissingLowLevelFunctions()
{
while (!m_lowLevelFunctionGenerationQueue.empty())
{
std::string name;
string name;
unsigned inArgs;
unsigned outArgs;
std::function<void(CompilerContext&)> generator;
function<void(CompilerContext&)> generator;
tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front();
m_lowLevelFunctionGenerationQueue.pop();
@ -194,7 +195,7 @@ void CompilerContext::appendYulUtilityFunctions(OptimiserSettings const& _optimi
solAssert(!m_appendYulUtilityFunctionsRan, "requestedYulFunctions called more than once.");
m_appendYulUtilityFunctionsRan = true;
std::string code = m_yulFunctionCollector.requestedFunctions();
string code = m_yulFunctionCollector.requestedFunctions();
if (!code.empty())
{
appendInlineAssembly(
@ -232,7 +233,7 @@ void CompilerContext::removeVariable(Declaration const& _declaration)
void CompilerContext::removeVariablesAboveStackHeight(unsigned _stackHeight)
{
std::vector<Declaration const*> toRemove;
vector<Declaration const*> toRemove;
for (auto _var: m_localVariables)
{
solAssert(!_var.second.empty(), "");
@ -249,14 +250,14 @@ unsigned CompilerContext::numberOfLocalVariables() const
return static_cast<unsigned>(m_localVariables.size());
}
std::shared_ptr<evmasm::Assembly> CompilerContext::compiledContract(ContractDefinition const& _contract) const
shared_ptr<evmasm::Assembly> CompilerContext::compiledContract(ContractDefinition const& _contract) const
{
auto ret = m_otherCompilers.find(&_contract);
solAssert(ret != m_otherCompilers.end(), "Compiled contract not found.");
return ret->second->assemblyPtr();
}
std::shared_ptr<evmasm::Assembly> CompilerContext::compiledContractRuntime(ContractDefinition const& _contract) const
shared_ptr<evmasm::Assembly> CompilerContext::compiledContractRuntime(ContractDefinition const& _contract) const
{
auto ret = m_otherCompilers.find(&_contract);
solAssert(ret != m_otherCompilers.end(), "Compiled contract not found.");
@ -319,7 +320,7 @@ unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
return static_cast<unsigned>(m_asm->deposit()) - _offset - 1;
}
std::pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const
pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const
{
auto it = m_stateVariables.find(&_declaration);
solAssert(it != m_stateVariables.end(), "Variable not found in storage.");
@ -348,13 +349,13 @@ CompilerContext& CompilerContext::appendConditionalPanic(util::PanicCode _code)
return *this;
}
CompilerContext& CompilerContext::appendRevert(std::string const& _message)
CompilerContext& CompilerContext::appendRevert(string const& _message)
{
appendInlineAssembly("{ " + revertReasonIfDebug(_message) + " }");
return *this;
}
CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, std::string const& _message)
CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, string const& _message)
{
if (_forwardReturnData && m_evmVersion.supportsReturndata())
appendInlineAssembly(R"({
@ -371,24 +372,24 @@ CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnDat
void CompilerContext::resetVisitedNodes(ASTNode const* _node)
{
std::stack<ASTNode const*> newStack;
stack<ASTNode const*> newStack;
newStack.push(_node);
std::swap(m_visitedNodes, newStack);
updateSourceLocation();
}
void CompilerContext::appendInlineAssembly(
std::string const& _assembly,
std::vector<std::string> const& _localVariables,
std::set<std::string> const& _externallyUsedFunctions,
string const& _assembly,
vector<string> const& _localVariables,
set<string> const& _externallyUsedFunctions,
bool _system,
OptimiserSettings const& _optimiserSettings,
std::string _sourceName
string _sourceName
)
{
unsigned startStackHeight = stackHeight();
std::set<yul::YulString> externallyUsedIdentifiers;
set<yul::YulString> externallyUsedIdentifiers;
for (auto const& fun: _externallyUsedFunctions)
externallyUsedIdentifiers.insert(yul::YulString(fun));
for (auto const& var: _localVariables)
@ -437,19 +438,19 @@ void CompilerContext::appendInlineAssembly(
ErrorReporter errorReporter(errors);
langutil::CharStream charStream(_assembly, _sourceName);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
std::optional<langutil::SourceLocation> locationOverride;
optional<langutil::SourceLocation> locationOverride;
if (!_system)
locationOverride = m_asm->currentSourceLocation();
std::shared_ptr<yul::Block> parserResult =
shared_ptr<yul::Block> parserResult =
yul::Parser(errorReporter, dialect, std::move(locationOverride))
.parse(charStream);
#ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
#endif
auto reportError = [&](std::string const& _context)
auto reportError = [&](string const& _context)
{
std::string message =
string message =
"Error parsing/analyzing inline assembly block:\n" +
_context + "\n"
"------------------ Input: -----------------\n" +
@ -482,7 +483,7 @@ void CompilerContext::appendInlineAssembly(
{
yul::Object obj;
obj.code = parserResult;
obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(analysisInfo);
obj.analysisInfo = make_shared<yul::AsmAnalysisInfo>(analysisInfo);
solAssert(!dialect.providesObjectAccess());
optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers);
@ -492,7 +493,7 @@ void CompilerContext::appendInlineAssembly(
// Store as generated sources, but first re-parse to update the source references.
solAssert(m_generatedYulUtilityCode.empty(), "");
m_generatedYulUtilityCode = yul::AsmPrinter(dialect)(*obj.code);
std::string code = yul::AsmPrinter{dialect}(*obj.code);
string code = yul::AsmPrinter{dialect}(*obj.code);
langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName);
obj.code = yul::Parser(errorReporter, dialect).parse(charStream);
*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj);
@ -547,7 +548,7 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
_optimiserSettings.optimizeStackAllocation,
_optimiserSettings.yulOptimiserSteps,
_optimiserSettings.yulOptimiserCleanupSteps,
isCreation? std::nullopt : std::make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
_externalIdentifiers
);
@ -557,11 +558,11 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
#endif
}
std::string CompilerContext::revertReasonIfDebug(std::string const& _message)
string CompilerContext::revertReasonIfDebug(string const& _message)
{
return YulUtilFunctions::revertReasonIfDebugBody(
m_revertStrings,
"mload(" + std::to_string(CompilerUtils::freeMemoryPointer) + ")",
"mload(" + to_string(CompilerUtils::freeMemoryPointer) + ")",
_message
);
}
@ -589,14 +590,14 @@ evmasm::AssemblyItem CompilerContext::FunctionCompilationQueue::entryLabel(
}
// some name that cannot clash with yul function names.
std::string labelName = "@" + _declaration.name() + "_" + std::to_string(_declaration.id());
string labelName = "@" + _declaration.name() + "_" + to_string(_declaration.id());
evmasm::AssemblyItem tag = _context.namedTag(
labelName,
params,
returns,
_declaration.id()
);
m_entryLabels.insert(std::make_pair(&_declaration, tag));
m_entryLabels.insert(make_pair(&_declaration, tag));
m_functionsToCompile.push(&_declaration);
return tag.tag();
}

View File

@ -33,6 +33,7 @@
#include <libsolutil/Whiskers.h>
#include <libsolutil/StackTooDeepString.h>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::frontend;
@ -104,9 +105,9 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType)
}
void CompilerUtils::revertWithError(
std::string const& _signature,
std::vector<Type const*> const& _parameterTypes,
std::vector<Type const*> const& _argumentTypes
string const& _signature,
vector<Type const*> const& _parameterTypes,
vector<Type const*> const& _argumentTypes
)
{
fetchFreeMemoryPointer();
@ -214,7 +215,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
m_context << Instruction::DUP1;
storeStringData(bytesConstRef(str->value()));
if (_padToWordBoundaries)
m_context << u256(std::max<size_t>(32, ((str->value().size() + 31) / 32) * 32));
m_context << u256(max<size_t>(32, ((str->value().size() + 31) / 32) * 32));
else
m_context << u256(str->value().size());
m_context << Instruction::ADD;
@ -263,7 +264,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
Whiskers templ(R"({
if lt(len, <encodedSize>) { <revertString> }
})");
templ("encodedSize", std::to_string(encodedSize));
templ("encodedSize", to_string(encodedSize));
templ("revertString", m_context.revertReasonIfDebug("Calldata too short"));
m_context.appendInlineAssembly(templ.render(), {"len"});
@ -319,7 +320,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
mstore(dst, array_length)
dst := add(dst, 0x20)
})");
templ("item_size", std::to_string(arrayType.calldataStride()));
templ("item_size", to_string(arrayType.calldataStride()));
// TODO add test
templ("revertStringPointer", m_context.revertReasonIfDebug("ABI memory decoding: invalid data pointer"));
templ("revertStringStart", m_context.revertReasonIfDebug("ABI memory decoding: invalid data start"));
@ -373,7 +374,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
m_context.appendInlineAssembly(Whiskers(R"({
if or(
gt(array_length, 0x100000000),
gt(add(data_ptr, mul(array_length, )" + std::to_string(arrayType.calldataStride()) + R"()), input_end)
gt(add(data_ptr, mul(array_length, )" + to_string(arrayType.calldataStride()) + R"()), input_end)
) { <revertString> }
})")
("revertString", m_context.revertReasonIfDebug("ABI calldata decoding: invalid data pointer"))
@ -617,7 +618,7 @@ void CompilerUtils::abiEncodeV2(
// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
std::string encoderName =
string encoderName =
_padToWordBoundaries ?
m_context.abiFunctions().tupleEncoderReversed(_givenTypes, _targetTypes, _encodeAsLibraryTypes) :
m_context.abiFunctions().tupleEncoderPackedReversed(_givenTypes, _targetTypes);
@ -630,7 +631,7 @@ void CompilerUtils::abiDecodeV2(TypePointers const& _parameterTypes, bool _fromM
m_context << Instruction::DUP2 << Instruction::ADD;
m_context << Instruction::SWAP1;
// stack: <end> <start>
std::string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory);
string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory);
m_context.callYulFunction(decoderName, 2, sizeOnStack(_parameterTypes));
}
@ -645,7 +646,7 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
calldatacopy(memptr, calldatasize(), size)
memptr := add(memptr, size)
})");
templ("element_size", std::to_string(_type.memoryStride()));
templ("element_size", to_string(_type.memoryStride()));
m_context.appendInlineAssembly(templ.render(), {"length", "memptr"});
}
else
@ -841,7 +842,7 @@ void CompilerUtils::convertType(
m_context << Instruction::POP << u256(0);
else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded)
{
unsigned bytes = std::min(typeOnStack.numBytes(), targetType.numBytes());
unsigned bytes = min(typeOnStack.numBytes(), targetType.numBytes());
m_context << ((u256(1) << (256 - bytes * 8)) - 1);
m_context << Instruction::NOT << Instruction::AND;
}
@ -959,7 +960,7 @@ void CompilerUtils::convertType(
case Type::Category::StringLiteral:
{
auto const& literalType = dynamic_cast<StringLiteralType const&>(_typeOnStack);
std::string const& value = literalType.value();
string const& value = literalType.value();
bytesConstRef data(value);
if (targetTypeCategory == Type::Category::FixedBytes)
{
@ -1185,7 +1186,7 @@ void CompilerUtils::convertType(
for (auto const& member: typeOnStack->members(nullptr))
{
solAssert(!member.type->containsNestedMapping());
std::pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name);
pair<u256, unsigned> const& offsets = typeOnStack->storageOffsetsOfMember(member.name);
_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
_context << u256(offsets.second);
StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true);
@ -1267,7 +1268,7 @@ void CompilerUtils::convertType(
if (sourceSize > 0 || targetSize > 0)
{
// Move it back into its place.
for (unsigned j = 0; j < std::min(sourceSize, targetSize); ++j)
for (unsigned j = 0; j < min(sourceSize, targetSize); ++j)
m_context <<
swapInstruction(depth + targetSize - sourceSize) <<
Instruction::POP;
@ -1374,7 +1375,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
[type](CompilerContext& _context) {
CompilerUtils utils(_context);
utils.allocateMemory(std::max<u256>(32u, type->memoryDataSize()));
utils.allocateMemory(max<u256>(32u, type->memoryDataSize()));
_context << Instruction::DUP1;
if (auto structType = dynamic_cast<StructType const*>(type))
@ -1492,7 +1493,7 @@ void CompilerUtils::popAndJump(unsigned _toHeight, evmasm::AssemblyItem const& _
m_context.adjustStackOffset(static_cast<int>(amount));
}
unsigned CompilerUtils::sizeOnStack(std::vector<Type const*> const& _variableTypes)
unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
{
unsigned size = 0;
for (Type const* type: _variableTypes)
@ -1508,7 +1509,7 @@ void CompilerUtils::computeHashStatic()
void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, bool _creation)
{
std::string which = _creation ? "Creation" : "Runtime";
string which = _creation ? "Creation" : "Runtime";
m_context.callLowLevelFunction(
"$copyContract" + which + "CodeToMemory_" + contract.type()->identifier(),
1,
@ -1516,7 +1517,7 @@ void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract,
[&contract, _creation](CompilerContext& _context)
{
// copy the contract's code into memory
std::shared_ptr<evmasm::Assembly> assembly =
shared_ptr<evmasm::Assembly> assembly =
_creation ?
_context.compiledContract(contract) :
_context.compiledContractRuntime(contract);

View File

@ -55,6 +55,7 @@
#include <algorithm>
#include <limits>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::frontend;
@ -79,7 +80,7 @@ public:
{
solAssert(
m_context.stackHeight() == stackHeight,
std::string("I sense a disturbance in the stack: ") + std::to_string(m_context.stackHeight()) + " vs " + std::to_string(stackHeight)
std::string("I sense a disturbance in the stack: ") + to_string(m_context.stackHeight()) + " vs " + to_string(stackHeight)
);
}
private:
@ -91,7 +92,7 @@ private:
void ContractCompiler::compileContract(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers
map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
)
{
CompilerContext::LocationSetter locationSetter(m_context, _contract);
@ -110,7 +111,7 @@ void ContractCompiler::compileContract(
size_t ContractCompiler::compileConstructor(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers
std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
)
{
CompilerContext::LocationSetter locationSetter(m_context, _contract);
@ -125,7 +126,7 @@ size_t ContractCompiler::compileConstructor(
void ContractCompiler::initializeContext(
ContractDefinition const& _contract,
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers
map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
)
{
m_context.setUseABICoderV2(*_contract.sourceUnit().annotation().useABICoderV2);
@ -186,7 +187,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
CompilerContext::LocationSetter locationSetter(m_context, _contract);
m_context << deployRoutine;
solAssert(m_context.runtimeSub() != std::numeric_limits<size_t>::max(), "Runtime sub not registered");
solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered");
ContractType contractType(_contract);
auto const& immutables = contractType.immutableVariables();
@ -230,7 +231,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract)
CompilerContext::LocationSetter locationSetter(m_context, _contract);
solAssert(m_context.runtimeSub() != std::numeric_limits<size_t>::max(), "Runtime sub not registered");
solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered");
m_context.pushSubroutineSize(m_context.runtimeSub());
m_context.pushSubroutineOffset(m_context.runtimeSub());
// This code replaces the address added by appendDeployTimeAddress().
@ -323,8 +324,8 @@ void ContractCompiler::appendDelegatecallCheck()
}
void ContractCompiler::appendInternalSelector(
std::map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints,
std::vector<FixedHash<4>> const& _ids,
map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints,
vector<FixedHash<4>> const& _ids,
evmasm::AssemblyItem const& _notFoundTag,
size_t _runs
)
@ -368,11 +369,11 @@ void ContractCompiler::appendInternalSelector(
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT;
evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()};
// Here, we have funid >= pivot
std::vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()};
vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()};
appendInternalSelector(_entryPoints, larger, _notFoundTag, _runs);
m_context << lessTag;
// Here, we have funid < pivot
std::vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)};
vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)};
appendInternalSelector(_entryPoints, smaller, _notFoundTag, _runs);
}
else
@ -410,8 +411,8 @@ bool hasPayableFunctions(ContractDefinition const& _contract)
void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract)
{
std::map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
std::map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints;
map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints;
if (_contract.isLibrary())
{
@ -447,7 +448,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true, false);
// stack now is: <can-call-non-view-functions>? <funhash>
std::vector<FixedHash<4>> sortedIDs;
vector<FixedHash<4>> sortedIDs;
for (auto const& it: interfaceFunctions)
{
callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag());
@ -571,7 +572,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete
void ContractCompiler::registerStateVariables(ContractDefinition const& _contract)
{
for (auto const& var: ContractType(_contract).stateVariables())
m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var));
m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var));
}
void ContractCompiler::registerImmutableVariables(ContractDefinition const& _contract)
@ -644,7 +645,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
m_breakTags.clear();
m_continueTags.clear();
m_currentFunction = &_function;
m_modifierDepth = std::numeric_limits<unsigned>::max();
m_modifierDepth = numeric_limits<unsigned>::max();
m_scopeStackHeight.clear();
m_context.setModifierDepth(0);
@ -661,10 +662,10 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
unsigned const c_argumentsSize = CompilerUtils::sizeOnStack(_function.parameters());
unsigned const c_returnValuesSize = CompilerUtils::sizeOnStack(_function.returnParameters());
std::vector<int> stackLayout;
vector<int> stackLayout;
if (!_function.isConstructor() && !_function.isFallback())
stackLayout.push_back(static_cast<int>(c_returnValuesSize)); // target of return address
stackLayout += std::vector<int>(c_argumentsSize, -1); // discard all arguments
stackLayout += vector<int>(c_argumentsSize, -1); // discard all arguments
for (size_t i = 0; i < c_returnValuesSize; ++i)
stackLayout.push_back(static_cast<int>(i));
@ -683,7 +684,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
else
{
m_context << swapInstruction(static_cast<unsigned>(stackLayout.size()) - static_cast<unsigned>(stackLayout.back()) - 1u);
std::swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
}
for (size_t i = 0; i < stackLayout.size(); ++i)
if (stackLayout[i] != static_cast<int>(i))
@ -789,7 +790,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable);
if (!ref->second.suffix.empty())
{
std::string const& suffix = ref->second.suffix;
string const& suffix = ref->second.suffix;
if (variable->type()->dataStoredIn(DataLocation::Storage))
{
solAssert(suffix == "offset" || suffix == "slot", "");
@ -864,7 +865,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
// lvalue context
auto variable = dynamic_cast<VariableDeclaration const*>(decl);
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1;
std::string const& suffix = ref->second.suffix;
string const& suffix = ref->second.suffix;
if (variable->type()->dataStoredIn(DataLocation::Storage))
{
solAssert(
@ -927,7 +928,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get();
// Only used in the scope below, but required to live outside to keep the
// std::shared_ptr's alive
// shared_ptr's alive
yul::Object object = {};
// The optimiser cannot handle external references
@ -940,8 +941,8 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
solAssert(dialect, "");
// Create a modifiable copy of the code and analysis
object.code = std::make_shared<yul::Block>(yul::ASTCopier().translate(*code));
object.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
object.code = make_shared<yul::Block>(yul::ASTCopier().translate(*code));
object.analysisInfo = make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
m_context.optimizeYul(object, *dialect, m_optimiserSettings);
@ -988,10 +989,10 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
TryCatchClause const& successClause = *_tryStatement.clauses().front();
if (successClause.parameters())
{
std::vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type};
vector<Type const*> exprTypes{_tryStatement.externalCall().annotation().type};
if (auto tupleType = dynamic_cast<TupleType const*>(exprTypes.front()))
exprTypes = tupleType->components();
std::vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters();
vector<ASTPointer<VariableDeclaration>> const& params = successClause.parameters()->parameters();
solAssert(exprTypes.size() == params.size(), "");
for (size_t i = 0; i < exprTypes.size(); ++i)
solAssert(params[i] && exprTypes[i] && *params[i]->annotation().type == *exprTypes[i], "");
@ -1007,7 +1008,7 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
return false;
}
void ContractCompiler::handleCatch(std::vector<ASTPointer<TryCatchClause>> const& _catchClauses)
void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _catchClauses)
{
// Stack is empty.
ASTPointer<TryCatchClause> error{};
@ -1284,7 +1285,7 @@ bool ContractCompiler::visit(Return const& _return)
if (Expression const* expression = _return.expression())
{
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters =
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
_return.annotation().functionReturnParameters->parameters();
TypePointers types;
for (auto const& retVariable: returnParameters)
@ -1431,7 +1432,7 @@ void ContractCompiler::appendModifierOrFunctionCode()
solAssert(m_currentFunction, "");
unsigned stackSurplus = 0;
Block const* codeBlock = nullptr;
std::vector<VariableDeclaration const*> addedVariables;
vector<VariableDeclaration const*> addedVariables;
m_modifierDepth++;
m_context.setModifierDepth(m_modifierDepth);

View File

@ -43,6 +43,7 @@
#include <numeric>
#include <utility>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::frontend;
@ -241,7 +242,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
if (!arrayType->isByteArrayOrString())
continue;
std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
Type const* memberType = structType->memberType(names[i]);
StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true);
@ -369,7 +370,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
utils().allocateMemory(std::max(u256(32u), arrayType.memoryDataSize()));
utils().allocateMemory(max(u256(32u), arrayType.memoryDataSize()));
m_context << Instruction::DUP1;
for (auto const& component: _tuple.components())
@ -382,7 +383,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
}
else
{
std::vector<std::unique_ptr<LValue>> lvalues;
vector<unique_ptr<LValue>> lvalues;
for (auto const& component: _tuple.components())
if (component)
{
@ -394,13 +395,13 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
}
}
else if (_tuple.annotation().willBeWrittenTo)
lvalues.push_back(std::unique_ptr<LValue>());
lvalues.push_back(unique_ptr<LValue>());
if (_tuple.annotation().willBeWrittenTo)
{
if (_tuple.components().size() == 1)
m_currentLValue = std::move(lvalues[0]);
else
m_currentLValue = std::make_unique<TupleObject>(m_context, std::move(lvalues));
m_currentLValue = make_unique<TupleObject>(m_context, std::move(lvalues));
}
}
return false;
@ -523,7 +524,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
m_context << u256(0) << Instruction::SUB;
break;
default:
solAssert(false, "Invalid unary operator: " + std::string(TokenTraits::toString(_unaryOperation.getOperator())));
solAssert(false, "Invalid unary operator: " + string(TokenTraits::toString(_unaryOperation.getOperator())));
}
return false;
}
@ -658,14 +659,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
TypePointers parameterTypes = functionType->parameterTypes();
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
if (functionCallKind == FunctionCallKind::StructConstructorCall)
{
TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
utils().allocateMemory(std::max(u256(32u), structType.memoryDataSize()));
utils().allocateMemory(max(u256(32u), structType.memoryDataSize()));
m_context << Instruction::DUP1;
for (unsigned i = 0; i < arguments.size(); ++i)
@ -991,7 +992,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::Error:
{
_functionCall.expression().accept(*this);
std::vector<Type const*> argumentTypes;
vector<Type const*> argumentTypes;
for (ASTPointer<Expression const> const& arg: _functionCall.sortedArguments())
{
arg->accept(*this);
@ -1059,7 +1060,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::RIPEMD160:
{
_functionCall.expression().accept(*this);
static std::map<FunctionType::Kind, u256> const contractAddresses{
static map<FunctionType::Kind, u256> const contractAddresses{
{FunctionType::Kind::ECRecover, 1},
{FunctionType::Kind::SHA256, 2},
{FunctionType::Kind::RIPEMD160, 3}
@ -1150,8 +1151,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::BytesConcat:
{
_functionCall.expression().accept(*this);
std::vector<Type const*> argumentTypes;
std::vector<Type const*> targetTypes;
vector<Type const*> argumentTypes;
vector<Type const*> targetTypes;
for (auto const& argument: arguments)
{
argument->accept(*this);
@ -1415,7 +1416,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// stack: <memory pointer> <selector>
// load current memory, mask and combine the selector
std::string mask = formatNumber((u256(-1) >> 32));
string mask = formatNumber((u256(-1) >> 32));
m_context.appendInlineAssembly(R"({
let data_start := add(mem_ptr, 0x20)
let data := mload(data_start)
@ -1475,7 +1476,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
// Desired Stack: [salt], [gas], [value]
enum Option { Salt, Gas, Value };
std::vector<Option> presentOptions;
vector<Option> presentOptions;
FunctionType const& funType = dynamic_cast<FunctionType const&>(
*_functionCallOptions.expression().annotation().type
);
@ -1485,7 +1486,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
for (size_t i = 0; i < _functionCallOptions.options().size(); ++i)
{
std::string const& name = *_functionCallOptions.names()[i];
string const& name = *_functionCallOptions.names()[i];
Type const* requiredType = TypeProvider::uint256();
Option newOption;
if (name == "salt")
@ -1817,7 +1818,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
);
m_context << Instruction::EXTCODEHASH;
}
else if ((std::set<std::string>{"send", "transfer"}).count(member))
else if ((set<string>{"send", "transfer"}).count(member))
{
solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, "");
utils().convertType(
@ -1826,7 +1827,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
true
);
}
else if ((std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
utils().convertType(
*_memberAccess.expression().annotation().type,
*TypeProvider::address(),
@ -1909,7 +1910,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
Whiskers(R"({
mstore(start, sub(end, add(start, 0x20)))
mstore(<free>, and(add(end, 31), not(31)))
})")("free", std::to_string(CompilerUtils::freeMemoryPointer)).render(),
})")("free", to_string(CompilerUtils::freeMemoryPointer)).render(),
{"start", "end"}
);
m_context << Instruction::POP;
@ -1945,7 +1946,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
solAssert(false, "min/max not available for the given type.");
}
else if ((std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member))
else if ((set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member))
{
// no-op
}
@ -1960,7 +1961,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{
case DataLocation::Storage:
{
std::pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member);
pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member);
m_context << offsets.first << Instruction::ADD << u256(offsets.second);
setLValueToStorageItem(_memberAccess);
break;
@ -2453,7 +2454,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons
IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
if (m_context.arithmetic() == Arithmetic::Checked)
{
std::string functionName;
string functionName;
switch (_operator)
{
case Token::Add:
@ -2619,7 +2620,7 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons
void ExpressionCompiler::appendExternalFunctionCall(
FunctionType const& _functionType,
std::vector<ASTPointer<Expression const>> const& _arguments,
vector<ASTPointer<Expression const>> const& _arguments,
bool _tryCall
)
{

View File

@ -30,6 +30,7 @@
#include <libsolutil/StackTooDeepString.h>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::frontend;
@ -409,7 +410,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
if (sourceType.location() == DataLocation::Storage)
{
// stack layout: source_ref target_ref
std::pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name);
pair<u256, unsigned> const& offsets = sourceType.storageOffsetsOfMember(member.name);
m_context << offsets.first << Instruction::DUP3 << Instruction::ADD;
m_context << u256(offsets.second);
// stack: source_ref target_ref source_member_ref source_member_off
@ -426,7 +427,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
// stack layout: source_ref target_ref source_value...
}
unsigned stackSize = sourceMemberType->sizeOnStack();
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
m_context << dupInstruction(1 + stackSize) << offsets.first << Instruction::ADD;
m_context << u256(offsets.second);
// stack: source_ref target_ref target_off source_value... target_member_ref target_member_byte_off
@ -468,7 +469,7 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
Type const* memberType = member.type;
if (memberType->category() == Type::Category::Mapping)
continue;
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
m_context
<< offsets.first << Instruction::DUP3 << Instruction::ADD
<< u256(offsets.second);
@ -591,7 +592,7 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc
// We will assign from right to left to optimize stack layout.
for (size_t i = 0; i < m_lvalues.size(); ++i)
{
std::unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1];
unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1];
Type const* valType = valueTypes[valueTypes.size() - i - 1];
unsigned stackHeight = m_context.stackHeight();
solAssert(!valType == !lvalue, "");

View File

@ -26,43 +26,44 @@
#include <libsolutil/Whiskers.h>
#include <libsolutil/StringUtils.h>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::util;
std::string MultiUseYulFunctionCollector::requestedFunctions()
string MultiUseYulFunctionCollector::requestedFunctions()
{
std::string result = std::move(m_code);
string result = std::move(m_code);
m_code.clear();
m_requestedFunctions.clear();
return result;
}
std::string MultiUseYulFunctionCollector::createFunction(std::string const& _name, std::function<std::string()> const& _creator)
string MultiUseYulFunctionCollector::createFunction(string const& _name, function<string ()> const& _creator)
{
if (!m_requestedFunctions.count(_name))
{
m_requestedFunctions.insert(_name);
std::string fun = _creator();
string fun = _creator();
solAssert(!fun.empty(), "");
solAssert(fun.find("function " + _name + "(") != std::string::npos, "Function not properly named.");
solAssert(fun.find("function " + _name + "(") != string::npos, "Function not properly named.");
m_code += std::move(fun);
}
return _name;
}
std::string MultiUseYulFunctionCollector::createFunction(
std::string const& _name,
std::function<std::string(std::vector<std::string>&, std::vector<std::string>&)> const& _creator
string MultiUseYulFunctionCollector::createFunction(
string const& _name,
function<string(vector<string>&, vector<string>&)> const& _creator
)
{
solAssert(!_name.empty(), "");
if (!m_requestedFunctions.count(_name))
{
m_requestedFunctions.insert(_name);
std::vector<std::string> arguments;
std::vector<std::string> returnParameters;
std::string body = _creator(arguments, returnParameters);
vector<string> arguments;
vector<string> returnParameters;
string body = _creator(arguments, returnParameters);
solAssert(!body.empty(), "");
m_code += Whiskers(R"(

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@
#include <libyul/AsmPrinter.h>
using namespace std;
using namespace solidity::langutil;
using namespace solidity::frontend;
using namespace solidity::util;
@ -40,110 +41,110 @@ YulArity YulArity::fromType(FunctionType const& _functionType)
};
}
std::string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl)
string IRNames::externalFunctionABIWrapper(Declaration const& _functionOrVarDecl)
{
if (auto const* function = dynamic_cast<FunctionDefinition const*>(&_functionOrVarDecl))
solAssert(!function->isConstructor());
return "external_fun_" + _functionOrVarDecl.name() + "_" + std::to_string(_functionOrVarDecl.id());
return "external_fun_" + _functionOrVarDecl.name() + "_" + to_string(_functionOrVarDecl.id());
}
std::string IRNames::function(FunctionDefinition const& _function)
string IRNames::function(FunctionDefinition const& _function)
{
if (_function.isConstructor())
return constructor(*_function.annotation().contract);
return "fun_" + _function.name() + "_" + std::to_string(_function.id());
return "fun_" + _function.name() + "_" + to_string(_function.id());
}
std::string IRNames::function(VariableDeclaration const& _varDecl)
string IRNames::function(VariableDeclaration const& _varDecl)
{
return "getter_fun_" + _varDecl.name() + "_" + std::to_string(_varDecl.id());
return "getter_fun_" + _varDecl.name() + "_" + to_string(_varDecl.id());
}
std::string IRNames::modifierInvocation(ModifierInvocation const& _modifierInvocation)
string IRNames::modifierInvocation(ModifierInvocation const& _modifierInvocation)
{
// This uses the ID of the modifier invocation because it has to be unique
// for each invocation.
solAssert(!_modifierInvocation.name().path().empty(), "");
std::string const& modifierName = _modifierInvocation.name().path().back();
string const& modifierName = _modifierInvocation.name().path().back();
solAssert(!modifierName.empty(), "");
return "modifier_" + modifierName + "_" + std::to_string(_modifierInvocation.id());
return "modifier_" + modifierName + "_" + to_string(_modifierInvocation.id());
}
std::string IRNames::functionWithModifierInner(FunctionDefinition const& _function)
string IRNames::functionWithModifierInner(FunctionDefinition const& _function)
{
return "fun_" + _function.name() + "_" + std::to_string(_function.id()) + "_inner";
return "fun_" + _function.name() + "_" + to_string(_function.id()) + "_inner";
}
std::string IRNames::creationObject(ContractDefinition const& _contract)
string IRNames::creationObject(ContractDefinition const& _contract)
{
return _contract.name() + "_" + toString(_contract.id());
}
std::string IRNames::deployedObject(ContractDefinition const& _contract)
string IRNames::deployedObject(ContractDefinition const& _contract)
{
return _contract.name() + "_" + toString(_contract.id()) + "_deployed";
}
std::string IRNames::internalDispatch(YulArity const& _arity)
string IRNames::internalDispatch(YulArity const& _arity)
{
return "dispatch_internal"
"_in_" + std::to_string(_arity.in) +
"_out_" + std::to_string(_arity.out);
"_in_" + to_string(_arity.in) +
"_out_" + to_string(_arity.out);
}
std::string IRNames::constructor(ContractDefinition const& _contract)
string IRNames::constructor(ContractDefinition const& _contract)
{
return "constructor_" + _contract.name() + "_" + std::to_string(_contract.id());
return "constructor_" + _contract.name() + "_" + to_string(_contract.id());
}
std::string IRNames::libraryAddressImmutable()
string IRNames::libraryAddressImmutable()
{
return "library_deploy_address";
}
std::string IRNames::constantValueFunction(VariableDeclaration const& _constant)
string IRNames::constantValueFunction(VariableDeclaration const& _constant)
{
solAssert(_constant.isConstant(), "");
return "constant_" + _constant.name() + "_" + std::to_string(_constant.id());
return "constant_" + _constant.name() + "_" + to_string(_constant.id());
}
std::string IRNames::localVariable(VariableDeclaration const& _declaration)
string IRNames::localVariable(VariableDeclaration const& _declaration)
{
return "var_" + _declaration.name() + '_' + std::to_string(_declaration.id());
}
std::string IRNames::localVariable(Expression const& _expression)
string IRNames::localVariable(Expression const& _expression)
{
return "expr_" + std::to_string(_expression.id());
return "expr_" + to_string(_expression.id());
}
std::string IRNames::trySuccessConditionVariable(Expression const& _expression)
string IRNames::trySuccessConditionVariable(Expression const& _expression)
{
auto annotation = dynamic_cast<FunctionCallAnnotation const*>(&_expression.annotation());
solAssert(annotation, "");
solAssert(annotation->tryCall, "Parameter must be a FunctionCall with tryCall-annotation set.");
return "trySuccessCondition_" + std::to_string(_expression.id());
return "trySuccessCondition_" + to_string(_expression.id());
}
std::string IRNames::tupleComponent(size_t _i)
string IRNames::tupleComponent(size_t _i)
{
return "component_" + std::to_string(_i + 1);
return "component_" + to_string(_i + 1);
}
std::string IRNames::zeroValue(Type const& _type, std::string const& _variableName)
string IRNames::zeroValue(Type const& _type, string const& _variableName)
{
return "zero_" + _type.identifier() + _variableName;
}
std::string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context)
string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context)
{
solAssert(_location.sourceName, "");
_context.markSourceUsed(*_location.sourceName);
std::string debugInfo = AsmPrinter::formatSourceLocation(
string debugInfo = AsmPrinter::formatSourceLocation(
_location,
_context.sourceIndices(),
_context.debugInfoSelection(),
@ -153,7 +154,7 @@ std::string dispenseLocationComment(langutil::SourceLocation const& _location, I
return debugInfo.empty() ? "" : "/// " + debugInfo;
}
std::string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
{
return dispenseLocationComment(_node.location(), _context);
}

View File

@ -31,18 +31,18 @@
#include <libsolutil/StringUtils.h>
#include <range/v3/view/map.hpp>
#include <range/v3/algorithm/find.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
std::string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function)
string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function)
{
std::string name = IRNames::function(_function);
string name = IRNames::function(_function);
if (!m_functions.contains(name))
m_functionGenerationQueue.push_back(&_function);
m_functionGenerationQueue.insert(&_function);
return name;
}
@ -51,8 +51,8 @@ FunctionDefinition const* IRGenerationContext::dequeueFunctionForCodeGeneration(
{
solAssert(!m_functionGenerationQueue.empty(), "");
FunctionDefinition const* result = m_functionGenerationQueue.front();
m_functionGenerationQueue.pop_front();
FunctionDefinition const* result = *m_functionGenerationQueue.begin();
m_functionGenerationQueue.erase(m_functionGenerationQueue.begin());
return result;
}
@ -121,19 +121,19 @@ void IRGenerationContext::addStateVariable(
unsigned _byteOffset
)
{
m_stateVariables[&_declaration] = std::make_pair(std::move(_storageOffset), _byteOffset);
m_stateVariables[&_declaration] = make_pair(std::move(_storageOffset), _byteOffset);
}
std::string IRGenerationContext::newYulVariable()
string IRGenerationContext::newYulVariable()
{
return "_" + std::to_string(++m_varCounter);
return "_" + to_string(++m_varCounter);
}
void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _internalDispatch)
{
solAssert(internalDispatchClean(), "");
for (DispatchQueue const& functions: _internalDispatch | ranges::views::values)
for (DispatchSet const& functions: _internalDispatch | ranges::views::values)
for (auto function: functions)
enqueueFunctionForCodeGeneration(*function);
@ -150,15 +150,16 @@ InternalDispatchMap IRGenerationContext::consumeInternalDispatchMap()
void IRGenerationContext::addToInternalDispatch(FunctionDefinition const& _function)
{
FunctionType const* functionType = TypeProvider::function(_function, FunctionType::Kind::Internal);
solAssert(functionType);
solAssert(functionType, "");
YulArity arity = YulArity::fromType(*functionType);
DispatchQueue& dispatchQueue = m_internalDispatchMap[arity];
if (ranges::find(dispatchQueue, &_function) == ranges::end(dispatchQueue))
{
dispatchQueue.push_back(&_function);
if (m_internalDispatchMap.count(arity) != 0 && m_internalDispatchMap[arity].count(&_function) != 0)
// Note that m_internalDispatchMap[arity] is a set with a custom comparator, which looks at function IDs not definitions
solAssert(*m_internalDispatchMap[arity].find(&_function) == &_function, "Different definitions with the same function ID");
m_internalDispatchMap[arity].insert(&_function);
enqueueFunctionForCodeGeneration(_function);
}
}

View File

@ -37,6 +37,7 @@
#include <set>
#include <string>
#include <memory>
#include <vector>
namespace solidity::frontend
{
@ -44,8 +45,20 @@ namespace solidity::frontend
class YulUtilFunctions;
class ABIFunctions;
using DispatchQueue = std::deque<FunctionDefinition const*>;
using InternalDispatchMap = std::map<YulArity, DispatchQueue>;
struct AscendingFunctionIDCompare
{
bool operator()(FunctionDefinition const* _f1, FunctionDefinition const* _f2) const
{
// NULLs always first.
if (_f1 != nullptr && _f2 != nullptr)
return _f1->id() < _f2->id();
else
return _f1 == nullptr;
}
};
using DispatchSet = std::set<FunctionDefinition const*, AscendingFunctionIDCompare>;
using InternalDispatchMap = std::map<YulArity, DispatchSet>;
/**
* Class that contains contextual information during IR generation.
@ -184,9 +197,10 @@ private:
/// were discovered by the IR generator during AST traversal.
/// Note that the queue gets filled in a lazy way - new definitions can be added while the
/// collected ones get removed and traversed.
/// The order and duplicates are relevant here
/// (see: IRGenerationContext::[enqueue|dequeue]FunctionForCodeGeneration)
DispatchQueue m_functionGenerationQueue;
/// The order and duplicates are irrelevant here (hence std::set rather than std::queue) as
/// long as the order of Yul functions in the generated code is deterministic and the same on
/// all platforms - which is a property guaranteed by MultiUseYulFunctionCollector.
DispatchSet m_functionGenerationQueue;
/// Collection of functions that need to be callable via internal dispatch.
/// Note that having a key with an empty set of functions is a valid situation. It means that

View File

@ -38,23 +38,25 @@
#include <libsolutil/StringUtils.h>
#include <libsolutil/Whiskers.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <json/json.h>
#include <sstream>
#include <variant>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::langutil;
using namespace solidity::util;
using namespace std::string_literals;
namespace
{
void verifyCallGraph(
std::set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables,
std::set<FunctionDefinition const*> _generatedFunctions
set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables,
set<FunctionDefinition const*> _generatedFunctions
)
{
for (auto const& expectedCallable: _expectedCallables)
@ -73,47 +75,47 @@ void verifyCallGraph(
);
}
std::set<CallableDeclaration const*, ASTNode::CompareByID> collectReachableCallables(
set<CallableDeclaration const*, ASTNode::CompareByID> collectReachableCallables(
CallGraph const& _graph
)
{
std::set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables;
set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables;
for (CallGraph::Node const& reachableNode: _graph.edges | ranges::views::keys)
if (std::holds_alternative<CallableDeclaration const*>(reachableNode))
reachableCallables.emplace(std::get<CallableDeclaration const*>(reachableNode));
if (holds_alternative<CallableDeclaration const*>(reachableNode))
reachableCallables.emplace(get<CallableDeclaration const*>(reachableNode));
return reachableCallables;
}
}
std::string IRGenerator::run(
string IRGenerator::run(
ContractDefinition const& _contract,
bytes const& _cborMetadata,
std::map<ContractDefinition const*, std::string_view const> const& _otherYulSources
map<ContractDefinition const*, string_view const> const& _otherYulSources
)
{
return yul::reindent(generate(_contract, _cborMetadata, _otherYulSources));
}
std::string IRGenerator::generate(
string IRGenerator::generate(
ContractDefinition const& _contract,
bytes const& _cborMetadata,
std::map<ContractDefinition const*, std::string_view const> const& _otherYulSources
map<ContractDefinition const*, string_view const> const& _otherYulSources
)
{
auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> std::string
auto subObjectSources = [&_otherYulSources](std::set<ContractDefinition const*, ASTNode::CompareByID> const& subObjects) -> string
{
std::string subObjectsSources;
for (ContractDefinition const* subObject: subObjects)
subObjectsSources += _otherYulSources.at(subObject);
return subObjectsSources;
};
auto formatUseSrcMap = [](IRGenerationContext const& _context) -> std::string
auto formatUseSrcMap = [](IRGenerationContext const& _context) -> string
{
return joinHumanReadable(
ranges::views::transform(_context.usedSourceNames(), [_context](std::string const& _sourceName) {
return std::to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName);
ranges::views::transform(_context.usedSourceNames(), [_context](string const& _sourceName) {
return to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName);
}),
", "
);
@ -162,7 +164,7 @@ std::string IRGenerator::generate(
FunctionDefinition const* constructor = _contract.constructor();
t("callValueCheck", !constructor || !constructor->isPayable() ? callValueCheck() : "");
std::vector<std::string> constructorParams;
vector<string> constructorParams;
if (constructor && !constructor->parameters().empty())
{
for (size_t i = 0; i < CompilerUtils::sizeOnStack(constructor->parameters()); ++i)
@ -178,7 +180,7 @@ std::string IRGenerator::generate(
t("deploy", deployCode(_contract));
generateConstructors(_contract);
std::set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract);
t("functions", m_context.functionCollector().requestedFunctions());
@ -201,7 +203,7 @@ std::string IRGenerator::generate(
t("sourceLocationCommentDeployed", dispenseLocationComment(_contract));
t("library_address", IRNames::libraryAddressImmutable());
t("dispatch", dispatchRoutine(_contract));
std::set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
generateInternalDispatchFunctions(_contract);
t("deployedFunctions", m_context.functionCollector().requestedFunctions());
t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated()));
@ -222,16 +224,16 @@ std::string IRGenerator::generate(
return t.render();
}
std::string IRGenerator::generate(Block const& _block)
string IRGenerator::generate(Block const& _block)
{
IRGeneratorForStatements generator(m_context, m_utils);
generator.generate(_block);
return generator.code();
}
std::set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions()
set<FunctionDefinition const*> IRGenerator::generateQueuedFunctions()
{
std::set<FunctionDefinition const*> functions;
set<FunctionDefinition const*> functions;
while (!m_context.functionGenerationQueueEmpty())
{
@ -256,7 +258,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
InternalDispatchMap internalDispatchMap = m_context.consumeInternalDispatchMap();
for (YulArity const& arity: internalDispatchMap | ranges::views::keys)
{
std::string funName = IRNames::internalDispatch(arity);
string funName = IRNames::internalDispatch(arity);
m_context.functionCollector().createFunction(funName, [&]() {
Whiskers templ(R"(
<sourceLocationComment>
@ -278,8 +280,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
templ("in", suffixedVariableNameList("in_", 0, arity.in));
templ("out", suffixedVariableNameList("out_", 0, arity.out));
std::vector<std::map<std::string, std::string>> cases;
std::set<int64_t> caseValues;
vector<map<string, string>> cases;
for (FunctionDefinition const* function: internalDispatchMap.at(arity))
{
solAssert(function, "");
@ -290,14 +291,12 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
solAssert(!function->isConstructor(), "");
// 0 is reserved for uninitialized function pointers
solAssert(function->id() != 0, "Unexpected function ID: 0");
solAssert(caseValues.count(function->id()) == 0, "Duplicate function ID");
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
cases.emplace_back(std::map<std::string, std::string>{
{"funID", std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
cases.emplace_back(map<string, string>{
{"funID", to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
{"name", IRNames::function(*function)}
});
caseValues.insert(function->id());
}
templ("cases", std::move(cases));
@ -314,9 +313,9 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
return internalDispatchMap;
}
std::string IRGenerator::generateFunction(FunctionDefinition const& _function)
string IRGenerator::generateFunction(FunctionDefinition const& _function)
{
std::string functionName = IRNames::function(_function);
string functionName = IRNames::function(_function);
return m_context.functionCollector().createFunction(functionName, [&]() {
m_context.resetLocalVariables();
Whiskers t(R"(
@ -329,7 +328,7 @@ std::string IRGenerator::generateFunction(FunctionDefinition const& _function)
)");
if (m_context.debugInfoSelection().astID)
t("astIDComment", "/// @ast-id " + std::to_string(_function.id()) + "\n");
t("astIDComment", "/// @ast-id " + to_string(_function.id()) + "\n");
else
t("astIDComment", "");
t("sourceLocationComment", dispenseLocationComment(_function));
@ -339,12 +338,12 @@ std::string IRGenerator::generateFunction(FunctionDefinition const& _function)
);
t("functionName", functionName);
std::vector<std::string> params;
vector<string> params;
for (auto const& varDecl: _function.parameters())
params += m_context.addLocalVariable(*varDecl).stackSlots();
t("params", joinHumanReadable(params));
std::vector<std::string> retParams;
std::string retInit;
vector<string> retParams;
string retInit;
for (auto const& varDecl: _function.returnParameters())
{
retParams += m_context.addLocalVariable(*varDecl).stackSlots();
@ -361,14 +360,14 @@ std::string IRGenerator::generateFunction(FunctionDefinition const& _function)
for (size_t i = 0; i < _function.modifiers().size(); ++i)
{
ModifierInvocation const& modifier = *_function.modifiers().at(i);
std::string next =
string next =
i + 1 < _function.modifiers().size() ?
IRNames::modifierInvocation(*_function.modifiers().at(i + 1)) :
IRNames::functionWithModifierInner(_function);
generateModifier(modifier, _function, next);
}
t("body",
(retParams.empty() ? std::string{} : joinHumanReadable(retParams) + " := ") +
(retParams.empty() ? string{} : joinHumanReadable(retParams) + " := ") +
IRNames::modifierInvocation(*_function.modifiers().at(0)) +
"(" +
joinHumanReadable(retParams + params) +
@ -381,13 +380,13 @@ std::string IRGenerator::generateFunction(FunctionDefinition const& _function)
});
}
std::string IRGenerator::generateModifier(
string IRGenerator::generateModifier(
ModifierInvocation const& _modifierInvocation,
FunctionDefinition const& _function,
std::string const& _nextFunction
string const& _nextFunction
)
{
std::string functionName = IRNames::modifierInvocation(_modifierInvocation);
string functionName = IRNames::modifierInvocation(_modifierInvocation);
return m_context.functionCollector().createFunction(functionName, [&]() {
m_context.resetLocalVariables();
Whiskers t(R"(
@ -401,15 +400,15 @@ std::string IRGenerator::generateModifier(
)");
t("functionName", functionName);
std::vector<std::string> retParamsIn;
vector<string> retParamsIn;
for (auto const& varDecl: _function.returnParameters())
retParamsIn += m_context.addLocalVariable(*varDecl).stackSlots();
std::vector<std::string> params = retParamsIn;
vector<string> params = retParamsIn;
for (auto const& varDecl: _function.parameters())
params += m_context.addLocalVariable(*varDecl).stackSlots();
t("params", joinHumanReadable(params));
std::vector<std::string> retParams;
std::string assignRetParams;
vector<string> retParams;
string assignRetParams;
for (size_t i = 0; i < retParamsIn.size(); ++i)
{
retParams.emplace_back(m_context.newYulVariable());
@ -424,7 +423,7 @@ std::string IRGenerator::generateModifier(
solAssert(modifier, "");
if (m_context.debugInfoSelection().astID)
t("astIDComment", "/// @ast-id " + std::to_string(modifier->id()) + "\n");
t("astIDComment", "/// @ast-id " + to_string(modifier->id()) + "\n");
else
t("astIDComment", "");
t("sourceLocationComment", dispenseLocationComment(*modifier));
@ -466,7 +465,7 @@ std::string IRGenerator::generateModifier(
t("evalArgs", expressionEvaluator.code());
IRGeneratorForStatements generator(m_context, m_utils, [&]() {
std::string ret = joinHumanReadable(retParams);
string ret = joinHumanReadable(retParams);
return
(ret.empty() ? "" : ret + " := ") +
_nextFunction + "(" + joinHumanReadable(params) + ")\n";
@ -477,9 +476,9 @@ std::string IRGenerator::generateModifier(
});
}
std::string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& _function)
string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& _function)
{
std::string functionName = IRNames::functionWithModifierInner(_function);
string functionName = IRNames::functionWithModifierInner(_function);
return m_context.functionCollector().createFunction(functionName, [&]() {
m_context.resetLocalVariables();
Whiskers t(R"(
@ -496,17 +495,17 @@ std::string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition co
dispenseLocationComment(m_context.mostDerivedContract())
);
t("functionName", functionName);
std::vector<std::string> retParams;
std::vector<std::string> retParamsIn;
vector<string> retParams;
vector<string> retParamsIn;
for (auto const& varDecl: _function.returnParameters())
retParams += m_context.addLocalVariable(*varDecl).stackSlots();
std::string assignRetParams;
string assignRetParams;
for (size_t i = 0; i < retParams.size(); ++i)
{
retParamsIn.emplace_back(m_context.newYulVariable());
assignRetParams += retParams.at(i) + " := " + retParamsIn.at(i) + "\n";
}
std::vector<std::string> params = retParamsIn;
vector<string> params = retParamsIn;
for (auto const& varDecl: _function.parameters())
params += m_context.addLocalVariable(*varDecl).stackSlots();
t("params", joinHumanReadable(params));
@ -517,9 +516,9 @@ std::string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition co
});
}
std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
{
std::string functionName = IRNames::function(_varDecl);
string functionName = IRNames::function(_varDecl);
return m_context.functionCollector().createFunction(functionName, [&]() {
Type const* type = _varDecl.annotation().type;
@ -541,7 +540,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
(
"astIDComment",
m_context.debugInfoSelection().astID ?
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
""
)
("sourceLocationComment", dispenseLocationComment(_varDecl))
@ -550,7 +549,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
dispenseLocationComment(m_context.mostDerivedContract())
)
("functionName", functionName)
("id", std::to_string(_varDecl.id()))
("id", to_string(_varDecl.id()))
.render();
}
else if (_varDecl.isConstant())
@ -566,7 +565,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
(
"astIDComment",
m_context.debugInfoSelection().astID ?
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
""
)
("sourceLocationComment", dispenseLocationComment(_varDecl))
@ -580,7 +579,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
.render();
}
std::string code;
string code;
auto const& location = m_context.storageLocationOfStateVariable(_varDecl);
code += Whiskers(R"(
@ -588,7 +587,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
let offset := <offset>
)")
("slot", location.first.str())
("offset", std::to_string(location.second))
("offset", to_string(location.second))
.render();
if (!paramTypes.empty())
@ -604,8 +603,8 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
// The initial value of @a currentType is only used if we skip the loop completely.
Type const* currentType = _varDecl.annotation().type;
std::vector<std::string> parameters;
std::vector<std::string> returnVariables;
vector<string> parameters;
vector<string> returnVariables;
for (size_t i = 0; i < paramTypes.size(); ++i)
{
@ -613,7 +612,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(currentType);
solAssert(mappingType || arrayType, "");
std::vector<std::string> keys = IRVariable("key_" + std::to_string(i),
vector<string> keys = IRVariable("key_" + to_string(i),
mappingType ? *mappingType->keyType() : *TypeProvider::uint256()
).stackSlots();
parameters += keys;
@ -656,8 +655,8 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
)
continue;
std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
std::vector<std::string> retVars = IRVariable("ret_" + std::to_string(returnVariables.size()), *returnTypes[i]).stackSlots();
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
vector<string> retVars = IRVariable("ret_" + to_string(returnVariables.size()), *returnTypes[i]).stackSlots();
returnVariables += retVars;
code += Whiskers(R"(
<ret> := <readStorage>(add(slot, <slotOffset>))
@ -674,7 +673,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front());
if (arrayType)
solAssert(arrayType->isByteArrayOrString(), "");
std::vector<std::string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
returnVariables += retVars;
code += Whiskers(R"(
<ret> := <readStorage>(slot, offset)
@ -698,7 +697,7 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
(
"astIDComment",
m_context.debugInfoSelection().astID ?
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
""
)
("sourceLocationComment", dispenseLocationComment(_varDecl))
@ -710,10 +709,10 @@ std::string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
});
}
std::string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType)
string IRGenerator::generateExternalFunction(ContractDefinition const& _contract, FunctionType const& _functionType)
{
std::string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
return m_context.functionCollector().createFunction(functionName, [&](std::vector<std::string>&, std::vector<std::string>&) -> std::string {
string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
return m_context.functionCollector().createFunction(functionName, [&](vector<string>&, vector<string>&) -> string {
Whiskers t(R"X(
<callValueCheck>
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
@ -724,8 +723,8 @@ std::string IRGenerator::generateExternalFunction(ContractDefinition const& _con
)X");
t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck());
unsigned paramVars = std::make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
unsigned retVars = std::make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
unsigned paramVars = make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
unsigned retVars = make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
t("abiDecode", abiFunctions.tupleDecoder(_functionType.parameterTypes()));
@ -748,14 +747,14 @@ std::string IRGenerator::generateExternalFunction(ContractDefinition const& _con
});
}
std::string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
string IRGenerator::generateInitialAssignment(VariableDeclaration const& _varDecl)
{
IRGeneratorForStatements generator(m_context, m_utils);
generator.initializeLocalVar(_varDecl);
return generator.code();
}
std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>> IRGenerator::evaluateConstructorArguments(
pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evaluateConstructorArguments(
ContractDefinition const& _contract
)
{
@ -768,12 +767,12 @@ std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::stri
auto it2 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c2);
return it1 < it2;
}
std::vector<ContractDefinition const*> const& linearizedBaseContracts;
vector<ContractDefinition const*> const& linearizedBaseContracts;
} inheritanceOrder{_contract.annotation().linearizedBaseContracts};
std::map<ContractDefinition const*, std::vector<std::string>> constructorParams;
map<ContractDefinition const*, vector<string>> constructorParams;
std::map<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *, InheritanceOrder>
map<ContractDefinition const*, std::vector<ASTPointer<Expression>>const *, InheritanceOrder>
baseConstructorArguments(inheritanceOrder);
for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts())
@ -805,7 +804,7 @@ std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::stri
solAssert(baseContract && arguments, "");
if (baseContract->constructor() && !arguments->empty())
{
std::vector<std::string> params;
vector<string> params;
for (size_t i = 0; i < arguments->size(); ++i)
params += generator.evaluateExpression(
*(arguments->at(i)),
@ -818,7 +817,7 @@ std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::stri
return {generator.code(), constructorParams};
}
std::string IRGenerator::initStateVariables(ContractDefinition const& _contract)
string IRGenerator::initStateVariables(ContractDefinition const& _contract)
{
IRGeneratorForStatements generator{m_context, m_utils};
for (VariableDeclaration const* variable: _contract.stateVariables())
@ -832,16 +831,16 @@ std::string IRGenerator::initStateVariables(ContractDefinition const& _contract)
void IRGenerator::generateConstructors(ContractDefinition const& _contract)
{
auto listAllParams =
[&](std::map<ContractDefinition const*, std::vector<std::string>> const& baseParams) -> std::vector<std::string>
[&](map<ContractDefinition const*, vector<string>> const& baseParams) -> vector<string>
{
std::vector<std::string> params;
vector<string> params;
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
if (baseParams.count(contract))
params += baseParams.at(contract);
return params;
};
std::map<ContractDefinition const*, std::vector<std::string>> baseConstructorParams;
map<ContractDefinition const*, vector<string>> baseConstructorParams;
for (size_t i = 0; i < _contract.annotation().linearizedBaseContracts.size(); ++i)
{
ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i];
@ -860,13 +859,13 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
}
<contractSourceLocationComment>
)");
std::vector<std::string> params;
vector<string> params;
if (contract->constructor())
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
params += m_context.addLocalVariable(*varDecl).stackSlots();
if (m_context.debugInfoSelection().astID && contract->constructor())
t("astIDComment", "/// @ast-id " + std::to_string(contract->constructor()->id()) + "\n");
t("astIDComment", "/// @ast-id " + to_string(contract->constructor()->id()) + "\n");
else
t("astIDComment", "");
t("sourceLocationComment", dispenseLocationComment(
@ -880,11 +879,11 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
);
t("params", joinHumanReadable(params));
std::vector<std::string> baseParams = listAllParams(baseConstructorParams);
vector<string> baseParams = listAllParams(baseConstructorParams);
t("baseParams", joinHumanReadable(baseParams));
t("comma", !params.empty() && !baseParams.empty() ? ", " : "");
t("functionName", IRNames::constructor(*contract));
std::pair<std::string, std::map<ContractDefinition const*, std::vector<std::string>>> evaluatedArgs = evaluateConstructorArguments(*contract);
pair<string, map<ContractDefinition const*, vector<string>>> evaluatedArgs = evaluateConstructorArguments(*contract);
baseConstructorParams.insert(evaluatedArgs.second.begin(), evaluatedArgs.second.end());
t("evalBaseArguments", evaluatedArgs.first);
if (i < _contract.annotation().linearizedBaseContracts.size() - 1)
@ -897,10 +896,10 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
else
t("hasNextConstructor", false);
t("initStateVariables", initStateVariables(*contract));
std::string body;
string body;
if (FunctionDefinition const* constructor = contract->constructor())
{
std::vector<ModifierInvocation*> realModifiers;
vector<ModifierInvocation*> realModifiers;
for (auto const& modifierInvocation: constructor->modifiers())
// Filter out the base constructor calls
if (dynamic_cast<ModifierDefinition const*>(modifierInvocation->name().annotation().referencedDeclaration))
@ -912,7 +911,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
for (size_t i = 0; i < realModifiers.size(); ++i)
{
ModifierInvocation const& modifier = *realModifiers.at(i);
std::string next =
string next =
i + 1 < realModifiers.size() ?
IRNames::modifierInvocation(*realModifiers.at(i + 1)) :
IRNames::functionWithModifierInner(*constructor);
@ -934,7 +933,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
}
}
std::string IRGenerator::deployCode(ContractDefinition const& _contract)
string IRGenerator::deployCode(ContractDefinition const& _contract)
{
Whiskers t(R"X(
let <codeOffset> := <allocateUnbounded>()
@ -948,11 +947,11 @@ std::string IRGenerator::deployCode(ContractDefinition const& _contract)
t("codeOffset", m_context.newYulVariable());
t("object", IRNames::deployedObject(_contract));
std::vector<std::map<std::string, std::string>> immutables;
vector<map<string, string>> immutables;
if (_contract.isLibrary())
{
solAssert(ContractType(_contract).immutableVariables().empty(), "");
immutables.emplace_back(std::map<std::string, std::string>{
immutables.emplace_back(map<string, string>{
{"immutableName"s, IRNames::libraryAddressImmutable()},
{"value"s, "address()"}
});
@ -963,21 +962,21 @@ std::string IRGenerator::deployCode(ContractDefinition const& _contract)
{
solUnimplementedAssert(immutable->type()->isValueType());
solUnimplementedAssert(immutable->type()->sizeOnStack() == 1);
immutables.emplace_back(std::map<std::string, std::string>{
{"immutableName"s, std::to_string(immutable->id())},
{"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"}
immutables.emplace_back(map<string, string>{
{"immutableName"s, to_string(immutable->id())},
{"value"s, "mload(" + to_string(m_context.immutableMemoryOffset(*immutable)) + ")"}
});
}
t("immutables", std::move(immutables));
return t.render();
}
std::string IRGenerator::callValueCheck()
string IRGenerator::callValueCheck()
{
return "if callvalue() { " + m_utils.revertReasonIfDebugFunction("Ether sent to non-payable function") + "() }";
}
std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
{
Whiskers t(R"X(
<?+cases>if iszero(lt(calldatasize(), 4))
@ -998,15 +997,15 @@ std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
<fallback>
)X");
t("shr224", m_utils.shiftRightFunction(224));
std::vector<std::map<std::string, std::string>> functions;
vector<map<string, string>> functions;
for (auto const& function: _contract.interfaceFunctions())
{
functions.emplace_back();
std::map<std::string, std::string>& templ = functions.back();
map<string, string>& templ = functions.back();
templ["functionSelector"] = "0x" + function.first.hex();
FunctionTypePointer const& type = function.second;
templ["functionName"] = type->externalSignature();
std::string delegatecallCheck;
string delegatecallCheck;
if (_contract.isLibrary())
{
solAssert(!type->isPayable(), "");
@ -1034,7 +1033,7 @@ std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
if (FunctionDefinition const* fallback = _contract.fallbackFunction())
{
solAssert(!_contract.isLibrary(), "");
std::string fallbackCode;
string fallbackCode;
if (!fallback->isPayable())
fallbackCode += callValueCheck() + "\n";
if (fallback->parameters().empty())
@ -1058,7 +1057,7 @@ std::string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
return t.render();
}
std::string IRGenerator::memoryInit(bool _useMemoryGuard)
string IRGenerator::memoryInit(bool _useMemoryGuard)
{
// This function should be called at the beginning of the EVM call frame
// and thus can assume all memory to be zero, including the contents of
@ -1069,10 +1068,10 @@ std::string IRGenerator::memoryInit(bool _useMemoryGuard)
"mstore(<memPtr>, memoryguard(<freeMemoryStart>))" :
"mstore(<memPtr>, <freeMemoryStart>)"
}
("memPtr", std::to_string(CompilerUtils::freeMemoryPointer))
("memPtr", to_string(CompilerUtils::freeMemoryPointer))
(
"freeMemoryStart",
std::to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory())
to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory())
).render();
}
@ -1102,10 +1101,10 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon
m_context.setMostDerivedContract(_contract);
for (auto const& var: ContractType(_contract).stateVariables())
m_context.addStateVariable(*std::get<0>(var), std::get<1>(var), std::get<2>(var));
m_context.addStateVariable(*get<0>(var), get<1>(var), get<2>(var));
}
std::string IRGenerator::dispenseLocationComment(ASTNode const& _node)
string IRGenerator::dispenseLocationComment(ASTNode const& _node)
{
return ::dispenseLocationComment(_node, m_context);
}

View File

@ -49,6 +49,7 @@
#include <range/v3/view/transform.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
@ -94,8 +95,8 @@ struct CopyTranslate: public yul::ASTCopier
return ASTCopier::translate(_identifier);
yul::Expression translated = translateReference(_identifier);
solAssert(std::holds_alternative<yul::Identifier>(translated));
return std::get<yul::Identifier>(std::move(translated));
solAssert(holds_alternative<yul::Identifier>(translated));
return get<yul::Identifier>(std::move(translated));
}
private:
@ -108,9 +109,9 @@ private:
auto const& reference = m_references.at(&_identifier);
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
solUnimplementedAssert(varDecl);
std::string const& suffix = reference.suffix;
string const& suffix = reference.suffix;
std::string value;
string value;
if (suffix.empty() && varDecl->isLocalVariable())
{
auto const& var = m_context.localVariable(*varDecl);
@ -164,7 +165,7 @@ private:
if (suffix == "slot")
value = m_context.storageLocationOfStateVariable(*varDecl).first.str();
else if (suffix == "offset")
value = std::to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
value = to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
else
solAssert(false);
}
@ -215,7 +216,7 @@ private:
}
std::string IRGeneratorForStatementsBase::code() const
string IRGeneratorForStatementsBase::code() const
{
return m_code.str();
}
@ -239,7 +240,7 @@ void IRGeneratorForStatementsBase::setLocation(ASTNode const& _node)
m_currentLocation = _node.location();
}
std::string IRGeneratorForStatements::code() const
string IRGeneratorForStatements::code() const
{
solAssert(!m_currentLValue, "LValue not reset!");
return IRGeneratorForStatementsBase::code();
@ -337,11 +338,11 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre
}
}
std::string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant)
string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const& _constant)
{
try
{
std::string functionName = IRNames::constantValueFunction(_constant);
string functionName = IRNames::constantValueFunction(_constant);
return m_context.functionCollector().createFunction(functionName, [&] {
Whiskers templ(R"(
<sourceLocationComment>
@ -409,7 +410,7 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional)
setLocation(_conditional);
std::string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
declare(_conditional);
appendCode() << "switch " << condition << "\n" "case 0 {\n";
@ -500,7 +501,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
_tuple.components().size() <<
")\n";
std::string mpos = IRVariable(_tuple).part("mpos").name();
string mpos = IRVariable(_tuple).part("mpos").name();
Type const& baseType = *arrayType.baseType();
for (size_t i = 0; i < _tuple.components().size(); i++)
{
@ -511,7 +512,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
appendCode() <<
m_utils.writeToMemoryFunction(baseType) <<
"(" <<
("add(" + mpos + ", " + std::to_string(i * arrayType.memoryStride()) + ")") <<
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
", " <<
converted.commaSeparatedList() <<
")\n";
@ -534,7 +535,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
}
else
{
std::vector<std::optional<IRLValue>> lvalues;
vector<optional<IRLValue>> lvalues;
for (size_t i = 0; i < _tuple.components().size(); ++i)
if (auto const& component = _tuple.components()[i])
{
@ -585,7 +586,7 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement)
{
_ifStatement.condition().accept(*this);
setLocation(_ifStatement);
std::string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean());
string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean());
if (_ifStatement.falseStatement())
{
@ -657,7 +658,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return)
if (Expression const* value = _return.expression())
{
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters =
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
_return.annotation().functionReturnParameters->parameters();
if (returnParameters.size() > 1)
for (size_t i = 0; i < returnParameters.size(); ++i)
@ -684,7 +685,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation)
solAssert(function->returnParameters().size() == 1);
solAssert(*function->returnParameters()[0]->type() == *_unaryOperation.annotation().type);
std::string argument = expressionAsType(_unaryOperation.subExpression(), *function->parameters()[0]->type());
string argument = expressionAsType(_unaryOperation.subExpression(), *function->parameters()[0]->type());
solAssert(!argument.empty());
solAssert(_unaryOperation.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal);
@ -811,8 +812,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
solAssert(function->returnParameters().size() == 1);
solAssert(*function->returnParameters()[0]->type() == *_binOp.annotation().type);
std::string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type());
std::string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type());
string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type());
string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type());
solAssert(!left.empty() && !right.empty());
solAssert(_binOp.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal);
@ -852,13 +853,13 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
if (auto type = dynamic_cast<IntegerType const*>(commonType))
isSigned = type->isSigned();
std::string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType);
string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType);
args += ", " + expressionAsCleanedType(_binOp.rightExpression(), *commonType);
auto functionType = dynamic_cast<FunctionType const*>(commonType);
solAssert(functionType ? (op == Token::Equal || op == Token::NotEqual) : true, "Invalid function pointer comparison!");
std::string expr;
string expr;
if (functionType && functionType->kind() == FunctionType::Kind::External)
{
@ -878,9 +879,9 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
else if (op == Token::NotEqual)
expr = "iszero(eq(" + std::move(args) + "))";
else if (op == Token::GreaterThanOrEqual)
expr = "iszero(" + std::string(isSigned ? "slt(" : "lt(") + std::move(args) + "))";
expr = "iszero(" + string(isSigned ? "slt(" : "lt(") + std::move(args) + "))";
else if (op == Token::LessThanOrEqual)
expr = "iszero(" + std::string(isSigned ? "sgt(" : "gt(") + std::move(args) + "))";
expr = "iszero(" + string(isSigned ? "sgt(" : "gt(") + std::move(args) + "))";
else if (op == Token::GreaterThan)
expr = (isSigned ? "sgt(" : "gt(") + std::move(args) + ")";
else if (op == Token::LessThan)
@ -924,8 +925,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
}
else
{
std::string left = expressionAsType(_binOp.leftExpression(), *commonType);
std::string right = expressionAsType(_binOp.rightExpression(), *commonType);
string left = expressionAsType(_binOp.leftExpression(), *commonType);
string right = expressionAsType(_binOp.rightExpression(), *commonType);
define(_binOp) << binaryOperation(_binOp.getOperator(), *commonType, left, right) << "\n";
}
return false;
@ -959,7 +960,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
TypePointers parameterTypes = functionType->parameterTypes();
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
if (functionCallKind == FunctionCallKind::StructConstructorCall)
{
@ -1000,7 +1001,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
solAssert(!functionType->takesArbitraryParameters());
std::vector<std::string> args;
vector<string> args;
if (functionType->hasBoundFirstArgument())
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
@ -1048,8 +1049,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
TypePointers paramTypes = functionType->parameterTypes();
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
std::vector<IRVariable> indexedArgs;
std::vector<std::string> nonIndexedArgs;
vector<IRVariable> indexedArgs;
vector<string> nonIndexedArgs;
TypePointers nonIndexedArgTypes;
TypePointers nonIndexedParamTypes;
if (!event.isAnonymous())
@ -1060,7 +1061,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
Expression const& arg = *arguments[i];
if (event.parameters()[i]->isIndexed())
{
std::string value;
string value;
if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[i]))
define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::uint256())) <<
m_utils.packedHashFunction({arg.annotation().type}, {referenceType}) <<
@ -1105,7 +1106,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs));
templ("log", "log" + std::to_string(indexedArgs.size()));
templ("log", "log" + to_string(indexedArgs.size()));
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) {
return _arg.commaSeparatedList();
})));
@ -1151,7 +1152,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ?
arguments[1]->annotation().type :
nullptr;
std::string requireOrAssertFunction = m_utils.requireOrAssertFunction(
string requireOrAssertFunction = m_utils.requireOrAssertFunction(
functionType->kind() == FunctionType::Kind::Assert,
messageArgumentType
);
@ -1178,9 +1179,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
TypePointers argumentTypes;
TypePointers targetTypes;
std::vector<std::string> argumentVars;
std::string selector;
std::vector<ASTPointer<Expression const>> argumentsOfEncodeFunction;
vector<string> argumentVars;
string selector;
vector<ASTPointer<Expression const>> argumentsOfEncodeFunction;
if (functionType->kind() == FunctionType::Kind::ABIEncodeCall)
{
@ -1251,13 +1252,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
// TODO This is an abuse of the `allocateUnbounded` function.
// We might want to introduce a new set of memory handling functions here
// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
std::string freeMemoryPre = m_context.newYulVariable();
string freeMemoryPre = m_context.newYulVariable();
appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n";
IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory());
IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32));
std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory());
std::string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory());
string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory());
string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory());
define(hashVariable) <<
"keccak256(" <<
(dataAreaFunction + "(" + array.commaSeparatedList() + ")") <<
@ -1388,8 +1389,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
{
auto array = convert(*arguments[0], *arrayType);
std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType);
std::string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType);
string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType);
string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType);
define(_functionCall) <<
"keccak256(" <<
(dataAreaFunction + "(" + array.commaSeparatedList() + ")") <<
@ -1452,7 +1453,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
case FunctionType::Kind::BytesConcat:
{
TypePointers argumentTypes;
std::vector<std::string> argumentVars;
vector<string> argumentVars;
for (ASTPointer<Expression const> const& argument: arguments)
{
argumentTypes.emplace_back(&type(*argument));
@ -1472,7 +1473,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
case FunctionType::Kind::AddMod:
case FunctionType::Kind::MulMod:
{
static std::map<FunctionType::Kind, std::string> functions = {
static map<FunctionType::Kind, string> functions = {
{FunctionType::Kind::AddMod, "addmod"},
{FunctionType::Kind::MulMod, "mulmod"},
};
@ -1486,7 +1487,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero));
appendCode() << templ.render();
std::string args;
string args;
for (size_t i = 0; i < 2; ++i)
args += expressionAsType(*arguments[i], *(parameterTypes[i])) + ", ";
args += modulus.name();
@ -1497,14 +1498,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
case FunctionType::Kind::Selfdestruct:
case FunctionType::Kind::BlockHash:
{
static std::map<FunctionType::Kind, std::string> functions = {
static map<FunctionType::Kind, string> functions = {
{FunctionType::Kind::GasLeft, "gas"},
{FunctionType::Kind::Selfdestruct, "selfdestruct"},
{FunctionType::Kind::BlockHash, "blockhash"},
};
solAssert(functions.find(functionType->kind()) != functions.end());
std::string args;
string args;
for (size_t i = 0; i < arguments.size(); ++i)
args += (args.empty() ? "" : ", ") + expressionAsType(*arguments[i], *(parameterTypes[i]));
define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n";
@ -1519,7 +1520,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
);
TypePointers argumentTypes;
std::vector<std::string> constructorParams;
vector<string> constructorParams;
for (ASTPointer<Expression const> const& arg: arguments)
{
argumentTypes.push_back(arg->annotation().type);
@ -1574,8 +1575,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
case FunctionType::Kind::Transfer:
{
solAssert(arguments.size() == 1 && parameterTypes.size() == 1);
std::string address{IRVariable(_functionCall.expression()).part("address").name()};
std::string value{expressionAsType(*arguments[0], *(parameterTypes[0]))};
string address{IRVariable(_functionCall.expression()).part("address").name()};
string value{expressionAsType(*arguments[0], *(parameterTypes[0]))};
Whiskers templ(R"(
let <gas> := 0
if iszero(<value>) { <gas> := <callStipend> }
@ -1607,14 +1608,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
solAssert(!functionType->gasSet());
solAssert(!functionType->hasBoundFirstArgument());
static std::map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = {
static map<FunctionType::Kind, std::tuple<unsigned, size_t>> precompiles = {
{FunctionType::Kind::ECRecover, std::make_tuple(1, 0)},
{FunctionType::Kind::SHA256, std::make_tuple(2, 0)},
{FunctionType::Kind::RIPEMD160, std::make_tuple(3, 12)},
};
auto [ address, offset ] = precompiles[functionType->kind()];
TypePointers argumentTypes;
std::vector<std::string> argumentStrings;
vector<string> argumentStrings;
for (auto const& arg: arguments)
{
argumentTypes.emplace_back(&type(*arg));
@ -1675,11 +1676,11 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
// Copy over existing values.
for (auto const& item: previousType.stackItems())
define(IRVariable(_options).part(std::get<0>(item)), IRVariable(_options.expression()).part(std::get<0>(item)));
define(IRVariable(_options).part(get<0>(item)), IRVariable(_options.expression()).part(get<0>(item)));
for (size_t i = 0; i < _options.names().size(); ++i)
{
std::string const& name = *_options.names()[i];
string const& name = *_options.names()[i];
solAssert(name == "salt" || name == "gas" || name == "value");
define(IRVariable(_options).part(name), *_options.options()[i]);
@ -1784,7 +1785,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
")\n";
else if (member == "code")
{
std::string externalCodeFunction = m_utils.externalCodeFunction();
string externalCodeFunction = m_utils.externalCodeFunction();
define(_memberAccess) <<
externalCodeFunction <<
"(" <<
@ -1796,12 +1797,12 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
"extcodehash(" <<
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
")\n";
else if (std::set<std::string>{"send", "transfer"}.count(member))
else if (set<string>{"send", "transfer"}.count(member))
{
solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable);
define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression());
}
else if (std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}.count(member))
else if (set<string>{"call", "callcode", "delegatecall", "staticcall"}.count(member))
define(IRVariable{_memberAccess}.part("address"), _memberAccess.expression());
else
solAssert(false, "Invalid member access to address");
@ -1944,7 +1945,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
MagicType const* arg = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type);
std::string requestedValue;
string requestedValue;
if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(arg->typeArgument()))
{
if (member == "min")
@ -1955,16 +1956,16 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(arg->typeArgument()))
{
if (member == "min")
requestedValue = std::to_string(enumType->minValue());
requestedValue = to_string(enumType->minValue());
else
requestedValue = std::to_string(enumType->maxValue());
requestedValue = to_string(enumType->maxValue());
}
else
solAssert(false, "min/max requested on unexpected type.");
define(_memberAccess) << requestedValue << "\n";
}
else if (std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member))
else if (set<string>{"encode", "encodePacked", "encodeWithSelector", "encodeCall", "encodeWithSignature", "decode"}.count(member))
{
// no-op
}
@ -1980,8 +1981,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
case DataLocation::Storage:
{
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
std::string slot = m_context.newYulVariable();
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
string slot = m_context.newYulVariable();
appendCode() << "let " << slot << " := " <<
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
setLValue(_memberAccess, IRLValue{
@ -1992,7 +1993,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
}
case DataLocation::Memory:
{
std::string pos = m_context.newYulVariable();
string pos = m_context.newYulVariable();
appendCode() << "let " << pos << " := " <<
("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n");
setLValue(_memberAccess, IRLValue{
@ -2003,9 +2004,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
}
case DataLocation::CallData:
{
std::string baseRef = expression.part("offset").name();
std::string offset = m_context.newYulVariable();
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << std::to_string(structType.calldataOffsetOfMember(member)) << ")\n";
string baseRef = expression.part("offset").name();
string offset = m_context.newYulVariable();
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
if (_memberAccess.annotation().type->isDynamicallyEncoded())
define(_memberAccess) <<
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
@ -2035,7 +2036,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
case Type::Category::Enum:
{
EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.expression().annotation().type);
define(_memberAccess) << std::to_string(type.memberValue(_memberAccess.memberName())) << "\n";
define(_memberAccess) << to_string(type.memberValue(_memberAccess.memberName())) << "\n";
break;
}
case Type::Category::Array:
@ -2075,7 +2076,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type);
if (member == "length")
define(_memberAccess) << std::to_string(type.numBytes()) << "\n";
define(_memberAccess) << to_string(type.numBytes()) << "\n";
else
solAssert(false, "Illegal fixed bytes member.");
break;
@ -2161,7 +2162,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
solAssert(false);
}
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(&actualType))
define(_memberAccess) << std::to_string(enumType->memberValue(_memberAccess.memberName())) << "\n";
define(_memberAccess) << to_string(enumType->memberValue(_memberAccess.memberName())) << "\n";
else if (dynamic_cast<UserDefinedValueType const*>(&actualType))
solAssert(member == "wrap" || member == "unwrap");
else if (auto const* arrayType = dynamic_cast<ArrayType const*>(&actualType))
@ -2221,7 +2222,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
yul::Statement modified = bodyCopier(_inlineAsm.operations());
solAssert(std::holds_alternative<yul::Block>(modified));
solAssert(holds_alternative<yul::Block>(modified));
// Do not provide dialect so that we get the full type information.
appendCode() << yul::AsmPrinter()(std::get<yul::Block>(modified)) << "\n";
@ -2241,7 +2242,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
MappingType const& mappingType = dynamic_cast<MappingType const&>(baseType);
Type const& keyType = *_indexAccess.indexExpression()->annotation().type;
std::string slot = m_context.newYulVariable();
string slot = m_context.newYulVariable();
Whiskers templ("let <slot> := <indexAccess>(<base><?+key>,<key></+key>)\n");
templ("slot", slot);
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
@ -2272,8 +2273,8 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
{
case DataLocation::Storage:
{
std::string slot = m_context.newYulVariable();
std::string offset = m_context.newYulVariable();
string slot = m_context.newYulVariable();
string offset = m_context.newYulVariable();
appendCode() << Whiskers(R"(
let <slot>, <offset> := <indexFunc>(<array>, <index>)
@ -2294,13 +2295,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
}
case DataLocation::Memory:
{
std::string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType);
std::string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name();
std::string const indexExpression = expressionAsType(
string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType);
string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name();
string const indexExpression = expressionAsType(
*_indexAccess.indexExpression(),
*TypeProvider::uint256()
);
std::string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
setLValue(_indexAccess, IRLValue{
*arrayType.baseType(),
@ -2310,13 +2311,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
}
case DataLocation::CallData:
{
std::string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType);
std::string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList();
std::string const indexExpression = expressionAsType(
string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType);
string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList();
string const indexExpression = expressionAsType(
*_indexAccess.indexExpression(),
*TypeProvider::uint256()
);
std::string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
if (arrayType.isByteArrayOrString())
define(_indexAccess) <<
@ -2348,7 +2349,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
let <result> := <shl248>(byte(<index>, <array>))
)")
("index", index.name())
("length", std::to_string(fixedBytesType.numBytes()))
("length", to_string(fixedBytesType.numBytes()))
("panic", m_utils.panicFunction(PanicCode::ArrayOutOfBounds))
("array", IRVariable(_indexAccess.baseExpression()).name())
("shl248", m_utils.shiftLeftFunction(256 - 8))
@ -2537,7 +2538,7 @@ void IRGeneratorForStatements::handleVariableReference(
void IRGeneratorForStatements::appendExternalFunctionCall(
FunctionCall const& _functionCall,
std::vector<ASTPointer<Expression const>> const& _arguments
vector<ASTPointer<Expression const>> const& _arguments
)
{
FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression()));
@ -2558,7 +2559,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
TypePointers parameterTypes = funType.parameterTypes();
TypePointers argumentTypes;
std::vector<std::string> argumentStrings;
vector<string> argumentStrings;
if (funType.hasBoundFirstArgument())
{
parameterTypes.insert(parameterTypes.begin(), funType.selfType());
@ -2580,7 +2581,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
// would remove that, so we use MSTORE here.
if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0)
appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << std::to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n";
}
// NOTE: When the expected size of returndata is static, we pass that in to the call opcode and it gets copied automatically.
@ -2648,10 +2649,10 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
if (returnInfo.dynamicReturnSize)
solAssert(m_context.evmVersion().supportsReturndata());
templ("returnDataSizeVar", m_context.newYulVariable());
templ("staticReturndataSize", std::to_string(returnInfo.estimatedReturnSize));
templ("staticReturndataSize", to_string(returnInfo.estimatedReturnSize));
templ("supportsReturnData", m_context.evmVersion().supportsReturndata());
std::string const retVars = IRVariable(_functionCall).commaSeparatedList();
string const retVars = IRVariable(_functionCall).commaSeparatedList();
templ("retVars", retVars);
solAssert(retVars.empty() == returnInfo.returnTypes.empty());
@ -2703,7 +2704,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
void IRGeneratorForStatements::appendBareCall(
FunctionCall const& _functionCall,
std::vector<ASTPointer<Expression const>> const& _arguments
vector<ASTPointer<Expression const>> const& _arguments
)
{
FunctionType const& funType = dynamic_cast<FunctionType const&>(type(_functionCall.expression()));
@ -2806,7 +2807,7 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
return;
define(IRVariable(_expression).part("functionIdentifier")) <<
std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) <<
to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(&_referencedFunction)) <<
"\n";
m_context.addToInternalDispatch(_referencedFunction);
}
@ -2863,7 +2864,7 @@ void IRGeneratorForStatements::declare(IRVariable const& _var)
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare, bool _forceCleanup)
{
std::string output;
string output;
if (_lhs.type() == _rhs.type() && !_forceCleanup)
for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems())
if (stackItemType)
@ -2893,7 +2894,7 @@ IRVariable IRGeneratorForStatements::zeroValue(Type const& _type, bool _splitFun
void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr)
{
std::string func;
string func;
if (_operation.getOperator() == Token::Not)
func = "iszero";
@ -2912,18 +2913,18 @@ void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const&
")\n";
}
std::string IRGeneratorForStatements::binaryOperation(
string IRGeneratorForStatements::binaryOperation(
langutil::Token _operator,
Type const& _type,
std::string const& _left,
std::string const& _right
string const& _left,
string const& _right
)
{
solAssert(
!TokenTraits::isShiftOp(_operator),
"Have to use specific shift operation function for shifts."
);
std::string fun;
string fun;
if (TokenTraits::isBitOp(_operator))
{
solAssert(
@ -3029,12 +3030,12 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
std::visit(
util::GenericVisitor{
[&](IRLValue::Storage const& _storage) {
std::string offsetArgument;
std::optional<unsigned> offsetStatic;
string offsetArgument;
optional<unsigned> offsetStatic;
std::visit(GenericVisitor{
[&](unsigned _offset) { offsetStatic = _offset; },
[&](std::string const& _offset) { offsetArgument = ", " + _offset; }
[&](string const& _offset) { offsetArgument = ", " + _offset; }
}, _storage.offset);
appendCode() <<
@ -3067,7 +3068,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
}
else if (auto const* literalType = dynamic_cast<StringLiteralType const*>(&_value.type()))
{
std::string writeUInt = m_utils.writeToMemoryFunction(*TypeProvider::uint256());
string writeUInt = m_utils.writeToMemoryFunction(*TypeProvider::uint256());
appendCode() <<
writeUInt <<
"(" <<
@ -3098,7 +3099,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
IRVariable prepared(m_context.newYulVariable(), _lvalue.type);
define(prepared, _value);
appendCode() << "mstore(" << std::to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
appendCode() << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
},
[&](IRLValue::Tuple const& _tuple) {
auto components = std::move(_tuple.components);
@ -3121,13 +3122,13 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue)
[&](IRLValue::Storage const& _storage) {
if (!_lvalue.type.isValueType())
define(result) << _storage.slot << "\n";
else if (std::holds_alternative<std::string>(_storage.offset))
else if (std::holds_alternative<string>(_storage.offset))
define(result) <<
m_utils.readFromStorageDynamic(_lvalue.type, true) <<
"(" <<
_storage.slot <<
", " <<
std::get<std::string>(_storage.offset) <<
std::get<string>(_storage.offset) <<
")\n";
else
define(result) <<
@ -3155,15 +3156,15 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue)
solAssert(_lvalue.type == *_immutable.variable->type());
if (m_context.executionContext() == IRGenerationContext::ExecutionContext::Creation)
{
std::string readFunction = m_utils.readFromMemory(*_immutable.variable->type());
string readFunction = m_utils.readFromMemory(*_immutable.variable->type());
define(result) <<
readFunction <<
"(" <<
std::to_string(m_context.immutableMemoryOffset(*_immutable.variable)) <<
to_string(m_context.immutableMemoryOffset(*_immutable.variable)) <<
")\n";
}
else
define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n";
define(result) << "loadimmutable(\"" << to_string(_immutable.variable->id()) << "\")\n";
},
[&](IRLValue::Tuple const&) {
solAssert(false, "Attempted to read from tuple lvalue.");
@ -3180,7 +3181,7 @@ void IRGeneratorForStatements::setLValue(Expression const& _expression, IRLValue
{
m_currentLValue.emplace(std::move(_lvalue));
if (_lvalue.type.dataStoredIn(DataLocation::CallData))
solAssert(std::holds_alternative<IRLValue::Stack>(_lvalue.kind));
solAssert(holds_alternative<IRLValue::Stack>(_lvalue.kind));
}
else
// Only define the expression, if it will not be written to.
@ -3195,7 +3196,7 @@ void IRGeneratorForStatements::generateLoop(
bool _isDoWhile
)
{
std::string firstRun;
string firstRun;
if (_isDoWhile)
{
@ -3277,7 +3278,7 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement)
void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
{
setLocation(_tryStatement);
std::string const runFallback = m_context.newYulVariable();
string const runFallback = m_context.newYulVariable();
appendCode() << "let " << runFallback << " := 1\n";
// This function returns zero on "short returndata". We have to add a success flag
@ -3289,7 +3290,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
{
appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n";
setLocation(*errorClause);
std::string const dataVariable = m_context.newYulVariable();
string const dataVariable = m_context.newYulVariable();
appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
appendCode() << "if " << dataVariable << " {\n";
appendCode() << runFallback << " := 0\n";
@ -3309,8 +3310,8 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
{
appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n";
setLocation(*panicClause);
std::string const success = m_context.newYulVariable();
std::string const code = m_context.newYulVariable();
string const success = m_context.newYulVariable();
string const code = m_context.newYulVariable();
appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n";
appendCode() << "if " << success << " {\n";
appendCode() << runFallback << " := 0\n";
@ -3357,9 +3358,9 @@ void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallba
}
void IRGeneratorForStatements::revertWithError(
std::string const& _signature,
std::vector<Type const*> const& _parameterTypes,
std::vector<ASTPointer<Expression const>> const& _errorArguments
string const& _signature,
vector<Type const*> const& _parameterTypes,
vector<ASTPointer<Expression const>> const& _errorArguments
)
{
Whiskers templ(R"({
@ -3373,8 +3374,8 @@ void IRGeneratorForStatements::revertWithError(
templ("hash", util::selectorFromSignatureU256(_signature).str());
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
std::vector<std::string> errorArgumentVars;
std::vector<Type const*> errorArgumentTypes;
vector<string> errorArgumentVars;
vector<Type const*> errorArgumentTypes;
for (ASTPointer<Expression const> const& arg: _errorArguments)
{
errorArgumentVars += IRVariable(*arg).stackSlots();
@ -3394,7 +3395,7 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
return false;
}
std::string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
{
solAssert(_library.isLibrary());
return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")";

View File

@ -20,6 +20,7 @@
#include <libsolidity/ast/AST.h>
#include <libsolutil/StringUtils.h>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::util;
@ -40,7 +41,7 @@ IRVariable::IRVariable(Expression const& _expression):
{
}
IRVariable IRVariable::part(std::string const& _name) const
IRVariable IRVariable::part(string const& _name) const
{
for (auto const& [itemName, itemType]: m_type.stackItems())
if (itemName == _name)
@ -62,9 +63,9 @@ bool IRVariable::hasPart(std::string const& _name) const
return false;
}
std::vector<std::string> IRVariable::stackSlots() const
vector<string> IRVariable::stackSlots() const
{
std::vector<std::string> result;
vector<string> result;
for (auto const& [itemName, itemType]: m_type.stackItems())
if (itemType)
{
@ -80,17 +81,17 @@ std::vector<std::string> IRVariable::stackSlots() const
return result;
}
std::string IRVariable::commaSeparatedList() const
string IRVariable::commaSeparatedList() const
{
return joinHumanReadable(stackSlots());
}
std::string IRVariable::commaSeparatedListPrefixed() const
string IRVariable::commaSeparatedListPrefixed() const
{
return joinHumanReadablePrefixed(stackSlots());
}
std::string IRVariable::name() const
string IRVariable::name() const
{
solAssert(m_type.sizeOnStack() == 1, "");
auto const& [itemName, type] = m_type.stackItems().front();
@ -107,7 +108,7 @@ IRVariable IRVariable::tupleComponent(size_t _i) const
return part(IRNames::tupleComponent(_i));
}
std::string IRVariable::suffixedName(std::string const& _suffix) const
string IRVariable::suffixedName(string const& _suffix) const
{
if (_suffix.empty())
return m_baseName;

View File

@ -1,34 +0,0 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
#include <libsolidity/experimental/analysis/Analysis.h>
#include <liblangutil/ErrorReporter.h>
using namespace solidity::langutil;
using namespace solidity::frontend::experimental;
bool Analysis::check(std::vector<std::shared_ptr<SourceUnit const>> const&)
{
m_errorReporter.error(
6547_error,
Error::Type::UnimplementedFeatureError,
SourceLocation{},
"Experimental Analysis is not implemented yet."
);
return false;
}

View File

@ -20,17 +20,18 @@
#include <liblangutil/Exceptions.h>
using namespace std;
using namespace solidity;
using namespace solidity::smtutil;
using namespace solidity::frontend;
using namespace solidity::frontend::smt;
std::map<std::string, ArraySlicePredicate::SliceData> ArraySlicePredicate::m_slicePredicates;
map<string, ArraySlicePredicate::SliceData> ArraySlicePredicate::m_slicePredicates;
std::pair<bool, ArraySlicePredicate::SliceData const&> ArraySlicePredicate::create(SortPointer _sort, EncodingContext& _context)
pair<bool, ArraySlicePredicate::SliceData const&> ArraySlicePredicate::create(SortPointer _sort, EncodingContext& _context)
{
solAssert(_sort->kind == Kind::Tuple, "");
auto tupleSort = std::dynamic_pointer_cast<TupleSort>(_sort);
auto tupleSort = dynamic_pointer_cast<TupleSort>(_sort);
solAssert(tupleSort, "");
auto tupleName = tupleSort->name;
@ -46,12 +47,12 @@ std::pair<bool, ArraySlicePredicate::SliceData const&> ArraySlicePredicate::crea
smt::SymbolicIntVariable endVar{TypeProvider::uint256(), TypeProvider::uint256(), "end_" + tupleName, _context };
smt::SymbolicIntVariable iVar{TypeProvider::uint256(), TypeProvider::uint256(), "i_" + tupleName, _context};
std::vector<SortPointer> domain{sort, sort, startVar.sort(), endVar.sort()};
auto sliceSort = std::make_shared<FunctionSort>(domain, SortProvider::boolSort);
vector<SortPointer> domain{sort, sort, startVar.sort(), endVar.sort()};
auto sliceSort = make_shared<FunctionSort>(domain, SortProvider::boolSort);
Predicate const& slice = *Predicate::create(sliceSort, "array_slice_" + tupleName, PredicateType::Custom, _context);
domain.emplace_back(iVar.sort());
auto predSort = std::make_shared<FunctionSort>(domain, SortProvider::boolSort);
auto predSort = make_shared<FunctionSort>(domain, SortProvider::boolSort);
Predicate const& header = *Predicate::create(predSort, "array_slice_header_" + tupleName, PredicateType::Custom, _context);
Predicate const& loop = *Predicate::create(predSort, "array_slice_loop_" + tupleName, PredicateType::Custom, _context);

View File

@ -31,6 +31,7 @@
#include <z3_version.h>
#endif
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::langutil;
@ -40,13 +41,13 @@ BMC::BMC(
smt::EncodingContext& _context,
UniqueErrorReporter& _errorReporter,
UniqueErrorReporter& _unsupportedErrorReporter,
std::map<h256, std::string> const& _smtlib2Responses,
map<h256, string> const& _smtlib2Responses,
ReadCallback::Callback const& _smtCallback,
ModelCheckerSettings _settings,
CharStreamProvider const& _charStreamProvider
):
SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider),
m_interface(std::make_unique<smtutil::SMTPortfolio>(
m_interface(make_unique<smtutil::SMTPortfolio>(
_smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout, _settings.printQuery
))
{
@ -64,7 +65,7 @@ BMC::BMC(
#endif
}
void BMC::analyze(SourceUnit const& _source, std::map<ASTNode const*, std::set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets)
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets)
{
// At this point every enabled solver is available.
if (!m_settings.solvers.cvc4 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3)
@ -96,7 +97,7 @@ void BMC::analyze(SourceUnit const& _source, std::map<ASTNode const*, std::set<V
2788_error,
{},
"BMC: " +
std::to_string(m_unprovedAmt) +
to_string(m_unprovedAmt) +
" verification condition(s) could not be proved." +
" Enable the model checker option \"show unproved\" to see all of them." +
" Consider choosing a specific contract to be verified in order to reduce the solving problems." +
@ -107,7 +108,7 @@ void BMC::analyze(SourceUnit const& _source, std::map<ASTNode const*, std::set<V
m_errorReporter.info(
6002_error,
"BMC: " +
std::to_string(m_safeTargets.size()) +
to_string(m_safeTargets.size()) +
" verification condition(s) proved safe!" +
" Enable the model checker option \"show proved safe\" to see all of them."
);
@ -137,7 +138,7 @@ void BMC::analyze(SourceUnit const& _source, std::map<ASTNode const*, std::set<V
"BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available."
" None of the installed solvers was enabled."
#ifdef HAVE_Z3_DLOPEN
" Install libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION) + " to enable Z3."
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3."
#endif
);
}
@ -312,7 +313,7 @@ bool BMC::visit(WhileStatement const& _node)
auto indicesBefore = copyVariableIndices();
_node.body().accept(*this);
auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints();
auto [continues, brokeInCurrentIteration] = mergeVariablesFromLoopCheckpoints();
auto indicesBreak = copyVariableIndices();
_node.condition().accept(*this);
@ -327,15 +328,13 @@ bool BMC::visit(WhileStatement const& _node)
indicesBefore,
copyVariableIndices()
);
loopCondition = loopCondition && expr(_node.condition());
loopCondition = expr(_node.condition());
broke = broke || brokeInCurrentIteration;
m_loopCheckpoints.pop();
}
if (bmcLoopIterations > 0)
m_context.addAssertion(!loopCondition || broke);
}
else {
smtutil::Expression loopConditionOnPreviousIterations(true);
smtutil::Expression loopConditionOnPreviousIteration(true);
for (unsigned int i = 0; i < bmcLoopIterations; ++i)
{
m_loopCheckpoints.emplace();
@ -349,7 +348,7 @@ bool BMC::visit(WhileStatement const& _node)
_node.body().accept(*this);
popPathCondition();
auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints();
auto [continues, brokeInCurrentIteration] = mergeVariablesFromLoopCheckpoints();
// merges indices modified when accepting loop condition that no longer holds
mergeVariables(
@ -362,29 +361,17 @@ bool BMC::visit(WhileStatement const& _node)
// breaks in current iterations are handled when traversing loop checkpoints
// handles case when the loop condition no longer holds but bmc loop iterations still unrolls the loop
mergeVariables(
broke || !loopConditionOnPreviousIterations,
broke || !loopConditionOnPreviousIteration,
indicesBefore,
copyVariableIndices()
);
m_loopCheckpoints.pop();
broke = broke || brokeInCurrentIteration;
loopConditionOnPreviousIterations = loopConditionOnPreviousIterations && loopCondition;
loopConditionOnPreviousIteration = loopCondition;
}
}
if (bmcLoopIterations > 0)
{
//after loop iterations are done, we check the loop condition last final time
auto indices = copyVariableIndices();
_node.condition().accept(*this);
loopCondition = expr(_node.condition());
// asseert that the loop is complete
m_context.addAssertion(!loopCondition || broke || !loopConditionOnPreviousIterations);
mergeVariables(
broke || !loopConditionOnPreviousIterations,
indices,
copyVariableIndices()
);
}
}
m_context.addAssertion(not(loopCondition) || broke);
m_loopExecutionHappened = true;
return false;
}
@ -397,7 +384,7 @@ bool BMC::visit(ForStatement const& _node)
smtutil::Expression broke(false);
smtutil::Expression forCondition(true);
smtutil::Expression forConditionOnPreviousIterations(true);
smtutil::Expression forConditionOnPreviousIteration(true);
unsigned int bmcLoopIterations = m_settings.bmcLoopIterations.value_or(1);
for (unsigned int i = 0; i < bmcLoopIterations; ++i)
{
@ -414,7 +401,7 @@ bool BMC::visit(ForStatement const& _node)
pushPathCondition(forCondition);
_node.body().accept(*this);
auto brokeInCurrentIteration = mergeVariablesFromLoopCheckpoints();
auto [continues, brokeInCurrentIteration] = mergeVariablesFromLoopCheckpoints();
// accept loop expression if there was no break
if (_node.loopExpression())
@ -440,38 +427,21 @@ bool BMC::visit(ForStatement const& _node)
// breaks in current iterations are handled when traversing loop checkpoints
// handles case when the loop condition no longer holds but bmc loop iterations still unrolls the loop
mergeVariables(
broke || !forConditionOnPreviousIterations,
broke || !forConditionOnPreviousIteration,
indicesBefore,
copyVariableIndices()
);
m_loopCheckpoints.pop();
broke = broke || brokeInCurrentIteration;
forConditionOnPreviousIterations = forConditionOnPreviousIterations && forCondition;
forConditionOnPreviousIteration = forCondition;
}
if (bmcLoopIterations > 0)
{
//after loop iterations are done, we check the loop condition last final time
auto indices = copyVariableIndices();
if (_node.condition())
{
_node.condition()->accept(*this);
forCondition = expr(*_node.condition());
}
// asseert that the loop is complete
m_context.addAssertion(!forCondition || broke || !forConditionOnPreviousIterations);
mergeVariables(
broke || !forConditionOnPreviousIterations,
indices,
copyVariableIndices()
);
}
m_context.addAssertion(not(forCondition) || broke);
m_loopExecutionHappened = true;
return false;
}
// merges variables based on loop control statements
// returns expression indicating whether there was a break in current loop unroll iteration
smtutil::Expression BMC::mergeVariablesFromLoopCheckpoints()
std::tuple<smtutil::Expression, smtutil::Expression> BMC::mergeVariablesFromLoopCheckpoints()
{
smtutil::Expression continues(false);
smtutil::Expression brokeInCurrentIteration(false);
@ -491,7 +461,7 @@ smtutil::Expression BMC::mergeVariablesFromLoopCheckpoints()
else if (loopControl.kind == LoopControlKind::Continue)
continues = continues || loopControl.pathConditions;
}
return brokeInCurrentIteration;
return std::pair(continues, brokeInCurrentIteration);
}
bool BMC::visit(TryStatement const& _tryStatement)
@ -503,11 +473,11 @@ bool BMC::visit(TryStatement const& _tryStatement)
if (_tryStatement.successClause()->parameters())
expressionToTupleAssignment(_tryStatement.successClause()->parameters()->parameters(), *externalCall);
smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + std::to_string(m_context.newUniqueId()), smtutil::SortProvider::uintSort);
smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + to_string(m_context.newUniqueId()), smtutil::SortProvider::uintSort);
auto const& clauses = _tryStatement.clauses();
m_context.addAssertion(clauseId >= 0 && clauseId < clauses.size());
solAssert(clauses[0].get() == _tryStatement.successClause(), "First clause of TryStatement should be the success clause");
std::vector<std::pair<VariableIndices, smtutil::Expression>> clausesVisitResults;
vector<pair<VariableIndices, smtutil::Expression>> clausesVisitResults;
for (size_t i = 0; i < clauses.size(); ++i)
clausesVisitResults.push_back(visitBranch(clauses[i].get()));
@ -735,7 +705,7 @@ void BMC::internalOrExternalFunctionCall(FunctionCall const& _funCall)
}
}
std::pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
Token _op,
smtutil::Expression const& _left,
smtutil::Expression const& _right,
@ -799,10 +769,10 @@ void BMC::reset()
m_loopExecutionHappened = false;
}
std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> BMC::modelExpressions()
pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
{
std::vector<smtutil::Expression> expressionsToEvaluate;
std::vector<std::string> expressionNames;
vector<smtutil::Expression> expressionsToEvaluate;
vector<string> expressionNames;
for (auto const& var: m_context.variables())
if (var.first->type()->isValueType())
{
@ -825,7 +795,7 @@ std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> BMC::model
if (uf->annotation().type->isValueType())
{
expressionsToEvaluate.emplace_back(expr(*uf));
std::string expressionName;
string expressionName;
if (uf->location().hasText())
expressionName = m_charStreamProvider.charStream(*uf->location().sourceName).text(
uf->location()
@ -838,7 +808,7 @@ std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> BMC::model
/// Verification targets.
std::string BMC::targetDescription(BMCVerificationTarget const& _target)
string BMC::targetDescription(BMCVerificationTarget const& _target)
{
if (
_target.type == VerificationTargetType::Underflow ||
@ -1064,20 +1034,20 @@ void BMC::addVerificationTarget(
void BMC::checkCondition(
BMCVerificationTarget const& _target,
smtutil::Expression _condition,
std::vector<SMTEncoder::CallStackEntry> const& _callStack,
std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> const& _modelExpressions,
vector<SMTEncoder::CallStackEntry> const& _callStack,
pair<vector<smtutil::Expression>, vector<string>> const& _modelExpressions,
SourceLocation const& _location,
ErrorId _errorHappens,
ErrorId _errorMightHappen,
std::string const& _additionalValueName,
string const& _additionalValueName,
smtutil::Expression const* _additionalValue
)
{
m_interface->push();
m_interface->addAssertion(_condition);
std::vector<smtutil::Expression> expressionsToEvaluate;
std::vector<std::string> expressionNames;
vector<smtutil::Expression> expressionsToEvaluate;
vector<string> expressionNames;
tie(expressionsToEvaluate, expressionNames) = _modelExpressions;
if (!_callStack.empty())
if (_additionalValue)
@ -1086,10 +1056,10 @@ void BMC::checkCondition(
expressionNames.push_back(_additionalValueName);
}
smtutil::CheckResult result;
std::vector<std::string> values;
vector<string> values;
tie(result, values) = checkSatisfiableAndGenerateModel(expressionsToEvaluate);
std::string extraComment = SMTEncoder::extraComment();
string extraComment = SMTEncoder::extraComment();
if (m_loopExecutionHappened)
extraComment +=
"False negatives are possible when unrolling loops.\n"
@ -1118,7 +1088,7 @@ void BMC::checkCondition(
if (values.size() == expressionNames.size())
{
modelMessage << "Counterexample:\n";
std::map<std::string, std::string> sortedModel;
map<string, string> sortedModel;
for (size_t i = 0; i < values.size(); ++i)
if (expressionsToEvaluate.at(i).name != values.at(i))
sortedModel[expressionNames.at(i)] = values.at(i);
@ -1164,7 +1134,7 @@ void BMC::checkBooleanNotConstant(
Expression const& _condition,
smtutil::Expression const& _constraints,
smtutil::Expression const& _value,
std::vector<SMTEncoder::CallStackEntry> const& _callStack
vector<SMTEncoder::CallStackEntry> const& _callStack
)
{
// Do not check for const-ness if this is a constant.
@ -1197,7 +1167,7 @@ void BMC::checkBooleanNotConstant(
m_errorReporter.warning(2512_error, _condition.location(), "BMC: Condition unreachable.", SMTEncoder::callStackMessage(_callStack));
else
{
std::string description;
string description;
if (positiveResult == smtutil::CheckResult::SATISFIABLE)
{
solAssert(negatedResult == smtutil::CheckResult::UNSATISFIABLE, "");
@ -1218,17 +1188,17 @@ void BMC::checkBooleanNotConstant(
}
}
std::pair<smtutil::CheckResult, std::vector<std::string>>
BMC::checkSatisfiableAndGenerateModel(std::vector<smtutil::Expression> const& _expressionsToEvaluate)
pair<smtutil::CheckResult, vector<string>>
BMC::checkSatisfiableAndGenerateModel(vector<smtutil::Expression> const& _expressionsToEvaluate)
{
smtutil::CheckResult result;
std::vector<std::string> values;
vector<string> values;
try
{
if (m_settings.printQuery)
{
auto portfolio = dynamic_cast<smtutil::SMTPortfolio*>(m_interface.get());
std::string smtlibCode = portfolio->dumpQuery(_expressionsToEvaluate);
string smtlibCode = portfolio->dumpQuery(_expressionsToEvaluate);
m_errorReporter.info(
6240_error,
"BMC: Requested query:\n" + smtlibCode
@ -1238,14 +1208,14 @@ BMC::checkSatisfiableAndGenerateModel(std::vector<smtutil::Expression> const& _e
}
catch (smtutil::SolverError const& _e)
{
std::string description("BMC: Error querying SMT solver");
string description("BMC: Error querying SMT solver");
if (_e.comment())
description += ": " + *_e.comment();
m_errorReporter.warning(8140_error, description);
result = smtutil::CheckResult::ERROR;
}
for (std::string& value: values)
for (string& value: values)
{
try
{

View File

@ -190,7 +190,7 @@ private:
smtutil::CheckResult checkSatisfiable();
//@}
smtutil::Expression mergeVariablesFromLoopCheckpoints();
std::tuple<smtutil::Expression, smtutil::Expression> mergeVariablesFromLoopCheckpoints();
bool isInsideLoop() const;
std::unique_ptr<smtutil::SolverInterface> m_interface;

Some files were not shown because too many files have changed in this diff Show More