Merge branch 'develop' into feature/eip712-typehash

# Conflicts:
#	libsolidity/ast/Types.cpp
This commit is contained in:
Anton Bukov 2023-10-02 13:20:48 +02:00
commit 23920b946c
999 changed files with 19662 additions and 13753 deletions

View File

@ -88,6 +88,7 @@ commands:
steps: steps:
- run: - run:
name: Generate bytecode reports for the selected preset name: Generate bytecode reports for the selected preset
no_output_timeout: 30m
command: | command: |
.circleci/parallel_bytecode_report.sh \ .circleci/parallel_bytecode_report.sh \
"<< parameters.label >>" \ "<< parameters.label >>" \
@ -178,47 +179,199 @@ commands:
paths: paths:
- << parameters.install_path >> - << parameters.install_path >>
defaults: # --------------------------------------------------------------------------
# Build Commands
setup_prerelease_commit_hash:
steps:
- run:
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
echo -n "$CIRCLE_SHA1" > commit_hash.txt
run_build:
steps:
- run:
name: Build
command: scripts/ci/build.sh
run_build_ossfuzz:
steps:
- run:
name: Build_ossfuzz
command: scripts/ci/build_ossfuzz.sh
run_proofs:
steps:
- run:
name: Correctness proofs for optimization rules
command: scripts/run_proofs.sh
run_soltest:
steps:
- run:
name: soltest
no_output_timeout: 30m
command: .circleci/soltest.sh
run_soltest_all:
steps:
- run:
name: soltest_all
no_output_timeout: 30m
command: .circleci/soltest_all.sh
run_cmdline_tests:
steps:
- run:
name: command line tests
no_output_timeout: 30m
command: .circleci/parallel_cli_tests.py
run_docs_pragma_min_version:
steps:
- run:
name: docs pragma version check
command: scripts/docs_version_pragma_check.sh
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Build Templates # Artifact Commands
- setup_prerelease_commit_hash: &setup_prerelease_commit_hash store_artifacts_solc:
name: Store commit hash and prerelease description: Store compiled solc executable as artifact
command: | steps:
if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi - store_artifacts:
echo -n "$CIRCLE_SHA1" > commit_hash.txt path: build/solc/solc
destination: solc
- run_build: &run_build store_artifacts_yul_phaser:
name: Build steps:
command: scripts/ci/build.sh - store_artifacts:
path: build/tools/yul-phaser
destination: yul-phaser
- run_build_ossfuzz: &run_build_ossfuzz persist_executables_to_workspace:
name: Build_ossfuzz description: Persist compiled target executables to workspace
command: scripts/ci/build_ossfuzz.sh steps:
- persist_to_workspace:
root: build
paths:
- solc/solc
- test/soltest
- test/tools/solfuzzer
- run_proofs: &run_proofs persist_executables_to_workspace_osx:
name: Correctness proofs for optimization rules description: Persist compiled target executables to workspace on macOS
command: scripts/run_proofs.sh steps:
- persist_to_workspace:
root: .
paths:
- build/solc/solc
- build/test/soltest
- build/test/tools/solfuzzer
- run_soltest: &run_soltest persist_ossfuzz_executables_to_workspace:
name: soltest description: Persist compiled OSSFUZZ executables to workspace
no_output_timeout: 30m steps:
command: ./.circleci/soltest.sh - 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
- run_soltest_all: &run_soltest_all store_artifacts_test_results:
name: soltest_all description: Store test output dir as artifact
no_output_timeout: 30m steps:
command: ./.circleci/soltest_all.sh - store_artifacts:
path: test_results/
destination: test_results/
- run_cmdline_tests: &run_cmdline_tests # --------------------------------------------------------------------------
name: command line tests # Complex Build Commands
no_output_timeout: 30m
command: .circleci/parallel_cli_tests.py
- run_docs_pragma_min_version: &run_docs_pragma_min_version soltest:
name: docs pragma version check steps:
command: ./scripts/docs_version_pragma_check.sh - 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:
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Matrix templates # Matrix templates
@ -227,6 +380,8 @@ defaults:
PRESETS: PRESETS:
legacy-optimize legacy-optimize
legacy-no-optimize legacy-no-optimize
via-ir-optimize
via-ir-no-optimize
- bytecode_compare_preset_matrix: &bytecode_compare_preset_matrix - bytecode_compare_preset_matrix: &bytecode_compare_preset_matrix
parameters: parameters:
@ -234,124 +389,10 @@ defaults:
# NOTE: Keep in sync with preset list in bytecode_compare_env_presets # NOTE: Keep in sync with preset list in bytecode_compare_env_presets
- legacy-optimize - legacy-optimize
- legacy-no-optimize - legacy-no-optimize
- via-ir-optimize
- 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 # Base Image Templates
@ -361,6 +402,7 @@ defaults:
environment: &base_archlinux_env environment: &base_archlinux_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 3 MAKEFLAGS: -j 3
CPUs: 3
- base_archlinux_large: &base_archlinux_large - base_archlinux_large: &base_archlinux_large
<<: *base_archlinux <<: *base_archlinux
@ -368,6 +410,7 @@ defaults:
environment: &base_archlinux_large_env environment: &base_archlinux_large_env
<<: *base_archlinux_env <<: *base_archlinux_env
MAKEFLAGS: -j 5 MAKEFLAGS: -j 5
CPUs: 5
- base_cimg_small: &base_cimg_small - base_cimg_small: &base_cimg_small
docker: docker:
@ -376,6 +419,7 @@ defaults:
environment: &base_cimg_small_env environment: &base_cimg_small_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 2 MAKEFLAGS: -j 2
CPUs: 2
- base_ems_large: &base_ems_large - base_ems_large: &base_ems_large
docker: docker:
@ -384,6 +428,7 @@ defaults:
environment: &base_ems_large_env environment: &base_ems_large_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 5 MAKEFLAGS: -j 5
CPUs: 5
- base_node_small: &base_node_small - base_node_small: &base_node_small
docker: docker:
@ -392,6 +437,7 @@ defaults:
environment: &base_node_small_env environment: &base_node_small_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 2 MAKEFLAGS: -j 2
CPUs: 2
- base_osx: &base_osx - base_osx: &base_osx
macos: macos:
@ -400,6 +446,7 @@ defaults:
environment: &base_osx_env environment: &base_osx_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j5 MAKEFLAGS: -j5
CPUs: 5
- base_osx_large: &base_osx_large - base_osx_large: &base_osx_large
<<: *base_osx <<: *base_osx
@ -407,6 +454,7 @@ defaults:
environment: &base_osx_large_env environment: &base_osx_large_env
<<: *base_osx_env <<: *base_osx_env
MAKEFLAGS: -j10 MAKEFLAGS: -j10
CPUs: 10
- base_python_small: &base_python_small - base_python_small: &base_python_small
docker: docker:
@ -415,6 +463,7 @@ defaults:
environment: &base_python_small_env environment: &base_python_small_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 2 MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu_clang: &base_ubuntu_clang - base_ubuntu_clang: &base_ubuntu_clang
docker: docker:
@ -422,6 +471,7 @@ defaults:
environment: &base_ubuntu_clang_env environment: &base_ubuntu_clang_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 3 MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu_clang_small: &base_ubuntu_clang_small - base_ubuntu_clang_small: &base_ubuntu_clang_small
<<: *base_ubuntu_clang <<: *base_ubuntu_clang
@ -429,6 +479,7 @@ defaults:
environment: &base_ubuntu_clang_small_env environment: &base_ubuntu_clang_small_env
<<: *base_ubuntu_clang_env <<: *base_ubuntu_clang_env
MAKEFLAGS: -j 2 MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu2004: &base_ubuntu2004 - base_ubuntu2004: &base_ubuntu2004
docker: docker:
@ -436,6 +487,7 @@ defaults:
environment: &base_ubuntu2004_env environment: &base_ubuntu2004_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 3 MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu2004_small: &base_ubuntu2004_small - base_ubuntu2004_small: &base_ubuntu2004_small
<<: *base_ubuntu2004 <<: *base_ubuntu2004
@ -443,6 +495,7 @@ defaults:
environment: &base_ubuntu2004_small_env environment: &base_ubuntu2004_small_env
<<: *base_ubuntu2004_env <<: *base_ubuntu2004_env
MAKEFLAGS: -j 2 MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu2004_xlarge: &base_ubuntu2004_xlarge - base_ubuntu2004_xlarge: &base_ubuntu2004_xlarge
<<: *base_ubuntu2004 <<: *base_ubuntu2004
@ -450,6 +503,7 @@ defaults:
environment: &base_ubuntu2004_xlarge_env environment: &base_ubuntu2004_xlarge_env
<<: *base_ubuntu2004_env <<: *base_ubuntu2004_env
MAKEFLAGS: -j 10 MAKEFLAGS: -j 10
CPUs: 10
- base_ubuntu2204: &base_ubuntu2204 - base_ubuntu2204: &base_ubuntu2204
docker: docker:
@ -457,6 +511,7 @@ defaults:
environment: &base_ubuntu2204_env environment: &base_ubuntu2204_env
TERM: xterm TERM: xterm
MAKEFLAGS: -j 3 MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu2204_clang: &base_ubuntu2204_clang - base_ubuntu2204_clang: &base_ubuntu2204_clang
docker: docker:
@ -466,6 +521,7 @@ defaults:
CC: clang CC: clang
CXX: clang++ CXX: clang++
MAKEFLAGS: -j 3 MAKEFLAGS: -j 3
CPUs: 3
- base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large - base_ubuntu2204_clang_large: &base_ubuntu2204_clang_large
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -473,6 +529,7 @@ defaults:
environment: &base_ubuntu2204_clang_large_env environment: &base_ubuntu2204_clang_large_env
<<: *base_ubuntu2204_clang_env <<: *base_ubuntu2204_clang_env
MAKEFLAGS: -j 5 MAKEFLAGS: -j 5
CPUs: 5
- base_ubuntu2204_small: &base_ubuntu2204_small - base_ubuntu2204_small: &base_ubuntu2204_small
<<: *base_ubuntu2204 <<: *base_ubuntu2204
@ -480,6 +537,7 @@ defaults:
environment: &base_ubuntu2204_small_env environment: &base_ubuntu2204_small_env
<<: *base_ubuntu2204_env <<: *base_ubuntu2204_env
MAKEFLAGS: -j 2 MAKEFLAGS: -j 2
CPUs: 2
- base_ubuntu2204_large: &base_ubuntu2204_large - base_ubuntu2204_large: &base_ubuntu2204_large
<<: *base_ubuntu2204 <<: *base_ubuntu2204
@ -487,6 +545,7 @@ defaults:
environment: &base_ubuntu2204_large_env environment: &base_ubuntu2204_large_env
<<: *base_ubuntu2204_env <<: *base_ubuntu2204_env
MAKEFLAGS: -j 5 MAKEFLAGS: -j 5
CPUs: 5
- base_ubuntu2204_xlarge: &base_ubuntu2204_xlarge - base_ubuntu2204_xlarge: &base_ubuntu2204_xlarge
<<: *base_ubuntu2204 <<: *base_ubuntu2204
@ -494,6 +553,7 @@ defaults:
environment: &base_ubuntu2204_xlarge_env environment: &base_ubuntu2204_xlarge_env
<<: *base_ubuntu2204_env <<: *base_ubuntu2204_env
MAKEFLAGS: -j 10 MAKEFLAGS: -j 10
CPUs: 10
- base_win: &base_win - base_win: &base_win
executor: executor:
@ -686,7 +746,7 @@ defaults:
name: t_native_test_ext_prb_math name: t_native_test_ext_prb_math
project: prb-math project: prb-math
binary_type: native binary_type: native
image: cimg/node:18.16 image: cimg/rust:1.70
- job_native_test_ext_elementfi: &job_native_test_ext_elementfi - job_native_test_ext_elementfi: &job_native_test_ext_elementfi
<<: *requires_b_ubu_static <<: *requires_b_ubu_static
@ -743,7 +803,11 @@ jobs:
pip install --user codespell pip install --user codespell
- run: - run:
name: Check spelling 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 - matrix_notify_failure_unless_pr
chk_docs_examples: chk_docs_examples:
@ -757,7 +821,7 @@ jobs:
command: sudo npm install -g solhint command: sudo npm install -g solhint
- run: - run:
name: Test Docs examples name: Test Docs examples
command: ./test/docsCodeStyle.sh command: test/docsCodeStyle.sh
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_coding_style: chk_coding_style:
@ -771,13 +835,13 @@ jobs:
sudo apt install -y shellcheck sudo apt install -y shellcheck
- run: - run:
name: Check for C++ coding style name: Check for C++ coding style
command: ./scripts/check_style.sh command: scripts/check_style.sh
- run: - run:
name: checking shell scripts name: checking shell scripts
command: ./scripts/chk_shellscripts/chk_shellscripts.sh command: scripts/chk_shellscripts/chk_shellscripts.sh
- run: - run:
name: Check for broken symlinks name: Check for broken symlinks
command: ./scripts/check_symlinks.sh command: scripts/check_symlinks.sh
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_errorcodes: chk_errorcodes:
@ -786,7 +850,7 @@ jobs:
- checkout - checkout
- run: - run:
name: Check for error codes name: Check for error codes
command: ./scripts/error_codes.py --check command: scripts/error_codes.py --check
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_pylint: chk_pylint:
@ -806,7 +870,7 @@ jobs:
- run: pylint --version - run: pylint --version
- run: - run:
name: Linting Python Scripts name: Linting Python Scripts
command: ./scripts/pylint_all.py command: scripts/pylint_all.py
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_antlr_grammar: chk_antlr_grammar:
@ -820,7 +884,7 @@ jobs:
sudo apt install -y openjdk-17-jdk sudo apt install -y openjdk-17-jdk
- run: - run:
name: Run tests name: Run tests
command: ./scripts/test_antlr_grammar.sh command: scripts/test_antlr_grammar.sh
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_buglist: chk_buglist:
@ -835,7 +899,7 @@ jobs:
npm install mktemp npm install mktemp
- run: - run:
name: Test buglist name: Test buglist
command: ./test/buglistTests.js command: test/buglistTests.js
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_proofs: chk_proofs:
@ -844,14 +908,14 @@ jobs:
- checkout - checkout
- install_python3: - install_python3:
packages: z3-solver packages: z3-solver
- run: *run_proofs - run_proofs
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_docs_pragma_min_version: chk_docs_pragma_min_version:
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
steps: steps:
- checkout - checkout
- run: *run_docs_pragma_min_version - run_docs_pragma_min_version
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_ubu_pyscripts: t_ubu_pyscripts:
@ -877,7 +941,8 @@ jobs:
# this runs 2x faster on xlarge but takes 4x more resources (compared to medium). # 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. # Enough other jobs depend on it that it's worth it though.
<<: *base_ubuntu2204_xlarge <<: *base_ubuntu2204_xlarge
<<: *steps_build steps:
- build
# x64 ASAN build, for testing for memory related bugs # x64 ASAN build, for testing for memory related bugs
b_ubu_asan: &b_ubu_asan b_ubu_asan: &b_ubu_asan
@ -887,14 +952,16 @@ jobs:
<<: *base_ubuntu2204_env <<: *base_ubuntu2204_env
CMAKE_OPTIONS: -DSANITIZE=address CMAKE_OPTIONS: -DSANITIZE=address
CMAKE_BUILD_TYPE: Release CMAKE_BUILD_TYPE: Release
<<: *steps_build steps:
- build
b_ubu_clang: &b_ubu_clang b_ubu_clang: &b_ubu_clang
<<: *base_ubuntu2204_clang_large <<: *base_ubuntu2204_clang_large
environment: environment:
<<: *base_ubuntu2204_clang_large_env <<: *base_ubuntu2204_clang_large_env
MAKEFLAGS: -j 10 MAKEFLAGS: -j 10
<<: *steps_build steps:
- build
b_ubu_san_clang: b_ubu_san_clang:
# This runs a bit faster on large and xlarge but on nightly efficiency matters more. # This runs a bit faster on large and xlarge but on nightly efficiency matters more.
@ -905,7 +972,8 @@ jobs:
environment: environment:
<<: *base_ubuntu2204_clang_env <<: *base_ubuntu2204_clang_env
CMAKE_OPTIONS: << parameters.cmake_options >> CMAKE_OPTIONS: << parameters.cmake_options >>
<<: *steps_build steps:
- build
b_ubu_force_release: &b_ubu_force_release b_ubu_force_release: &b_ubu_force_release
<<: *b_ubu <<: *b_ubu
@ -924,7 +992,7 @@ jobs:
CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON
steps: steps:
- checkout - checkout
- run: *run_build - run_build
- run: - run:
name: strip binary name: strip binary
command: strip build/solc/solc command: strip build/solc/solc
@ -947,8 +1015,8 @@ jobs:
CMAKE_BUILD_TYPE: Debug CMAKE_BUILD_TYPE: Debug
steps: steps:
- checkout - checkout
- run: *run_build - run_build
- persist_to_workspace: *artifacts_executables - persist_executables_to_workspace
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_ubu_codecov: t_ubu_codecov:
@ -967,11 +1035,11 @@ jobs:
- run: - run:
name: "Code Coverage: Syntax Tests" name: "Code Coverage: Syntax Tests"
command: codecov --flags syntax --gcov-root build command: codecov --flags syntax --gcov-root build
- run: *run_soltest - run_soltest
- run: - run:
name: "Coverage: All" name: "Coverage: All"
command: codecov --flags all --gcov-root build command: codecov --flags all --gcov-root build
- store_artifacts: *artifacts_test_results - store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
# Builds in C++20 mode and uses debug build in order to speed up. # Builds in C++20 mode and uses debug build in order to speed up.
@ -985,16 +1053,16 @@ jobs:
MAKEFLAGS: -j 10 MAKEFLAGS: -j 10
steps: steps:
- checkout - checkout
- run: *run_build - run_build
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
b_ubu_ossfuzz: &b_ubu_ossfuzz b_ubu_ossfuzz: &b_ubu_ossfuzz
<<: *base_ubuntu_clang <<: *base_ubuntu_clang
steps: steps:
- checkout - checkout
- run: *setup_prerelease_commit_hash - setup_prerelease_commit_hash
- run: *run_build_ossfuzz - run_build_ossfuzz
- persist_to_workspace: *artifacts_executables_ossfuzz - persist_ossfuzz_executables_to_workspace
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_ubu_ossfuzz: &t_ubu_ossfuzz t_ubu_ossfuzz: &t_ubu_ossfuzz
@ -1009,8 +1077,9 @@ jobs:
git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus
mkdir -p test_results mkdir -p test_results
scripts/regressions.py -o test_results scripts/regressions.py -o test_results
- store_test_results: *store_test_results - store_test_results:
- store_artifacts: *artifacts_test_results path: test_results/
- store_artifacts_test_results
b_archlinux: b_archlinux:
<<: *base_archlinux_large <<: *base_archlinux_large
@ -1024,9 +1093,9 @@ jobs:
command: | command: |
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar
- checkout - checkout
- run: *run_build - run_build
- store_artifacts: *artifacts_solc - store_artifacts_solc
- persist_to_workspace: *artifacts_executables - persist_executables_to_workspace
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
b_osx: b_osx:
@ -1036,18 +1105,11 @@ jobs:
CMAKE_BUILD_TYPE: Release CMAKE_BUILD_TYPE: Release
steps: steps:
- checkout - checkout
- when: - install_dependencies_osx
condition: true - run_build
<<: *steps_install_dependencies_osx - store_artifacts_solc
- run: *run_build - store_artifacts_yul_phaser
- store_artifacts: *artifacts_solc - persist_executables_to_workspace_osx
- 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 - matrix_notify_failure_unless_pr
t_osx_soltest: &t_osx_soltest t_osx_soltest: &t_osx_soltest
@ -1058,14 +1120,13 @@ jobs:
OPTIMIZE: 0 OPTIMIZE: 0
steps: steps:
- checkout - checkout
- when: - install_dependencies_osx
condition: true
<<: *steps_install_dependencies_osx
- attach_workspace: - attach_workspace:
at: . at: .
- run: *run_soltest - run_soltest
- store_test_results: *store_test_results - store_test_results:
- store_artifacts: *artifacts_test_results path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_osx_cli: t_osx_cli:
@ -1073,13 +1134,11 @@ jobs:
parallelism: 7 # Should match number of tests in .circleci/cli.sh parallelism: 7 # Should match number of tests in .circleci/cli.sh
steps: steps:
- checkout - checkout
- when: - install_dependencies_osx
condition: true
<<: *steps_install_dependencies_osx
- attach_workspace: - attach_workspace:
at: . at: .
- run: *run_cmdline_tests - run_cmdline_tests
- store_artifacts: *artifacts_test_results - store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
b_ems: b_ems:
@ -1110,10 +1169,10 @@ jobs:
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
steps: steps:
- checkout - checkout
- run: *setup_prerelease_commit_hash - setup_prerelease_commit_hash
- run: - run:
name: Build documentation name: Build documentation
command: ./docs/docs.sh command: docs/docs.sh
- store_artifacts: - store_artifacts:
path: docs/_build/html/ path: docs/_build/html/
destination: docs-html destination: docs-html
@ -1122,11 +1181,13 @@ jobs:
t_ubu_soltest_all: &t_ubu_soltest_all t_ubu_soltest_all: &t_ubu_soltest_all
<<: *base_ubuntu2204_large <<: *base_ubuntu2204_large
parallelism: 50 parallelism: 50
<<: *steps_soltest_all steps:
- soltest_all
t_ubu_lsp: &t_ubu_lsp t_ubu_lsp: &t_ubu_lsp
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
<<: *steps_test_lsp steps:
- test_lsp
t_archlinux_soltest: &t_archlinux_soltest t_archlinux_soltest: &t_archlinux_soltest
<<: *base_archlinux <<: *base_archlinux
@ -1143,9 +1204,7 @@ jobs:
name: Install runtime dependencies name: Install runtime dependencies
command: | command: |
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
- when: - soltest
condition: true
<<: *steps_soltest
t_ubu_clang_soltest: &t_ubu_clang_soltest t_ubu_clang_soltest: &t_ubu_clang_soltest
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -1157,7 +1216,8 @@ jobs:
# The high parallelism in this job is causing the SMT tests to run out of memory, # The high parallelism in this job is causing the SMT tests to run out of memory,
# so disabling for now. # so disabling for now.
SOLTEST_FLAGS: --no-smt SOLTEST_FLAGS: --no-smt
<<: *steps_soltest steps:
- soltest
t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all 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 # NOTE: This definition is identical to t_ubu_soltest_all but in the workflow we make it depend on
@ -1167,7 +1227,8 @@ jobs:
t_ubu_cli: &t_ubu_cli t_ubu_cli: &t_ubu_cli
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
parallelism: 7 # Should match number of tests in .circleci/cli.sh 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_force_release_cli: &t_ubu_force_release_cli
<<: *t_ubu_cli <<: *t_ubu_cli
@ -1191,7 +1252,8 @@ jobs:
# Suppress CLN memory leak. # Suppress CLN memory leak.
# See: https://github.com/ethereum/solidity/issues/13891 for details. # See: https://github.com/ethereum/solidity/issues/13891 for details.
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0 LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0
<<: *steps_cmdline_tests steps:
- cmdline_tests
t_ubu_asan_soltest: t_ubu_asan_soltest:
<<: *base_ubuntu2204 <<: *base_ubuntu2204
@ -1205,7 +1267,8 @@ jobs:
# Suppress CLN memory leak. # Suppress CLN memory leak.
# See: https://github.com/ethereum/solidity/issues/13891 for details. # See: https://github.com/ethereum/solidity/issues/13891 for details.
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp
<<: *steps_soltest steps:
- soltest
t_ubu_asan_clang_soltest: t_ubu_asan_clang_soltest:
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -1216,7 +1279,8 @@ jobs:
OPTIMIZE: 0 OPTIMIZE: 0
SOLTEST_FLAGS: --no-smt 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 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: t_ubu_ubsan_clang_soltest:
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -1225,12 +1289,14 @@ jobs:
<<: *base_ubuntu2204_clang_env <<: *base_ubuntu2204_clang_env
EVM: << pipeline.parameters.evm-version >> EVM: << pipeline.parameters.evm-version >>
SOLTEST_FLAGS: --no-smt SOLTEST_FLAGS: --no-smt
<<: *steps_soltest steps:
- soltest
t_ubu_ubsan_clang_cli: t_ubu_ubsan_clang_cli:
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
parallelism: 7 # Should match number of tests in .circleci/cli.sh parallelism: 7 # Should match number of tests in .circleci/cli.sh
<<: *steps_cmdline_tests steps:
- cmdline_tests
t_ems_solcjs: t_ems_solcjs:
# Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small). # Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small).
@ -1454,7 +1520,8 @@ jobs:
name: "Run solc.exe to make sure build was successful." name: "Run solc.exe to make sure build was successful."
command: .\build\solc\Release\solc.exe --version command: .\build\solc\Release\solc.exe --version
shell: powershell.exe shell: powershell.exe
- store_artifacts: *artifact_solc_windows - store_artifacts:
path: upload/
- persist_to_workspace: - persist_to_workspace:
root: build root: build
paths: paths:
@ -1483,10 +1550,11 @@ jobs:
command: python -m pip install --user deepdiff colorama command: python -m pip install --user deepdiff colorama
- run: - run:
name: Executing solc LSP test suite 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 shell: powershell.exe
- store_test_results: *store_test_results - store_test_results:
- store_artifacts: *artifacts_test_results path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
# Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu # Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu
@ -1719,11 +1787,13 @@ workflows:
- t_native_test_ext_yield_liquidator - t_native_test_ext_yield_liquidator
- t_native_test_ext_perpetual_pools - t_native_test_ext_perpetual_pools
- t_native_test_ext_uniswap - t_native_test_ext_uniswap
- t_native_test_ext_prb_math
- t_native_test_ext_elementfi - t_native_test_ext_elementfi
- t_native_test_ext_brink - t_native_test_ext_brink
# NOTE: We are disabling gp2 tests due to constant failures. # NOTE: We are disabling gp2 tests due to constant failures.
#- t_native_test_ext_gp2 #- 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 # NOTE: The external tests below were commented because they
# depend on a specific version of hardhat which does not support shanghai EVM. # depend on a specific version of hardhat which does not support shanghai EVM.
#- t_native_test_ext_trident #- t_native_test_ext_trident

View File

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

View File

@ -44,6 +44,9 @@ cd test-cases/
echo "Preparing input files" echo "Preparing input files"
python3 ../scripts/isolate_tests.py ../test/ python3 ../scripts/isolate_tests.py ../test/
# FIXME: These cases crash because of https://github.com/ethereum/solidity/issues/13583
rm ./*_bytecode_too_large_*.sol ./*_combined_too_large_*.sol
if [[ $binary_type == native ]]; then if [[ $binary_type == native ]]; then
interface=$(echo -e "standard-json\ncli" | circleci tests split) interface=$(echo -e "standard-json\ncli" | circleci tests split)
echo "Selected interface: ${interface}" echo "Selected interface: ${interface}"

View File

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

View File

@ -6,42 +6,16 @@ on:
- opened - opened
env: env:
ORGANIZATION: Ethereum
DRY_RUN: false DRY_RUN: false
jobs: jobs:
comment-external-pr: comment-external-pr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Get organization members # Note: this step requires that the INTERNAL_CONTRIBUTORS environment variable
id: get_members # is already defined in the repository with the current json list of internal contributors.
env:
GH_TOKEN: ${{ secrets.READ_ORG }}
CONTRIBUTOR: ${{ github.event.pull_request.user.login }}
run: |
gh api graphql \
--raw-field organization="$ORGANIZATION" \
--raw-field query='
query($organization: String!) {
organization(login: $organization) {
team(slug: "Solidity") {
members(first: 100) {
nodes {
login
}
}
}
}
}' > org_members.json
echo "CONTRIBUTOR_IS_ORG_MEMBER=$(
jq \
--arg contributor $CONTRIBUTOR \
'.data.organization.team.members | any(.nodes[].login; . == $contributor)' \
org_members.json
)" >> $GITHUB_OUTPUT
- name: Comment on external contribution PR - name: Comment on external contribution PR
if: ${{ steps.get_members.outputs.CONTRIBUTOR_IS_ORG_MEMBER == 'false' }} if: "!contains(fromJSON(vars.INTERNAL_CONTRIBUTORS), github.event.pull_request.user.login)"
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.html_url }} PR: ${{ github.event.pull_request.html_url }}

View File

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

View File

@ -51,11 +51,11 @@ To set indentation and tab width settings uniformly, the repository contains an
## 1. Namespaces ## 1. Namespaces
1. No `using namespace` declarations in header files. 1. No `using namespace` declarations in header files.
2. Use `using namespace std;` in cpp files, but avoid importing namespaces from boost and others. 2. `using namespace solidity;` and other project local namespaces is fine in cpp files, and generally encouraged.
3. All symbols should be declared in a namespace except for final applications. 3. Avoid `using namespace` at file level for third party libraries, such as boost, ranges, etc.
4. Use anonymous namespaces for helpers whose scope is a cpp file only. 4. All symbols should be declared in a namespace except for final applications.
5. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore. 5. Use anonymous namespaces for helpers whose scope is a cpp file only.
6. Do not use `std::` qualifier in cpp files (see 2.), except for `std::move` and `std::forward`, which will otherwise cause the `check_style` step to fail. 6. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
Only in the header: Only in the header:
```cpp ```cpp
@ -66,16 +66,6 @@ std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
} }
``` ```
Only in the cpp file:
```cpp
#include <cassert>
using namespace std;
tuple<float, float> myNamespace::meanAndSigma(vector<float> const& _v)
{
// ...
}
```
## 2. Preprocessor ## 2. Preprocessor
1. File comment is always at top, and includes: 1. File comment is always at top, and includes:

View File

@ -1,7 +1,34 @@
### 0.8.21 (unreleased) ### 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:
* Code Generator: Always generate code for the expression in ``<expression>.selector`` in the legacy code generation pipeline.
* Yul Optimizer: Fix ``FullInliner`` step (``i``) not preserving the evaluation order of arguments passed into inlined functions in code that is not in expression-split form (i.e. when using a custom optimizer sequence in which the step not preceded by ``ExpressionSplitter`` (``x``)).
Language Features: Language Features:
* Allow qualified access to events from other contracts. * Allow qualified access to events from other contracts.
* Relax restrictions on initialization of immutable variables. Reads and writes may now happen at any point at construction time outside of functions and modifiers. Explicit initialization is no longer mandatory.
Compiler Features: Compiler Features:
* Commandline Interface: Add ``--ast-compact-json`` output in assembler mode. * Commandline Interface: Add ``--ast-compact-json`` output in assembler mode.
@ -9,23 +36,31 @@ Compiler Features:
* Commandline Interface: Respect ``--optimize-yul`` and ``--no-optimize-yul`` in compiler mode and accept them in assembler mode as well. ``--optimize --no-optimize-yul`` combination now allows enabling EVM assembly optimizer without enabling Yul optimizer. * Commandline Interface: Respect ``--optimize-yul`` and ``--no-optimize-yul`` in compiler mode and accept them in assembler mode as well. ``--optimize --no-optimize-yul`` combination now allows enabling EVM assembly optimizer without enabling Yul optimizer.
* EWasm: Remove EWasm backend. * EWasm: Remove EWasm backend.
* Parser: Introduce ``pragma experimental solidity``, which will enable an experimental language mode that in particular has no stability guarantees between non-breaking releases and is not suited for production use. * Parser: Introduce ``pragma experimental solidity``, which will enable an experimental language mode that in particular has no stability guarantees between non-breaking releases and is not suited for production use.
* SMTChecker: Add ``--model-checker-print-query`` CLI option and ``settings.modelChecker.printQuery`` JSON option to output the SMTChecker queries in the SMTLIB2 format. This requires using `smtlib2` solver only. * SMTChecker: Add ``--model-checker-print-query`` CLI option and ``settings.modelChecker.printQuery`` JSON option to output the SMTChecker queries in the SMTLIB2 format. This requires using ``smtlib2`` solver only.
* Standard JSON Interface: Add ``ast`` file-level output for Yul input. * Standard JSON Interface: Add ``ast`` file-level output for Yul input.
* Standard JSON Interface: Add ``irAst`` and ``irOptimizedAst`` contract-level outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR. * Standard JSON Interface: Add ``irAst`` and ``irOptimizedAst`` contract-level outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR.
* Yul Optimizer: Remove experimental `ReasoningBasedSimplifier` optimization step. * Yul Optimizer: Remove experimental ``ReasoningBasedSimplifier`` optimization step.
* Yul Optimizer: Stack-to-memory mover is now enabled by default whenever possible for via IR code generation and pure Yul compilation. * Yul Optimizer: Stack-to-memory mover is now enabled by default whenever possible for via IR code generation and pure Yul compilation.
Bugfixes: Bugfixes:
* Code Generator: Disallow complex expressions whose results are types, built-ins, modules or some unassignable functions. The legacy code generation pipeline would not actually evaluate them, discarding any side-effects they might have.
* Code Generator: Fix not entirely deterministic order of functions in unoptimized Yul output. The choice of C++ compiler in some cases would result in different (but equivalent) bytecode (especially from native binaries vs emscripten binaries).
* Commandline Interface: Fix internal error when using ``--stop-after parsing`` and requesting some of the outputs that require full analysis or compilation. * Commandline Interface: Fix internal error when using ``--stop-after parsing`` and requesting some of the outputs that require full analysis or compilation.
* Commandline Interface: It is no longer possible to specify both ``--optimize-yul`` and ``--no-optimize-yul`` at the same time. * Commandline Interface: It is no longer possible to specify both ``--optimize-yul`` and ``--no-optimize-yul`` at the same time.
* SMTChecker: Fix encoding of side-effects inside ``if`` and ``ternary conditional``statements in the BMC engine. * SMTChecker: Fix encoding of side-effects inside ``if`` and ``ternary conditional``statements in the BMC engine.
* SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function. * SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function.
* SMTChecker: Fix generation of invalid SMT-LIB2 scripts in BMC engine with trusted mode for external calls when CHC engine times out.
* SMTChecker: Fix internal error caused by incorrectly classifying external function call using function pointer as a public getter.
* SMTChecker: Fix internal error caused by using external identifier to encode member access to functions that take an internal function as a parameter. * SMTChecker: Fix internal error caused by using external identifier to encode member access to functions that take an internal function as a parameter.
* Standard JSON Interface: Fix an incomplete AST being returned when analysis is interrupted by certain kinds of fatal errors. * Standard JSON Interface: Fix an incomplete AST being returned when analysis is interrupted by certain kinds of fatal errors.
* Type Checker: Disallow using certain unassignable function types in complex expressions.
* Type Checker: Function declaration types referring to different declarations are no longer convertible to each other.
* Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation. * Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation.
* Yul Optimizer: Fix ``FullInliner`` step not ignoring code that is not in expression-split form.
* Yul Optimizer: Fix optimized IR being unnecessarily passed through the Yul optimizer again before bytecode generation. * Yul Optimizer: Fix optimized IR being unnecessarily passed through the Yul optimizer again before bytecode generation.
AST Changes: AST Changes:
* AST: Add the ``experimentalSolidity`` field to the ``SourceUnit`` nodes, which indicate whether the experimental parsing mode has been enabled via ``pragma experimental solidity``. * AST: Add the ``experimentalSolidity`` field to the ``SourceUnit`` nodes, which indicate whether the experimental parsing mode has been enabled via ``pragma experimental solidity``.

View File

@ -3,9 +3,9 @@
### Requirements ### Requirements
- [ ] GitHub account with access to [solidity](https://github.com/ethereum/solidity), [solc-js](https://github.com/ethereum/solc-js), - [ ] 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), [solc-bin](https://github.com/ethereum/solc-bin), [homebrew-ethereum](https://github.com/ethereum/homebrew-ethereum),
[solidity-blog](https://github.com/ethereum/solidity-blog) and [solidity-portal](https://github.com/ethereum/solidity-portal) repositories. [solidity-website](https://github.com/ethereum/solidity-website).
- [ ] DockerHub account with push rights to the [``solc`` image](https://hub.docker.com/r/ethereum/solc). - [ ] DockerHub account with push rights to the [``solc`` image](https://hub.docker.com/r/ethereum/solc).
- [ ] Lauchpad (Ubuntu One) account with a membership in the ["Ethereum" team](https://launchpad.net/~ethereum) and - [ ] Launchpad (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). 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``. - [ ] 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). - [ ] [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. - [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements.
### Blog Post ### Blog Post
- [ ] 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-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-blog](https://github.com/ethereum/solidity-blog) in the ``Security Alerts`` category in case of important bug(s). - [ ] 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).
### Changelog ### Changelog
- [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it. - [ ] 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. - [ ] 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. 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). - [ ] Remove "still in progress" warning from the [release notes](https://github.com/ethereum/solidity/releases).
- [ ] Merge the [blog posts](https://github.com/ethereum/solidity-blog/pulls) related to the release. - [ ] Merge the [blog posts](https://github.com/ethereum/solidity-website/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. - [ ] 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-portal/blob/master/index.html). - [ ] Update the release information section [in the source of soliditylang.org](https://github.com/ethereum/solidity-website/blob/main/src/pages/index.tsx).
- [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - [ ] 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. - [ ] 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/). - [ ] 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 fmtlib
PREFIX "${PROJECT_BINARY_DIR}/deps" PREFIX "${PROJECT_BINARY_DIR}/deps"
DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads" DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads"
DOWNLOAD_NAME fmt-8.0.1.tar.gz DOWNLOAD_NAME fmt-9.1.0.tar.gz
URL https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz URL https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
URL_HASH SHA256=b06ca3130158c625848f3fb7418f235155a4d389b2abc3a6245fb01cb0eb1e01 URL_HASH SHA256=5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
) )
if (CMAKE_VERSION VERSION_LESS "3.14.0") 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. 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 the deprecated old error reporter. It is enabled by default, but passing ``--old-reporter`` falls back to the deprecated old error reporter.
Metadata Hash Options Metadata Hash Options
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~

23
docs/README.md Normal file
View File

@ -0,0 +1,23 @@
# Solidity Language Docs
## Local environment setup
1. Install python https://www.python.org/downloads/
1. Install sphinx (the tool used to generate the docs) https://www.sphinx-doc.org/en/master/usage/installation.html
Go to `/docs` and run `./docs.sh` to install dependencies and build the project:
```sh
cd docs
./docs.sh
```
That will output the generated htmls under _build/
## Serve environment
```py
python3 -m http.server -d _build/html --cgi 8080
```
Visit dev server at http://localhost:8080

595
docs/_static/css/custom-dark.css vendored Normal file
View File

@ -0,0 +1,595 @@
/* DARK MODE STYLING */
/* code directives */
:root[style*=dark] .method dt,
:root[style*=dark] .class dt,
:root[style*=dark] .data dt,
:root[style*=dark] .attribute dt,
:root[style*=dark] .function dt,
:root[style*=dark] .classmethod dt,
:root[style*=dark] .exception dt,
:root[style*=dark] .descclassname,
:root[style*=dark] .descname {
background-color: #2d2d2d !important;
}
:root[style*=dark] .rst-content dl:not(.docutils) dt {
background-color: #0008;
border-top: solid 3px #fff2;
border-left: solid 3px #fff2;
}
:root[style*=dark] em.property {
color: #888888;
}
/* tables */
:root[style*=dark] .rst-content table.docutils td {
border: 0px;
}
:root[style*=dark] .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td {
background-color: #0002;
}
:root[style*=dark] .rst-content pre {
background: none;
}
/* inlined code highlights */
:root[style*=dark] .xref,
:root[style*=dark] .py-meth {
color: #aaddff !important;
font-weight: normal !important;
}
/* highlight color search text */
:root[style*=dark] .rst-content .highlighted {
background: #ff5722;
box-shadow: 0 0 0 2px #f0978b;
}
/* notes, warnings, hints */
:root[style*=dark] .hint .admonition-title {
background: #2aa87c !important;
}
:root[style*=dark] .warning .admonition-title {
background: #cc4444 !important;
}
:root[style*=dark] .admonition-title {
background: #3a7ca8 !important;
}
:root[style*=dark] .admonition,
:root[style*=dark] .note {
background-color: #0008 !important;
}
/* table of contents */
:root[style*=dark] .sidebar {
background-color: #191919 !important;
}
:root[style*=dark] .sidebar-title {
background-color: #2b2b2b !important;
}
:root[style*=dark] .wy-menu-vertical code.docutils.literal.notranslate {
background: none !important;
border: none !important;
}
:root[style*=dark] .toc-backref {
color: grey !important;
}
:root[style*=dark] .highlight {
background: #0008;
color: #f8f8f2
}
:root[style*=dark] .highlight .c {
color: #888
}
/* Comment */
:root[style*=dark] .highlight .err {
color: #960050;
background-color: #1e0010
}
/* Error */
:root[style*=dark] .highlight .k {
color: #66d9ef
}
/* Keyword */
:root[style*=dark] .highlight .l {
color: #ae81ff
}
/* Literal */
:root[style*=dark] .highlight .n {
color: #f8f8f2
}
/* Name */
:root[style*=dark] .highlight .o {
color: #f92672
}
/* Operator */
:root[style*=dark] .highlight .p {
color: #f8f8f2
}
/* Punctuation */
:root[style*=dark] .highlight .ch {
color: #888
}
/* Comment.Hashbang */
:root[style*=dark] .highlight .cm {
color: #888
}
/* Comment.Multiline */
:root[style*=dark] .highlight .cp {
color: #888
}
/* Comment.Preproc */
:root[style*=dark] .highlight .cpf {
color: #888
}
/* Comment.PreprocFile */
:root[style*=dark] .highlight .c1 {
color: #888
}
/* Comment.Single */
:root[style*=dark] .highlight .cs {
color: #888
}
/* Comment.Special */
:root[style*=dark] .highlight .gd {
color: #f92672
}
/* Generic.Deleted */
:root[style*=dark] .highlight .ge {
font-style: italic
}
/* Generic.Emph */
:root[style*=dark] .highlight .gi {
color: #a6e22e
}
/* Generic.Inserted */
:root[style*=dark] .highlight .gs {
font-weight: bold
}
/* Generic.Strong */
:root[style*=dark] .highlight .gu {
color: #888
}
/* Generic.Subheading */
:root[style*=dark] .highlight .kc {
color: #66d9ef
}
/* Keyword.Constant */
:root[style*=dark] .highlight .kd {
color: #66d9ef
}
/* Keyword.Declaration */
:root[style*=dark] .highlight .kn {
color: #f92672
}
/* Keyword.Namespace */
:root[style*=dark] .highlight .kp {
color: #66d9ef
}
/* Keyword.Pseudo */
:root[style*=dark] .highlight .kr {
color: #66d9ef
}
/* Keyword.Reserved */
:root[style*=dark] .highlight .kt {
color: #66d9ef
}
/* Keyword.Type */
:root[style*=dark] .highlight .ld {
color: #e6db74
}
/* Literal.Date */
:root[style*=dark] .highlight .m {
color: #ae81ff
}
/* Literal.Number */
:root[style*=dark] .highlight .s {
color: #e6db74
}
/* Literal.String */
:root[style*=dark] .highlight .na {
color: #a6e22e
}
/* Name.Attribute */
:root[style*=dark] .highlight .nb {
color: #f8f8f2
}
/* Name.Builtin */
:root[style*=dark] .highlight .nc {
color: #a6e22e
}
/* Name.Class */
:root[style*=dark] .highlight .no {
color: #66d9ef
}
/* Name.Constant */
:root[style*=dark] .highlight .nd {
color: #a6e22e
}
/* Name.Decorator */
:root[style*=dark] .highlight .ni {
color: #f8f8f2
}
/* Name.Entity */
:root[style*=dark] .highlight .ne {
color: #a6e22e
}
/* Name.Exception */
:root[style*=dark] .highlight .nf {
color: #a6e22e
}
/* Name.Function */
:root[style*=dark] .highlight .nl {
color: #f8f8f2
}
/* Name.Label */
:root[style*=dark] .highlight .nn {
color: #f8f8f2
}
/* Name.Namespace */
:root[style*=dark] .highlight .nx {
color: #a6e22e
}
/* Name.Other */
:root[style*=dark] .highlight .py {
color: #f8f8f2
}
/* Name.Property */
:root[style*=dark] .highlight .nt {
color: #f92672
}
/* Name.Tag */
:root[style*=dark] .highlight .nv {
color: #f8f8f2
}
/* Name.Variable */
:root[style*=dark] .highlight .ow {
color: #f92672
}
/* Operator.Word */
:root[style*=dark] .highlight .w {
color: #f8f8f2
}
/* Text.Whitespace */
:root[style*=dark] .highlight .mb {
color: #ae81ff
}
/* Literal.Number.Bin */
:root[style*=dark] .highlight .mf {
color: #ae81ff
}
/* Literal.Number.Float */
:root[style*=dark] .highlight .mh {
color: #ae81ff
}
/* Literal.Number.Hex */
:root[style*=dark] .highlight .mi {
color: #ae81ff
}
/* Literal.Number.Integer */
:root[style*=dark] .highlight .mo {
color: #ae81ff
}
/* Literal.Number.Oct */
:root[style*=dark] .highlight .sa {
color: #e6db74
}
/* Literal.String.Affix */
:root[style*=dark] .highlight .sb {
color: #e6db74
}
/* Literal.String.Backtick */
:root[style*=dark] .highlight .sc {
color: #e6db74
}
/* Literal.String.Char */
:root[style*=dark] .highlight .dl {
color: #e6db74
}
/* Literal.String.Delimiter */
:root[style*=dark] .highlight .sd {
color: #e6db74
}
/* Literal.String.Doc */
:root[style*=dark] .highlight .s2 {
color: #e6db74
}
/* Literal.String.Double */
:root[style*=dark] .highlight .se {
color: #ae81ff
}
/* Literal.String.Escape */
:root[style*=dark] .highlight .sh {
color: #e6db74
}
/* Literal.String.Heredoc */
:root[style*=dark] .highlight .si {
color: #e6db74
}
/* Literal.String.Interpol */
:root[style*=dark] .highlight .sx {
color: #e6db74
}
/* Literal.String.Other */
:root[style*=dark] .highlight .sr {
color: #e6db74
}
/* Literal.String.Regex */
:root[style*=dark] .highlight .s1 {
color: #e6db74
}
/* Literal.String.Single */
:root[style*=dark] .highlight .ss {
color: #e6db74
}
/* Literal.String.Symbol */
:root[style*=dark] .highlight .bp {
color: #f8f8f2
}
/* Name.Builtin.Pseudo */
:root[style*=dark] .highlight .fm {
color: #a6e22e
}
/* Name.Function.Magic */
:root[style*=dark] .highlight .vc {
color: #f8f8f2
}
/* Name.Variable.Class */
:root[style*=dark] .highlight .vg {
color: #f8f8f2
}
/* Name.Variable.Global */
:root[style*=dark] .highlight .vi {
color: #f8f8f2
}
/* Name.Variable.Instance */
:root[style*=dark] .highlight .vm {
color: #f8f8f2
}
/* Name.Variable.Magic */
:root[style*=dark] .highlight .il {
color: #ae81ff
}
/* Grammar */
:root[style*=dark] .railroad-diagram {
fill: white;
}
:root[style*=dark] .railroad-diagram path {
stroke: white;
}
:root[style*=dark] .railroad-diagram rect {
stroke: white;
}
:root[style*=dark] .a4 .sig-name {
background-color: transparent !important;
}

View File

@ -1,9 +1,173 @@
/* ROOT DECLARATIONS */
:root {
/* Text */
--color-a: #2B247C;
--color-b: #672AC8;
--color-c: #5554D9;
--color-d: #9F94E8;
--color-e: #AEC0F1;
--color-f: #E6E3EC;
/* Background */
--white: #FAF8FF;
--black: #110C4E;
--menu-bg: #2B247C06;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--navHeight: 4.5rem;
--sideWidth: 300px;
--maxWidth: 80rem;
--desktopInlinePadding: 2rem;
--mobileInlinePadding: 1rem;
--currentVersionHeight: 45px;
text-rendering: geometricPrecision;
-webkit-font-smoothing: antialiased;
}
a,
button {
border-radius: 0;
}
:root[style*=dark] {
--color-a: #E6E3EC !important;
--color-b: #AEC0F1 !important;
--color-c: #9F94E8 !important;
--color-d: #5554D9 !important;
--color-e: #672AC8 !important;
--color-f: #2B247C !important;
--white: #110C4E !important;
--black: #FAF8FF !important;
--menu-bg: #E6E3EC06 !important;
}
html,
body,
.unified-header::before,
.wy-nav-side,
.rst-versions,
code,
div,
input[type=text],
a,
.wy-grid-for-nav {
transition: background 150ms ease-in-out;
}
html,
body,
.wy-grid-for-nav {
background-color: var(--color-f) !important;
}
body {
font-family: "Overpass", sans-serif;
}
a {
color: var(--color-c);
}
a, section {
scroll-margin-top: calc(var(--navHeight) + 2rem);
}
hr {
margin-block: 2rem;
border-color: var(--color-d) !important;
}
/* HEADER STYLES */
h1 {
font-family: 'Overpass', sans-serif;
font-weight: 700;
font-size: 44px;
color: var(--color-a) !important;
line-height: 1.1;
text-wrap: balance;
margin-top: 4rem;
margin-bottom: 1.5rem;
}
section:first-of-type h1:first-of-type {
font-family: 'Overpass mono', monospace;
font-size: 48px;
margin-top: 3rem;
margin-bottom: 5rem;
}
h2 {
font-family: 'Overpass', sans-serif;
font-weight: 700;
font-size: 38px;
color: var(--color-a) !important;
line-height: 46px;
text-wrap: balance;
margin-top: 4rem;
margin-bottom: 1.5rem;
}
*:not([role=navigation])>p[role=heading]>span,
h3 {
font-family: 'Overpass', sans-serif;
font-weight: 700;
font-size: 32px;
color: var(--color-a) !important;
line-height: 46px;
text-wrap: balance;
margin-top: 4rem;
margin-bottom: 1.5rem;
}
h4 {
font-family: 'Overpass', sans-serif;
font-weight: 700;
font-size: 32px;
color: var(--color-a) !important;
line-height: 46px;
text-wrap: balance;
margin-top: 3rem;
margin-bottom: 1.5rem;
}
h5 {
font-family: 'Overpass', sans-serif;
font-weight: 700;
font-size: 18px;
color: var(--color-a) !important;
line-height: 1.4;
text-wrap: balance;
}
h6 {
font-family: 'Overpass', sans-serif;
font-weight: 700;
font-size: 16px;
color: var(--color-a) !important;
line-height: 1.4;
text-wrap: balance;
}
span.pre,
pre { pre {
white-space: pre-wrap; /* css-3 */ /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: pre-wrap;
white-space: -pre-wrap; /* Opera 4-6 */ /* Mozilla, since 1999 */
white-space: -o-pre-wrap; /* Opera 7 */ white-space: -moz-pre-wrap;
/* Opera 4-6 */
white-space: -pre-wrap;
/* Opera 7 */
white-space: -o-pre-wrap;
word-wrap: break-word; word-wrap: break-word;
font-family: 'Overpass Mono', monospace;
}
small,
small * {
font-size: 12px;
} }
.wy-table-responsive table td, .wy-table-responsive table td,
@ -16,10 +180,6 @@ pre {
} }
/* links */ /* links */
.rst-content a:not(:visited) {
color: #002fa7;
}
.rst-content .highlighted { .rst-content .highlighted {
background: #eac545; background: #eac545;
} }
@ -29,24 +189,12 @@ pre {
background: #fafafa; background: #fafafa;
} }
.wy-side-nav-search > a img.logo {
width: 100px;
padding: 0;
}
.wy-side-nav-search > a {
padding: 0;
margin: 0;
}
/* project version (displayed under project logo) */ /* project version (displayed under project logo) */
.wy-side-nav-search > div.version { .wy-side-nav-search>div.version {
color: #272525; color: var(--color-b);
} margin-top: 0;
margin-bottom: 0.5rem;
/* menu section headers */ text-align: start;
.wy-menu p.caption {
color: #65afff;
} }
/* Link to Remix IDE shown next to code snippets */ /* Link to Remix IDE shown next to code snippets */
@ -58,18 +206,621 @@ pre {
} }
.rst-content .remix-link-container a.remix-link { .rst-content .remix-link-container a.remix-link {
display: inline-block;
font-size: 0.7em; font-size: 0.7em;
padding: 0.1em 0.4em; padding: 0.1em 0.5em;
background: #e1e4e5; background: transparent;
color: #707070; color: var(--color-a) !important;
} border: 1px solid var(--color-a);
text-decoration: none;
.rst-content .remix-link-container a.remix-link:hover {
background: #c8cbcc;
} }
.rst-content div.highlight-solidity, .rst-content div.highlight-solidity,
.rst-content div.highlight-yul { .rst-content div.highlight-yul {
margin-top: 0; margin-top: 0;
} }
/* CUSTOMIZATION UPDATES */
.wy-nav-content-wrap,
.wy-nav-content {
background: transparent !important;
}
.wy-side-nav-search {
background-color: transparent !important;
color: var(--color-a) !important;
box-shadow: 0 4 4 0 var(--color-a);
border-bottom: 1px solid var(--color-d) !important;
}
.wy-side-nav-search svg {
color: var(--color-a) !important;
}
.wy-nav-top {
background-color: transparent !important;
color: var(--color-a) !important;
}
.wy-nav-top a {
color: var(--color-a) !important;
}
.wy-breadcrumbs a.icon-home:before {
content: "Documentation";
font-family: "Overpass", sans-serif;
}
.rst-content table.docutils thead {
color: var(--color-a);
}
code.docutils.literal.notranslate {
padding: 2px 4px;
font-size: 0.875em;
font-family: "Overpass Mono", monospace;
background: var(--white);
color: var(--color-c);
border: 0px;
}
dt code.docutils.literal.notranslate {
background: none;
}
.wy-nav-content {
color: var(--color-a);
}
/* .rst-content a:not(:visited) { */
/* color: var(--color-b) !important; */
/* } */
.rst-content a:visited {
color: var(--color-c) !important;
}
.rst-content a {
text-decoration: underline;
}
.rst-content a:where(:focus, :focus-visible, :hover) {
color: var(--color-d) !important;
}
.wy-side-scroll a {
color: var(--color-a);
background: transparent;
font-size: 1rem;
line-height: 125%;
}
.wy-menu-vertical li.current a,
.wy-menu-vertical li.current li a,
.wy-menu-vertical li.current li a code {
border: none;
color: var(--color-a);
}
ul.current ul,
.wy-menu-vertical li.current a:hover,
.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,
.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,
.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,
.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,
.wy-menu-vertical li.current {
background: var(--menu-bg) !important;
}
.wy-menu.wy-menu-vertical>ul {
margin-bottom: 3rem;
}
.wy-menu.wy-menu-vertical>p {
color: var(--color-c);
}
.wy-menu-vertical li.on a,
.wy-menu-vertical li.current>a {
background: var(--menu-bg) !important;
border-bottom: 0px !important;
border-top: 0px !important;
}
.btn {
border-radius: 0;
text-decoration: none !important;
}
.wy-breadcrumbs-aside a,
.wy-breadcrumbs-aside a:visited,
a.fa.fa-github,
a.fa.fa-github:visited,
a.fa.fa-github:not(:visited),
a.btn.btn-neutral:visited,
a.btn.btn-neutral:not(:visited),
a.btn.btn-neutral {
background: transparent !important;
color: var(--color-a) !important;
border: 2px solid var(--color-a) !important;
text-decoration: none;
}
.rst-content .remix-link-container a.remix-link:hover,
.wy-breadcrumbs-aside a:hover,
a.fa.fa-github:hover,
a.btn.btn-neutral:hover {
background: var(--white) !important;
color: var(--color-b) !important;
border-color: var(--color-b) !important;
}
footer .rst-footer-buttons {
display: flex;
justify-content: center;
gap: 2rem;
}
/**
* Customization for the unified layout
*/
/* Site wrapper, and two children: header and rest */
.unified-wrapper {
position: relative;
display: flex;
flex-direction: column;
inset: 0;
max-width: var(--maxWidth);
margin-inline: auto;
}
/* Site header */
.unified-header {
position: fixed;
top: 0;
inset-inline: 0;
z-index: 99999;
display: flex;
align-items: center;
box-shadow: var(--shadow);
}
.unified-header .inner-header {
display: flex;
margin-inline: auto;
width: 100%;
max-width: var(--maxWidth);
align-items: center;
justify-content: space-between;
padding-inline: var(--desktopInlinePadding);
padding-block: 1rem;
}
.unified-header::before {
content: "";
position: absolute;
inset: 0;
opacity: 95%;
background: var(--color-f);
z-index: -1;
backdrop-filter: blur(3px);
}
.unified-header .home-link {
display: block;
text-decoration: none;
width: 25px;
height: 40px;
}
.unified-header .home-link:hover .solidity-logo {
transform: scale(1.1);
transition: transform 100ms ease-in-out;
}
.unified-header img.solidity-logo {
transform: scale(1);
transition: transform 100ms ease-in-out;
width: 100%;
height: 100%;
}
.unified-header .nav-bar {
display: flex;
align-items: center;
justify-content: flex-end;
}
.unified-header .nav-bar .nav-button-container {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.unified-header .nav-link {
display: inline-block;
padding-inline: 8px;
padding-block: 4px;
font-size: 14px;
font-family: 'Overpass Mono', monospace;
text-decoration: none;
color: var(--color-a);
letter-spacing: -0.02em;
font-weight: 400;
box-sizing: content-box;
border-bottom: 1px solid transparent;
white-space: nowrap;
}
.unified-header .nav-link.active {
background: var(--white);
}
.unified-header .nav-link:hover {
color: var(--color-c);
border-bottom: 1px solid var(--color-c);
}
/* Rest: Flex-row, with two children: side bar, and content */
.unified-wrapper .wy-grid-for-nav {
position: relative !important;
display: flex;
margin-inline: auto;
}
/* First child: Side bar */
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side {
position: fixed;
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);
bottom: 0;
left: auto;
overflow: auto;
}
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side .wy-side-scroll {
position: static !important;
width: unset !important;
overflow: unset !important;
height: unset !important;
padding-bottom: 2rem;
}
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side .wy-side-scroll .wy-side-nav-search {
margin: 0 !important;
width: var(--sideWidth) !important;
}
.wy-nav-side,
.wy-side-scroll,
.wy-side-nav-search,
.my-menu {
width: 100% !important;
}
.wy-nav-side input[type=text] {
font-family: "Overpass", sans-serif;
border-radius: 0;
border-color: var(--color-d);
background: var(--white);
box-shadow: none;
color: var(--color-a);
}
.wy-nav-side input[type=text]::placeholder {
font-family: "Overpass", sans-serif;
color: var(--color-e);
font-size: 16px;
position: relative;
top: 4px;
}
/* Second child: Content */
.unified-wrapper .wy-grid-for-nav .wy-nav-content {
width: 100%;
max-width: unset !important; /* override */
padding-inline: var(--desktopInlinePadding);
margin-inline-start: var(--sideWidth);
margin-top: var(--navHeight);
}
.unified-wrapper .wy-grid-for-nav .wy-nav-content .rst-content {
max-width: min(70ch, calc(100vw - 2 * var(--desktopInlinePadding) - var(--sideWidth)));
margin-inline: auto;
}
.unified-wrapper.menu-open .backdrop {
opacity: 0.5;
}
.unified-wrapper .wy-nav-side,
.unified-wrapper .rst-versions {
left: auto;
}
.unified-wrapper .backdrop {
opacity: 0;
transition: opacity 200ms ease-in-out;
}
@media (max-width: 768px) {
h2 {
margin-top: 3rem;
margin-bottom: 1rem;
}
h3 {
margin-top: 3rem;
margin-bottom: 1rem;
}
h4 {
margin-top: 2rem;
margin-bottom: 1rem;
}
/* Menu closed styles */
.unified-header .nav-link {
display: none;
}
.unified-header .inner-header {
padding-inline: var(--mobileInlinePadding);
}
.unified-wrapper .wy-grid-for-nav nav.wy-nav-side {
transform: translateX(-100%);
transition: transform 200ms ease-in-out;
}
/* Menu open styles */
.unified-wrapper.menu-open nav.wy-nav-side {
transform: translateX(0);
transition: transform 200ms ease-in-out;
}
.unified-wrapper.menu-open .rst-versions {
position: sticky;
bottom: 0;
width: 100%;
}
.unified-wrapper.menu-open .backdrop {
display: block;
position: fixed;
inset: 0;
opacity: 1;
transition: opacity 200ms ease-in-out;
z-index: 5;
background: #0006;
}
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 {
color: var(--color-a) !important;
}
.rst-versions {
background: var(--color-f);
}
.rst-versions.shift-up {
height: unset !important;
max-height: unset !important;
overflow-y: unset !important;
}
.rst-content dl:not(.docutils) dt {
color: var(--color-a);
background-color: #fff8;
border-top: solid 3px #0002;
border-inline-start: solid 3px #0002;
padding: 2px 6px;
}
.rst-versions .rst-current-version {
border-color: var(--color-d) !important;
}
.rst-current-version *,
.rst-current-version .fa:before,
.rst-current-version .fa-element {
color: var(--color-b) !important;
}
.rst-current-version dt,
.rst-current-version dd,
.rst-current-version dd a,
.rst-other-versions dl:last-of-type dt,
.rst-other-versions dl:last-of-type dd,
.rst-other-versions dl:last-of-type dd a {
font-size: 14px !important;
}
.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 {
text-decoration: underline;
color: var(--color-c) !important;
}
.rst-other-versions dt {
color: var(--color-a) !important;
}
.rst-other-versions dl {
margin-bottom: 1.5rem !important;
}
.rst-other-versions dl:last-of-type {
margin-top: 2rem !important;
}
/* Bottom Search */
.wy-nav-side input[type=text],
.rst-other-versions dl:last-of-type dd {
width: 100%;
}
.rst-other-versions dl:last-of-type dt {
color: var(--color-b) !important;
}
.rst-other-versions dl:last-of-type div[style*=padding],
.rst-other-versions dl dd:first-of-type a {
padding-inline-start: 0 !important;
}
button.toctree-expand {
color: var(--black) !important;
}
/* Light/dark color mode toggle 🌓 */
button.color-toggle {
display: inline-flex;
appearance: none;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
user-select: none;
outline: none;
height: 28px;
width: 28px;
background: none;
border: none;
padding: 6px;
margin: 6px;
transition-duration: 200ms;
transition-property: background-color,
color,
fill,
stroke,
opacity;
}
button.color-toggle:focus-visible {
outline: 2px solid var(--color-c);
color: var(--color-c);
}
button.color-toggle:hover {
color: var(--color-c);
background: #0002;
}
button.color-toggle .color-toggle-icon {
width: 100%;
height: 100%;
margin: 0;
display: inline-block;
line-height: 1em;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
vertical-align: middle;
/* color: var(--color-a); */
}
button.mobile-menu-button {
display: none;
}
@media (max-width: 768px) {
nav.wy-nav-top {
display: none;
}
button.mobile-menu-button {
display: flex;
}
}
.hidden {
display: none;
}
#search-results .search li:first-child,
#search-results .search li {
border-color: var(--color-d);
}
#search-results .search li:last-child {
border: 0px;
}
.forum-link::after {
content: ' ↗';
font-size: 14px;
font-family: 'Overpass Mono', monospace;
}
.wy-breadcrumbs>li {
padding-top: 8px;
}
.wy-breadcrumbs-aside a {
padding: 0.5rem 0.75rem;
font-size: 12px;
font-family: "'Overpass'", sans-serif;
font-weight: 700;
}
a.skip-to-content:visited,
a.skip-to-content:not(:visited),
a.skip-to-content {
display: block;
pointer-events: none;
width: fit-content;
opacity: 0;
transition: opacity 200ms ease-in-out;
padding: 2px 4px;
font-size: 14px;
margin-inline-end: auto;
margin-inline-start: 1.5rem;
color: var(--color-a);
white-space: nowrap;
}
a.skip-to-content:focus {
opacity: 1;
transition: opacity 200ms ease-in-out;
}
#content {
scroll-margin-top: 6rem;
scroll-behavior: smooth;
}

View File

@ -1,652 +0,0 @@
/* links */
.rst-content a:not(:visited) {
color: #aaddff;
}
/* code directives */
.method dt,
.class dt,
.data dt,
.attribute dt,
.function dt,
.classmethod dt,
.exception dt,
.descclassname,
.descname {
background-color: #2d2d2d !important;
}
.rst-content dl:not(.docutils) dt {
color: #aaddff;
background-color: #2d2d2d;
border-top: solid 3px #525252;
border-left: solid 3px #525252;
}
em.property {
color: #888888;
}
/* tables */
.rst-content table.docutils thead {
color: #ddd;
}
.rst-content table.docutils td {
border: 0px;
}
.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td {
background-color: #5a5a5a;
}
.rst-content pre {
background: none;
}
/* inlined code highlights */
.xref,
.py-meth,
.rst-content a code {
color: #aaddff !important;
font-weight: normal !important;
}
.rst-content code {
color: #eee !important;
font-weight: normal !important;
}
code.literal {
background-color: #2d2d2d !important;
border: 1px solid #6d6d6d !important;
}
code.docutils.literal.notranslate {
color: #ddd;
}
/* highlight color search text */
.rst-content .highlighted {
background: #ff5722;
box-shadow: 0 0 0 2px #f0978b;
}
/* notes, warnings, hints */
.hint .admonition-title {
background: #2aa87c !important;
}
.warning .admonition-title {
background: #cc4444 !important;
}
.admonition-title {
background: #3a7ca8 !important;
}
.admonition,
.note {
background-color: #2d2d2d !important;
}
/* table of contents */
.wy-nav-content-wrap {
background-color: rgba(0, 0, 0, 0.6) !important;
}
.sidebar {
background-color: #191919 !important;
}
.sidebar-title {
background-color: #2b2b2b !important;
}
.wy-menu-vertical a {
color: #ddd;
}
.wy-menu-vertical code.docutils.literal.notranslate {
color: #404040;
background: none !important;
border: none !important;
}
.wy-nav-content {
background: #3c3c3c;
color: #dddddd;
}
.wy-menu-vertical li.on a,
.wy-menu-vertical li.current>a {
background: #a3a3a3;
border-bottom: 0px !important;
border-top: 0px !important;
}
.wy-menu-vertical li.current {
background: #b3b3b3;
}
.toc-backref {
color: grey !important;
}
.highlight .hll {
background-color: #49483e
}
.highlight {
background: #222;
color: #f8f8f2
}
.highlight .c {
color: #888
}
/* Comment */
.highlight .err {
color: #960050;
background-color: #1e0010
}
/* Error */
.highlight .k {
color: #66d9ef
}
/* Keyword */
.highlight .l {
color: #ae81ff
}
/* Literal */
.highlight .n {
color: #f8f8f2
}
/* Name */
.highlight .o {
color: #f92672
}
/* Operator */
.highlight .p {
color: #f8f8f2
}
/* Punctuation */
.highlight .ch {
color: #888
}
/* Comment.Hashbang */
.highlight .cm {
color: #888
}
/* Comment.Multiline */
.highlight .cp {
color: #888
}
/* Comment.Preproc */
.highlight .cpf {
color: #888
}
/* Comment.PreprocFile */
.highlight .c1 {
color: #888
}
/* Comment.Single */
.highlight .cs {
color: #888
}
/* Comment.Special */
.highlight .gd {
color: #f92672
}
/* Generic.Deleted */
.highlight .ge {
font-style: italic
}
/* Generic.Emph */
.highlight .gi {
color: #a6e22e
}
/* Generic.Inserted */
.highlight .gs {
font-weight: bold
}
/* Generic.Strong */
.highlight .gu {
color: #888
}
/* Generic.Subheading */
.highlight .kc {
color: #66d9ef
}
/* Keyword.Constant */
.highlight .kd {
color: #66d9ef
}
/* Keyword.Declaration */
.highlight .kn {
color: #f92672
}
/* Keyword.Namespace */
.highlight .kp {
color: #66d9ef
}
/* Keyword.Pseudo */
.highlight .kr {
color: #66d9ef
}
/* Keyword.Reserved */
.highlight .kt {
color: #66d9ef
}
/* Keyword.Type */
.highlight .ld {
color: #e6db74
}
/* Literal.Date */
.highlight .m {
color: #ae81ff
}
/* Literal.Number */
.highlight .s {
color: #e6db74
}
/* Literal.String */
.highlight .na {
color: #a6e22e
}
/* Name.Attribute */
.highlight .nb {
color: #f8f8f2
}
/* Name.Builtin */
.highlight .nc {
color: #a6e22e
}
/* Name.Class */
.highlight .no {
color: #66d9ef
}
/* Name.Constant */
.highlight .nd {
color: #a6e22e
}
/* Name.Decorator */
.highlight .ni {
color: #f8f8f2
}
/* Name.Entity */
.highlight .ne {
color: #a6e22e
}
/* Name.Exception */
.highlight .nf {
color: #a6e22e
}
/* Name.Function */
.highlight .nl {
color: #f8f8f2
}
/* Name.Label */
.highlight .nn {
color: #f8f8f2
}
/* Name.Namespace */
.highlight .nx {
color: #a6e22e
}
/* Name.Other */
.highlight .py {
color: #f8f8f2
}
/* Name.Property */
.highlight .nt {
color: #f92672
}
/* Name.Tag */
.highlight .nv {
color: #f8f8f2
}
/* Name.Variable */
.highlight .ow {
color: #f92672
}
/* Operator.Word */
.highlight .w {
color: #f8f8f2
}
/* Text.Whitespace */
.highlight .mb {
color: #ae81ff
}
/* Literal.Number.Bin */
.highlight .mf {
color: #ae81ff
}
/* Literal.Number.Float */
.highlight .mh {
color: #ae81ff
}
/* Literal.Number.Hex */
.highlight .mi {
color: #ae81ff
}
/* Literal.Number.Integer */
.highlight .mo {
color: #ae81ff
}
/* Literal.Number.Oct */
.highlight .sa {
color: #e6db74
}
/* Literal.String.Affix */
.highlight .sb {
color: #e6db74
}
/* Literal.String.Backtick */
.highlight .sc {
color: #e6db74
}
/* Literal.String.Char */
.highlight .dl {
color: #e6db74
}
/* Literal.String.Delimiter */
.highlight .sd {
color: #e6db74
}
/* Literal.String.Doc */
.highlight .s2 {
color: #e6db74
}
/* Literal.String.Double */
.highlight .se {
color: #ae81ff
}
/* Literal.String.Escape */
.highlight .sh {
color: #e6db74
}
/* Literal.String.Heredoc */
.highlight .si {
color: #e6db74
}
/* Literal.String.Interpol */
.highlight .sx {
color: #e6db74
}
/* Literal.String.Other */
.highlight .sr {
color: #e6db74
}
/* Literal.String.Regex */
.highlight .s1 {
color: #e6db74
}
/* Literal.String.Single */
.highlight .ss {
color: #e6db74
}
/* Literal.String.Symbol */
.highlight .bp {
color: #f8f8f2
}
/* Name.Builtin.Pseudo */
.highlight .fm {
color: #a6e22e
}
/* Name.Function.Magic */
.highlight .vc {
color: #f8f8f2
}
/* Name.Variable.Class */
.highlight .vg {
color: #f8f8f2
}
/* Name.Variable.Global */
.highlight .vi {
color: #f8f8f2
}
/* Name.Variable.Instance */
.highlight .vm {
color: #f8f8f2
}
/* Name.Variable.Magic */
.highlight .il {
color: #ae81ff
}
/* Link to Remix IDE shown over code snippets */
.rst-content .remix-link-container a.remix-link {
color: black;
}
/* Grammar */
.railroad-diagram {
fill: white;
}
.railroad-diagram path {
stroke: white;
}
.railroad-diagram rect {
stroke: white;
}
.a4 .sig-name {
background-color: transparent !important;
}

2
docs/_static/css/fonts.css vendored Normal file
View File

@ -0,0 +1,2 @@
@import url("https://fonts.cdnfonts.com/css/overpass");
@import url("https://fonts.cdnfonts.com/css/overpass-mono");

399
docs/_static/css/pygments.css vendored Normal file
View File

@ -0,0 +1,399 @@
pre {
line-height: 125%;
}
td.linenos .normal {
color: inherit;
background-color: transparent;
padding-left: 5px;
padding-right: 5px;
}
span.linenos {
color: inherit;
background-color: transparent;
padding-left: 5px;
padding-right: 5px;
}
td.linenos .special {
color: #000000;
background-color: #ffffc0;
padding-left: 5px;
padding-right: 5px;
}
span.linenos.special {
color: #000000;
background-color: #ffffc0;
padding-left: 5px;
padding-right: 5px;
}
.highlight .hll {
background-color: #ffffcc
}
.highlight {
background: #eeffcc;
}
.highlight .c {
color: #408090;
font-style: italic
}
/* Comment */
.highlight .err {
border: 1px solid #FF0000
}
/* Error */
.highlight .k {
color: #007020;
font-weight: bold
}
/* Keyword */
.highlight .o {
color: #666666
}
/* Operator */
.highlight .ch {
color: #408090;
font-style: italic
}
/* Comment.Hashbang */
.highlight .cm {
color: #408090;
font-style: italic
}
/* Comment.Multiline */
.highlight .cp {
color: #007020
}
/* Comment.Preproc */
.highlight .cpf {
color: #408090;
font-style: italic
}
/* Comment.PreprocFile */
.highlight .c1 {
color: #408090;
font-style: italic
}
/* Comment.Single */
.highlight .cs {
color: #408090;
background-color: #fff0f0
}
/* Comment.Special */
.highlight .gd {
color: #A00000
}
/* Generic.Deleted */
.highlight .ge {
font-style: italic
}
/* Generic.Emph */
.highlight .gr {
color: #FF0000
}
/* Generic.Error */
.highlight .gh {
color: #000080;
font-weight: bold
}
/* Generic.Heading */
.highlight .gi {
color: #00A000
}
/* Generic.Inserted */
.highlight .go {
color: #333333
}
/* Generic.Output */
.highlight .gp {
color: #c65d09;
font-weight: bold
}
/* Generic.Prompt */
.highlight .gs {
font-weight: bold
}
/* Generic.Strong */
.highlight .gu {
color: #800080;
font-weight: bold
}
/* Generic.Subheading */
.highlight .gt {
color: #0044DD
}
/* Generic.Traceback */
.highlight .kc {
color: #007020;
font-weight: bold
}
/* Keyword.Constant */
.highlight .kd {
color: #007020;
font-weight: bold
}
/* Keyword.Declaration */
.highlight .kn {
color: #007020;
font-weight: bold
}
/* Keyword.Namespace */
.highlight .kp {
color: #007020
}
/* Keyword.Pseudo */
.highlight .kr {
color: #007020;
font-weight: bold
}
/* Keyword.Reserved */
.highlight .kt {
color: #902000
}
/* Keyword.Type */
.highlight .m {
color: #208050
}
/* Literal.Number */
.highlight .s {
color: #4070a0
}
/* Literal.String */
.highlight .na {
color: #4070a0
}
/* Name.Attribute */
.highlight .nb {
color: #007020
}
/* Name.Builtin */
.highlight .nc {
color: #0e84b5;
font-weight: bold
}
/* Name.Class */
.highlight .no {
color: #60add5
}
/* Name.Constant */
.highlight .nd {
color: #555555;
font-weight: bold
}
/* Name.Decorator */
.highlight .ni {
color: #d55537;
font-weight: bold
}
/* Name.Entity */
.highlight .ne {
color: #007020
}
/* Name.Exception */
.highlight .nf {
color: #06287e
}
/* Name.Function */
.highlight .nl {
color: #002070;
font-weight: bold
}
/* Name.Label */
.highlight .nn {
color: #0e84b5;
font-weight: bold
}
/* Name.Namespace */
.highlight .nt {
color: #062873;
font-weight: bold
}
/* Name.Tag */
.highlight .nv {
color: #bb60d5
}
/* Name.Variable */
.highlight .ow {
color: #007020;
font-weight: bold
}
/* Operator.Word */
.highlight .w {
color: #bbbbbb
}
/* Text.Whitespace */
.highlight .mb {
color: #208050
}
/* Literal.Number.Bin */
.highlight .mf {
color: #208050
}
/* Literal.Number.Float */
.highlight .mh {
color: #208050
}
/* Literal.Number.Hex */
.highlight .mi {
color: #208050
}
/* Literal.Number.Integer */
.highlight .mo {
color: #208050
}
/* Literal.Number.Oct */
.highlight .sa {
color: #4070a0
}
/* Literal.String.Affix */
.highlight .sb {
color: #4070a0
}
/* Literal.String.Backtick */
.highlight .sc {
color: #4070a0
}
/* Literal.String.Char */
.highlight .dl {
color: #4070a0
}
/* Literal.String.Delimiter */
.highlight .sd {
color: #4070a0;
font-style: italic
}
/* Literal.String.Doc */
.highlight .s2 {
color: #4070a0
}
/* Literal.String.Double */
.highlight .se {
color: #4070a0;
font-weight: bold
}
/* Literal.String.Escape */
.highlight .sh {
color: #4070a0
}
/* Literal.String.Heredoc */
.highlight .si {
color: #70a0d0;
font-style: italic
}
/* Literal.String.Interpol */
.highlight .sx {
color: #c65d09
}
/* Literal.String.Other */
.highlight .sr {
color: #235388
}
/* Literal.String.Regex */
.highlight .s1 {
color: #4070a0
}
/* Literal.String.Single */
.highlight .ss {
color: #517918
}
/* Literal.String.Symbol */
.highlight .bp {
color: #007020
}
/* Name.Builtin.Pseudo */
.highlight .fm {
color: #06287e
}
/* Name.Function.Magic */
.highlight .vc {
color: #bb60d5
}
/* Name.Variable.Class */
.highlight .vg {
color: #bb60d5
}
/* Name.Variable.Global */
.highlight .vi {
color: #bb60d5
}
/* Name.Variable.Instance */
.highlight .vm {
color: #bb60d5
}
/* Name.Variable.Magic */
.highlight .il {
color: #208050
}
/* Literal.Number.Integer.Long */

View File

@ -9,6 +9,13 @@ input[type=checkbox] {
padding: 10px; padding: 10px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
background-color: var(--color-f);
border-top: 1px solid var(--color-c);
}
.fa-caret-down,
.fa-book {
color: var(--color-a) !important;
} }
.rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .fa-book,
@ -76,8 +83,6 @@ html.transition *:after {
transition-delay: 0 !important; transition-delay: 0 !important;
} }
nav.wy-nav-side { .wy-menu-vertical a:hover {
/* The default padding of 2em is too small and the "Keyword Index" link gets obscured background-color: #0002;
* by the version toggle. */
padding-bottom: 3em;
} }

BIN
docs/_static/img/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

3
docs/_static/img/hamburger-dark.svg vendored Normal file
View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="#E6E3EC" xmlns="http://www.w3.org/2000/svg" focusable="false" class="color-toggle-icon" aria-hidden="true">
<path d="M 3 5 A 1.0001 1.0001 0 1 0 3 7 L 21 7 A 1.0001 1.0001 0 1 0 21 5 L 3 5 z M 3 11 A 1.0001 1.0001 0 1 0 3 13 L 21 13 A 1.0001 1.0001 0 1 0 21 11 L 3 11 z M 3 17 A 1.0001 1.0001 0 1 0 3 19 L 21 19 A 1.0001 1.0001 0 1 0 21 17 L 3 17 z" />
</svg>

After

Width:  |  Height:  |  Size: 413 B

3
docs/_static/img/hamburger-light.svg vendored Normal file
View File

@ -0,0 +1,3 @@
<svg width="24px" height="24px" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" focusable="false" class="color-toggle-icon" aria-hidden="true">
<path fill="#2B247C" d="M 3 5 A 1.0001 1.0001 0 1 0 3 7 L 21 7 A 1.0001 1.0001 0 1 0 21 5 L 3 5 z M 3 11 A 1.0001 1.0001 0 1 0 3 13 L 21 13 A 1.0001 1.0001 0 1 0 21 11 L 3 11 z M 3 17 A 1.0001 1.0001 0 1 0 3 19 L 21 19 A 1.0001 1.0001 0 1 0 21 17 L 3 17 z" />
</svg>

After

Width:  |  Height:  |  Size: 437 B

8
docs/_static/img/logo-dark.svg vendored Normal file
View File

@ -0,0 +1,8 @@
<svg width="100" height="160" viewBox="0 0 100 160" fill="#E6E3EC" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.8" d="M50 44.3013L25 1L0 44.3013L25 87.6025L50 44.3013Z" />
<path opacity="0.45" d="M50 44.3091L75 1.00781L25 1.00781L0 44.3091H50Z" />
<path opacity="0.6" d="M75 1.00781L25 1.00781L50 44.3091H100L75 1.00781Z" />
<path opacity="0.8" d="M50 115.699L75 159L100 115.699L75 72.3975L50 115.699Z" />
<path opacity="0.45" d="M50 115.691L25 158.993H75L100 115.691L50 115.691Z" />
<path opacity="0.6" d="M25 158.993H75L50 115.691L0 115.691L25 158.993Z" />
</svg>

After

Width:  |  Height:  |  Size: 574 B

8
docs/_static/img/logo.svg vendored Normal file
View File

@ -0,0 +1,8 @@
<svg width="100" height="160" viewBox="0 0 100 160" fill="#2B247C" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.8" d="M50 44.3013L25 1L0 44.3013L25 87.6025L50 44.3013Z" />
<path opacity="0.45" d="M50 44.3091L75 1.00781L25 1.00781L0 44.3091H50Z" />
<path opacity="0.6" d="M75 1.00781L25 1.00781L50 44.3091H100L75 1.00781Z" />
<path opacity="0.8" d="M50 115.699L75 159L100 115.699L75 72.3975L50 115.699Z" />
<path opacity="0.45" d="M50 115.691L25 158.993H75L100 115.691L50 115.691Z" />
<path opacity="0.6" d="M25 158.993H75L50 115.691L0 115.691L25 158.993Z" />
</svg>

After

Width:  |  Height:  |  Size: 574 B

3
docs/_static/img/moon.svg vendored Normal file
View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="#2B247C" xmlns="http://www.w3.org/2000/svg" focusable="false" class="color-toggle-icon" aria-hidden="true">
<path d="M21.4,13.7C20.6,13.9,19.8,14,19,14c-5,0-9-4-9-9c0-0.8,0.1-1.6,0.3-2.4c0.1-0.3,0-0.7-0.3-1 c-0.3-0.3-0.6-0.4-1-0.3C4.3,2.7,1,7.1,1,12c0,6.1,4.9,11,11,11c4.9,0,9.3-3.3,10.6-8.1c0.1-0.3,0-0.7-0.3-1 C22.1,13.7,21.7,13.6,21.4,13.7z" />
</svg>

After

Width:  |  Height:  |  Size: 408 B

13
docs/_static/img/sun.svg vendored Normal file
View File

@ -0,0 +1,13 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" focusable="false" class="color-toggle-icon" aria-hidden="true">
<g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="#E6E3EC">
<circle cx="12" cy="12" r="5" />
<path d="M12 1v2" />
<path d="M12 21v2" />
<path d="M4.22 4.22l1.42 1.42" />
<path d="M18.36 18.36l1.42 1.42" />
<path d="M1 12h2" />
<path d="M21 12h2" />
<path d="M4.22 19.78l1.42-1.42" />
<path d="M18.36 5.64l1.42-1.42" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 554 B

38
docs/_static/js/constants.js vendored Normal file
View File

@ -0,0 +1,38 @@
// 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 COLOR_TOGGLE_ICON_CLASS = "color-toggle-icon";
const SOLIDITY_LOGO_CLASS = "solidity-logo";
const LS_COLOR_SCHEME = "color-scheme";
// Solidity navigation constants
const SOLIDITY_HOME_URL = "https://soliditylang.org";
const BLOG_URL = `${SOLIDITY_HOME_URL}/blog`;
const DOCS_URL = "/";
const USE_CASES_PATH = `${SOLIDITY_HOME_URL}/use-cases`;
const CONTRIBUTE_PATH = `/en/latest/contributing.html`;
const ABOUT_PATH = `${SOLIDITY_HOME_URL}/about`;
const FORUM_URL = "https://forum.soliditylang.org/";
const NAV_LINKS = [
{ name: "Blog", href: BLOG_URL },
{ name: "Documentation", href: DOCS_URL },
{ name: "Use cases", href: USE_CASES_PATH },
{ name: "Contribute", href: CONTRIBUTE_PATH },
{ name: "About", href: ABOUT_PATH },
{ name: "Forum", href: FORUM_URL },
];
const MOBILE_MENU_TOGGLE_CLASS = "shift";
const WRAPPER_CLASS = "unified-wrapper";

250
docs/_static/js/initialize.js vendored Normal file
View File

@ -0,0 +1,250 @@
const getLogoSrc = (isDark) => (isDark ? DARK_LOGO_PATH : LIGHT_LOGO_PATH);
const getModeIconSrc = (isDark) => (isDark ? SUN_ICON_PATH : MOON_ICON_PATH);
const getMenuIconSrc = (isDark) =>
isDark ? DARK_HAMBURGER_PATH : LIGHT_HAMBURGER_PATH;
function addFooterNote() {
const contentInfo = document.querySelector("div[role=contentinfo]");
const footerNote = document.createElement("p");
footerNote.classList.add("footer-note");
footerNote.innerHTML =
'Customized with ❤️ by the <a href="https://ethereum.org/" target="_blank">ethereum.org</a> team.';
contentInfo.parentNode.insertBefore(footerNote, contentInfo.nextSibling);
}
function rearrangeDom() {
const bodyDivs = document.querySelectorAll("body>div");
bodyDivs.forEach((div) => div.remove());
const wrapperDiv = document.createElement("div");
wrapperDiv.classList.add(WRAPPER_CLASS);
bodyDivs.forEach((div) => wrapperDiv.appendChild(div));
document.body.prepend(wrapperDiv);
const rstVersions = document.querySelector(".rst-versions");
rstVersions.remove();
const wyNavSide = document.querySelector("nav.wy-nav-side");
wyNavSide.appendChild(rstVersions);
const backdrop = document.createElement("div");
backdrop.classList.add("backdrop");
wrapperDiv.appendChild(backdrop);
const content = document.querySelector(".wy-nav-content");
content.id = "content";
const oldWrap = document.querySelector("section.wy-nav-content-wrap");
oldWrap.remove();
document.querySelector(".wy-grid-for-nav").appendChild(content);
}
function buildHeader() {
const isDarkMode = localStorage.getItem(LS_COLOR_SCHEME) == DARK;
const header = document.createElement("div");
header.classList.add("unified-header");
document.querySelector(`.${WRAPPER_CLASS}`).prepend(header);
const innerHeader = document.createElement("div");
innerHeader.classList.add("inner-header");
header.appendChild(innerHeader);
const homeLink = document.createElement("a");
homeLink.classList.add("home-link");
homeLink.href = SOLIDITY_HOME_URL;
homeLink.ariaLabel = "Solidity home";
innerHeader.appendChild(homeLink);
const logo = document.createElement("img");
logo.classList.add(SOLIDITY_LOGO_CLASS);
logo.src = getLogoSrc(isDarkMode);
logo.alt = "Solidity logo";
homeLink.appendChild(logo);
const skipToContent = document.createElement("a");
skipToContent.classList.add("skip-to-content");
skipToContent.href = "#content";
skipToContent.innerText = "{skip to content}";
innerHeader.appendChild(skipToContent);
const navBar = document.createElement("nav");
navBar.classList.add("nav-bar");
innerHeader.appendChild(navBar);
const linkElements = NAV_LINKS.map(({ name, href }) => {
const link = document.createElement("a");
link.classList.add("nav-link");
link.setAttribute("key", name);
link.setAttribute("href", href);
link.setAttribute("aria-label", name);
if (href === FORUM_URL) {
link.classList.add("forum-link");
link.setAttribute("target", "_blank");
link.setAttribute("rel", "noopener noreferrer");
}
link.innerText = name;
return link;
});
linkElements.forEach((link) => navBar.appendChild(link));
// Flex wrapper for color mode and mobile menu buttons
const navButtonContainer = document.createElement("div");
navButtonContainer.classList.add("nav-button-container");
navBar.appendChild(navButtonContainer);
// Build color toggle
const toggleIcon = document.createElement("img");
toggleIcon.classList.add(COLOR_TOGGLE_ICON_CLASS);
toggleIcon.src = getModeIconSrc(isDarkMode);
toggleIcon.alt = "Color mode toggle icon";
toggleIcon.setAttribute("aria-hidden", "true");
toggleIcon.setAttribute("key", "toggle icon");
const colorModeButton = document.createElement("button");
colorModeButton.classList.add("color-toggle");
colorModeButton.setAttribute("type", "button");
colorModeButton.setAttribute("aria-label", "Toggle light dark mode");
colorModeButton.setAttribute("key", "color mode button");
colorModeButton.addEventListener("click", toggleColorMode);
colorModeButton.appendChild(toggleIcon);
navButtonContainer.appendChild(colorModeButton);
// Build mobile hamburger menu
const menuIcon = document.createElement("img");
menuIcon.classList.add(COLOR_TOGGLE_ICON_CLASS);
menuIcon.src = getMenuIconSrc(isDarkMode);
menuIcon.alt = "Toggle menu";
menuIcon.setAttribute("aria-hidden", "true");
menuIcon.setAttribute("key", "menu icon");
const menuButton = document.createElement("button");
menuButton.classList.add("color-toggle");
menuButton.classList.add("mobile-menu-button");
menuButton.setAttribute("type", "button");
menuButton.setAttribute("aria-label", "Toggle menu");
menuButton.setAttribute("key", "menu button");
menuButton.addEventListener("click", toggleMenu);
menuButton.appendChild(menuIcon);
navButtonContainer.appendChild(menuButton);
}
const updateActiveNavLink = () => {
const navLinks = document.querySelectorAll(".unified-header .nav-link");
navLinks.forEach((link) => {
const href = link.getAttribute("href");
if (document.documentURI.includes("contributing.html")) {
link.classList[href.includes("contributing.html") ? "add" : "remove"](
"active"
);
} else {
link.classList[document.documentURI.includes(href) ? "add" : "remove"](
"active"
);
}
});
};
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() {
// Rearrange DOM elements for styling
rearrangeDom();
// Check localStorage for existing color scheme preference
var prefersDark = localStorage.getItem(LS_COLOR_SCHEME) == DARK;
// Check link for search param "color"... it may be "light" or "dark"
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.size > 0) {
// This is used for color mode continuity between the main Solidity Lang site and the docs
var colorSchemeParam = urlParams.get("color");
// If present, overwrite prefersDark accordingly
if (colorSchemeParam) {
prefersDark = colorSchemeParam == DARK;
}
// Remove "color" search param from URL
const { location, title } = document;
const { pathname, origin, search, hash } = location;
const newSearchParams = new URLSearchParams(search);
newSearchParams.delete("color");
const sanitizedSearch =
newSearchParams.size < 1 ? "" : "?" + newSearchParams.toString();
window.history.replaceState(
origin,
title,
pathname + sanitizedSearch + hash
);
}
// In case none existed, establish localStorage color scheme preference
var mode = prefersDark ? DARK : LIGHT;
localStorage.setItem(LS_COLOR_SCHEME, mode);
// Select the root element and set the style attribute to denote color-scheme attribute
document
.querySelector(":root")
.setAttribute("style", `--color-scheme: ${mode}`);
// Remove old input and RTD logo anchor element
document.querySelector("input[name=mode]").remove();
document.querySelector("label[for=switch]").remove();
document.querySelector(".wy-side-nav-search > a").remove();
// Add footer note
addFooterNote();
// Build header
buildHeader();
// Close menu
toggleMenu({ force: false });
// Update active nav link
updateActiveNavLink();
// Update GitHub edit path to direct to `develop` branch
updateGitHubEditPath();
}
document.addEventListener("DOMContentLoaded", initialize);
const handleClick = (e) => {
if (e.target.closest(".backdrop")) {
toggleMenu({ force: false });
}
if (e.target.closest("a")) {
const target = e.target.closest("a");
const href = target.getAttribute("href");
if (href.includes(SOLIDITY_HOME_URL)) {
const url = new URL(href);
const params = new URLSearchParams(url.search);
params.set("color", localStorage.getItem(LS_COLOR_SCHEME));
url.search = params.toString();
target.setAttribute("href", url.toString());
}
}
};
document.addEventListener("click", handleClick);
const handleKeyDown = (e) => {
if (e.metaKey && e.key === "k") {
document.querySelector("#rtd-search-form input").focus();
} else if (e.key === "Escape") {
toggleMenu({ force: false });
}
if (e.metaKey && e.code === "Backslash") {
toggleColorMode();
}
};
document.addEventListener("keydown", handleKeyDown);

View File

@ -1,39 +1,47 @@
document.addEventListener('DOMContentLoaded', function() { function toggleColorMode() {
// Check localStorage for previous color scheme preference, assign the opposite
var newMode = localStorage.getItem(LS_COLOR_SCHEME) == DARK ? LIGHT : DARK;
function toggleCssMode(isDay) { // Update localStorage with new color scheme preference
var mode = (isDay ? "Day" : "Night"); localStorage.setItem(LS_COLOR_SCHEME, newMode);
localStorage.setItem("css-mode", mode);
var url_root = DOCUMENTATION_OPTIONS.URL_ROOT == "./" ? "" : DOCUMENTATION_OPTIONS.URL_ROOT; // Update the root element with the new color scheme preference
var daysheet = $(`link[href="${url_root}_static/pygments.css"]`)[0].sheet; document
daysheet.disabled = !isDay; .querySelector(":root")
.setAttribute("style", `--color-scheme: ${newMode}`);
var nightsheet = $(`link[href="${url_root}_static/css/dark.css"]`)[0]; // Update logo
if (!isDay && nightsheet === undefined) { document
var element = document.createElement("link"); .querySelector(`img.${SOLIDITY_LOGO_CLASS}`)
element.setAttribute("rel", "stylesheet"); .setAttribute("src", newMode === LIGHT ? LIGHT_LOGO_PATH : DARK_LOGO_PATH);
element.setAttribute("type", "text/css");
element.setAttribute("href", `${url_root}_static/css/dark.css`); // Update color mode toggle icon
document.getElementsByTagName("head")[0].appendChild(element); document
return; .querySelector(`img.${COLOR_TOGGLE_ICON_CLASS}`)
} .setAttribute("src", newMode === LIGHT ? MOON_ICON_PATH : SUN_ICON_PATH);
if (nightsheet !== undefined) {
nightsheet.sheet.disabled = isDay; // Update hamburger menu icon color
} document
.querySelector("button.mobile-menu-button img")
.setAttribute(
"src",
newMode === LIGHT ? LIGHT_HAMBURGER_PATH : DARK_HAMBURGER_PATH
);
}
function toggleMenu(options = {}) {
const handleClassToggle = ({ classList }, className) => {
if (typeof options.force !== "undefined") {
classList.toggle(className, options.force);
} else {
classList.toggle(className);
} }
};
var initial = localStorage.getItem("css-mode") != "Night"; document
var checkbox = document.querySelector('input[name=mode]'); .querySelectorAll('[data-toggle="rst-versions"]')
.forEach((e) => handleClassToggle(e, MOBILE_MENU_TOGGLE_CLASS));
toggleCssMode(initial); document
checkbox.checked = initial; .querySelectorAll('[data-toggle="wy-nav-shift"]')
.forEach((e) => handleClassToggle(e, MOBILE_MENU_TOGGLE_CLASS));
checkbox.addEventListener('change', function() { handleClassToggle(document.querySelector(`.${WRAPPER_CLASS}`), "menu-open");
document.documentElement.classList.add('transition'); }
window.setTimeout(() => {
document.documentElement.classList.remove('transition');
}, 1000)
toggleCssMode(this.checked);
})
});

View File

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

View File

@ -1,4 +1,30 @@
[ [
{
"uid": "SOL-2023-2",
"name": "FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"summary": "Optimizer sequences containing FullInliner do not preserve the evaluation order of arguments of inlined function calls in code that is not in expression-split form.",
"description": "Function call arguments in Yul are evaluated right to left. This order matters when the argument expressions have side-effects, and changing it may change contract behavior. FullInliner is an optimizer step that can replace a function call with the body of that function. The transformation involves assigning argument expressions to temporary variables, which imposes an explicit evaluation order. FullInliner was written with the assumption that this order does not necessarily have to match usual argument evaluation order because the argument expressions have no side-effects. In most circumstances this assumption is true because the default optimization step sequence contains the ExpressionSplitter step. ExpressionSplitter ensures that the code is in *expression-split form*, which means that function calls cannot appear nested inside expressions, and all function call arguments have to be variables. The assumption is, however, not guaranteed to be true in general. Version 0.6.7 introduced a setting allowing users to specify an arbitrary optimization step sequence, making it possible for the FullInliner to actually encounter argument expressions with side-effects, which can result in behavior differences between optimized and unoptimized bytecode. Contracts compiled without optimization or with the default optimization sequence are not affected. To trigger the bug the user has to explicitly choose compiler settings that contain a sequence with FullInliner step not preceded by ExpressionSplitter.",
"link": "https://blog.soliditylang.org/2023/07/19/full-inliner-non-expression-split-argument-evaluation-order-bug/",
"introduced": "0.6.7",
"fixed": "0.8.21",
"severity": "low",
"conditions": {
"yulOptimizer": true
}
},
{
"uid": "SOL-2023-1",
"name": "MissingSideEffectsOnSelectorAccess",
"summary": "Accessing the ``.selector`` member on complex expressions leaves the expression unevaluated in the legacy code generation.",
"description": "When accessing the ``.selector`` member on an expression with side-effects, like an assignment, a function call or a conditional, the expression would not be evaluated in the legacy code generation. This would happen in expressions where the functions used in the expression were all known at compilation time, regardless of whether the whole expression could be evaluated at compilation time or not. Note that the code generated by the IR pipeline was unaffected and would behave as expected.",
"link": "https://blog.soliditylang.org/2023/07/19/missing-side-effects-on-selector-access-bug/",
"introduced": "0.6.2",
"fixed": "0.8.21",
"severity": "low",
"conditions": {
"viaIR": false
}
},
{ {
"uid": "SOL-2022-7", "uid": "SOL-2022-7",
"name": "StorageWriteRemovalBeforeConditionalTermination", "name": "StorageWriteRemovalBeforeConditionalTermination",

View File

@ -1422,6 +1422,8 @@
}, },
"0.6.10": { "0.6.10": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1436,6 +1438,8 @@
}, },
"0.6.11": { "0.6.11": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1450,6 +1454,8 @@
}, },
"0.6.12": { "0.6.12": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1464,6 +1470,7 @@
}, },
"0.6.2": { "0.6.2": {
"bugs": [ "bugs": [
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1481,6 +1488,7 @@
}, },
"0.6.3": { "0.6.3": {
"bugs": [ "bugs": [
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1498,6 +1506,7 @@
}, },
"0.6.4": { "0.6.4": {
"bugs": [ "bugs": [
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1515,6 +1524,7 @@
}, },
"0.6.5": { "0.6.5": {
"bugs": [ "bugs": [
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1532,6 +1542,7 @@
}, },
"0.6.6": { "0.6.6": {
"bugs": [ "bugs": [
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1548,6 +1559,8 @@
}, },
"0.6.7": { "0.6.7": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1564,6 +1577,8 @@
}, },
"0.6.8": { "0.6.8": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"NestedCalldataArrayAbiReencodingSizeValidation", "NestedCalldataArrayAbiReencodingSizeValidation",
@ -1577,6 +1592,8 @@
}, },
"0.6.9": { "0.6.9": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1592,6 +1609,8 @@
}, },
"0.7.0": { "0.7.0": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1606,6 +1625,8 @@
}, },
"0.7.1": { "0.7.1": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1621,6 +1642,8 @@
}, },
"0.7.2": { "0.7.2": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1635,6 +1658,8 @@
}, },
"0.7.3": { "0.7.3": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1648,6 +1673,8 @@
}, },
"0.7.4": { "0.7.4": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1660,6 +1687,8 @@
}, },
"0.7.5": { "0.7.5": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1672,6 +1701,8 @@
}, },
"0.7.6": { "0.7.6": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1684,6 +1715,8 @@
}, },
"0.8.0": { "0.8.0": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1696,6 +1729,8 @@
}, },
"0.8.1": { "0.8.1": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1708,6 +1743,8 @@
}, },
"0.8.10": { "0.8.10": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1717,6 +1754,8 @@
}, },
"0.8.11": { "0.8.11": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1727,6 +1766,8 @@
}, },
"0.8.12": { "0.8.12": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1737,6 +1778,8 @@
}, },
"0.8.13": { "0.8.13": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"StorageWriteRemovalBeforeConditionalTermination", "StorageWriteRemovalBeforeConditionalTermination",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
@ -1748,6 +1791,8 @@
}, },
"0.8.14": { "0.8.14": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"StorageWriteRemovalBeforeConditionalTermination", "StorageWriteRemovalBeforeConditionalTermination",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
@ -1757,6 +1802,8 @@
}, },
"0.8.15": { "0.8.15": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"StorageWriteRemovalBeforeConditionalTermination", "StorageWriteRemovalBeforeConditionalTermination",
"AbiReencodingHeadOverflowWithStaticArrayCleanup" "AbiReencodingHeadOverflowWithStaticArrayCleanup"
], ],
@ -1764,24 +1811,37 @@
}, },
"0.8.16": { "0.8.16": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"StorageWriteRemovalBeforeConditionalTermination" "StorageWriteRemovalBeforeConditionalTermination"
], ],
"released": "2022-08-08" "released": "2022-08-08"
}, },
"0.8.17": { "0.8.17": {
"bugs": [], "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess"
],
"released": "2022-09-08" "released": "2022-09-08"
}, },
"0.8.18": { "0.8.18": {
"bugs": [], "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess"
],
"released": "2023-02-01" "released": "2023-02-01"
}, },
"0.8.19": { "0.8.19": {
"bugs": [], "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess"
],
"released": "2023-02-22" "released": "2023-02-22"
}, },
"0.8.2": { "0.8.2": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1793,11 +1853,20 @@
"released": "2021-03-02" "released": "2021-03-02"
}, },
"0.8.20": { "0.8.20": {
"bugs": [], "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess"
],
"released": "2023-05-10" "released": "2023-05-10"
}, },
"0.8.21": {
"bugs": [],
"released": "2023-07-19"
},
"0.8.3": { "0.8.3": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1809,6 +1878,8 @@
}, },
"0.8.4": { "0.8.4": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1819,6 +1890,8 @@
}, },
"0.8.5": { "0.8.5": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1829,6 +1902,8 @@
}, },
"0.8.6": { "0.8.6": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1839,6 +1914,8 @@
}, },
"0.8.7": { "0.8.7": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1849,6 +1926,8 @@
}, },
"0.8.8": { "0.8.8": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",
@ -1860,6 +1939,8 @@
}, },
"0.8.9": { "0.8.9": {
"bugs": [ "bugs": [
"FullInlinerNonExpressionSplitArgumentEvaluationOrder",
"MissingSideEffectsOnSelectorAccess",
"AbiReencodingHeadOverflowWithStaticArrayCleanup", "AbiReencodingHeadOverflowWithStaticArrayCleanup",
"DirtyBytesArrayToStorage", "DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride", "DataLocationChangeInInternalOverride",

View File

@ -151,7 +151,7 @@ Modifiers
- ``view`` for functions: Disallows modification of state. - ``view`` for functions: Disallows modification of state.
- ``payable`` for functions: Allows them to receive Ether together with a call. - ``payable`` for functions: Allows them to receive Ether together with a call.
- ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot. - ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot.
- ``immutable`` for state variables: Allows exactly one assignment at construction time and is constant afterwards. Is stored in code. - ``immutable`` for state variables: Allows assignment at construction time and is constant when deployed. Is stored in code.
- ``anonymous`` for events: Does not store event signature as topic. - ``anonymous`` for events: Does not store event signature as topic.
- ``indexed`` for event parameters: Stores the parameter as topic. - ``indexed`` for event parameters: Stores the parameter as topic.
- ``virtual`` for functions and modifiers: Allows the function's or modifier's - ``virtual`` for functions and modifiers: Allows the function's or modifier's

View File

@ -31,7 +31,10 @@ def setup(sphinx):
sphinx.add_lexer('Solidity', SolidityLexer) sphinx.add_lexer('Solidity', SolidityLexer)
sphinx.add_lexer('Yul', YulLexer) sphinx.add_lexer('Yul', YulLexer)
sphinx.add_css_file('css/fonts.css')
sphinx.add_css_file('css/custom.css') sphinx.add_css_file('css/custom.css')
sphinx.add_css_file('css/custom-dark.css')
sphinx.add_css_file('css/pygments.css')
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
@ -132,7 +135,6 @@ html_theme = 'sphinx_rtd_theme'
# documentation. # documentation.
html_theme_options = { html_theme_options = {
'logo_only': True, 'logo_only': True,
'style_nav_header_background': '#65afff',
'display_version': True, 'display_version': True,
} }
@ -148,12 +150,12 @@ html_theme_options = {
# The name of an image file (relative to this directory) to place at the top # The name of an image file (relative to this directory) to place at the top
# of the sidebar. # of the sidebar.
html_logo = "logo.svg" # html_logo = "logo.svg"
# The name of an image file (within the static path) to use as favicon of the # The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large. # pixels large.
html_favicon = "_static/img/favicon.png" html_favicon = "_static/img/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
@ -162,7 +164,7 @@ html_static_path = ['_static']
html_css_files = ["css/toggle.css"] html_css_files = ["css/toggle.css"]
html_js_files = ["js/toggle.js"] 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 # Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied # .htaccess) here, relative to this directory. These files are copied
@ -210,7 +212,7 @@ html_extra_templates = {
#html_show_sourcelink = True #html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True html_show_sphinx = False
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True #html_show_copyright = True

View File

@ -30,19 +30,23 @@ Not all types for constants and immutables are implemented at this time. The onl
.. code-block:: solidity .. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.4; pragma solidity ^0.8.21;
uint constant X = 32**22 + 8; uint constant X = 32**22 + 8;
contract C { contract C {
string constant TEXT = "abc"; string constant TEXT = "abc";
bytes32 constant MY_HASH = keccak256("abc"); bytes32 constant MY_HASH = keccak256("abc");
uint immutable decimals; uint immutable decimals = 18;
uint immutable maxBalance; uint immutable maxBalance;
address immutable owner = msg.sender; address immutable owner = msg.sender;
constructor(uint decimals_, address ref) { constructor(uint decimals_, address ref) {
decimals = decimals_; if (decimals_ != 0)
// Immutables are only immutable when deployed.
// At construction time they can be assigned to any number of times.
decimals = decimals_;
// Assignments to immutables can even access the environment. // Assignments to immutables can even access the environment.
maxBalance = ref.balance; maxBalance = ref.balance;
} }
@ -74,10 +78,29 @@ Immutable
========= =========
Variables declared as ``immutable`` are a bit less restricted than those Variables declared as ``immutable`` are a bit less restricted than those
declared as ``constant``: Immutable variables can be assigned an arbitrary declared as ``constant``: Immutable variables can be assigned a
value in the constructor of the contract or at the point of their declaration. value at construction time.
They can be assigned only once and can, from that point on, be read even during The value can be changed at any time before deployment and then it becomes permanent.
construction time.
One additional restriction is that immutables can only be assigned to inside expressions for which
there is no possibility of being executed after creation.
This excludes all modifier definitions and functions other than constructors.
There are no restrictions on reading immutable variables.
The read is even allowed to happen before the variable is written to for the first time because variables in
Solidity always have a well-defined initial value.
For this reason it is also allowed to never explicitly assign a value to an immutable.
.. warning::
When accessing immutables at construction time, please keep the :ref:`initialization order
<state-variable-initialization-order>` in mind.
Even if you provide an explicit initializer, some expressions may end up being evaluated before
that initializer, especially when they are at a different level in inheritance hierarchy.
.. note::
Before Solidity 0.8.21 initialization of immutable variables was more restrictive.
Such variables had to be initialized exactly once at construction time and could not be read
before then.
The contract creation code generated by the compiler will modify the The contract creation code generated by the compiler will modify the
contract's runtime code before it is returned by replacing all references contract's runtime code before it is returned by replacing all references
@ -86,14 +109,3 @@ you are comparing the
runtime code generated by the compiler with the one actually stored in the runtime code generated by the compiler with the one actually stored in the
blockchain. The compiler outputs where these immutables are located in the deployed bytecode blockchain. The compiler outputs where these immutables are located in the deployed bytecode
in the ``immutableReferences`` field of the :ref:`compiler JSON standard output <compiler-api>`. in the ``immutableReferences`` field of the :ref:`compiler JSON standard output <compiler-api>`.
.. note::
Immutables that are assigned at their declaration are only considered
initialized once the constructor of the contract is executing.
This means you cannot initialize immutables inline with a value
that depends on another immutable. You can do this, however,
inside the constructor of the contract.
This is a safeguard against different interpretations about the order
of state variable initialization and constructor execution, especially
with regards to inheritance.

View File

@ -9,9 +9,10 @@ Events
Solidity events give an abstraction on top of the EVM's logging functionality. 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. Applications can subscribe and listen to these events through the RPC interface of an Ethereum client.
Events are inheritable members of contracts. When you call them, they cause the Events can be defined at file level or as inheritable members of contracts (including interfaces and libraries).
When you call them, they cause the
arguments to be stored in the transaction's log - a special data structure 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, in the blockchain. These logs are associated with the address of the contract that emitted them,
are incorporated into the blockchain, and stay there as long as a block is are incorporated into the blockchain, and stay there as long as a block is
accessible (forever as of now, but this might accessible (forever as of now, but this might
change with Serenity). The Log and its event data is not accessible from within 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. body.
The ``_`` symbol can appear in the modifier multiple times. Each occurrence is replaced with The ``_`` symbol can appear in the modifier multiple times. Each occurrence is replaced with
the function body. the function body, and the function returns the return value of the final occurrence.
Arbitrary expressions are allowed for modifier arguments and in this context, Arbitrary expressions are allowed for modifier arguments and in this context,
all symbols visible from the function are visible in the modifier. Symbols all symbols visible from the function are visible in the modifier. Symbols

View File

@ -65,7 +65,7 @@ inheritance.
Types defined inside interfaces and other contract-like structures Types defined inside interfaces and other contract-like structures
can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``. can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``.
.. warning: .. warning::
Interfaces have supported ``enum`` types since :doc:`Solidity version 0.5.0 <050-breaking-changes>`, make Interfaces have supported ``enum`` types since :doc:`Solidity version 0.5.0 <050-breaking-changes>`, make
sure the pragma version specifies this version as a minimum. sure the pragma version specifies this version as a minimum.

View File

@ -22,6 +22,7 @@ sourceUnit: (
| enumDefinition | enumDefinition
| userDefinedValueTypeDefinition | userDefinedValueTypeDefinition
| errorDefinition | errorDefinition
| eventDefinition
)* EOF; )* EOF;
//@doc: inline //@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. | | `CMake`_ (version 3.21.3+ on | Cross-platform build file generator. |
| Windows, 3.13+ otherwise) | | | Windows, 3.13+ otherwise) | |
+-----------------------------------+-------------------------------------------------------+ +-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.77 on | C++ libraries. | | `Boost`_ (version 1.77+ on | C++ libraries. |
| Windows, 1.65+ otherwise) | | | Windows, 1.65+ otherwise) | |
+-----------------------------------+-------------------------------------------------------+ +-----------------------------------+-------------------------------------------------------+
| `Git`_ | Command-line tool for retrieving source code. | | `Git`_ | Command-line tool for retrieving source code. |
@ -380,7 +380,7 @@ Prerequisites - macOS
--------------------- ---------------------
For macOS builds, ensure that you have the latest version of For macOS builds, ensure that you have the latest version of
`Xcode installed <https://developer.apple.com/xcode/download/>`_. `Xcode installed <https://developer.apple.com/xcode/resources/>`_.
This contains the `Clang C++ compiler <https://en.wikipedia.org/wiki/Clang>`_, the This contains the `Clang C++ compiler <https://en.wikipedia.org/wiki/Clang>`_, the
`Xcode IDE <https://en.wikipedia.org/wiki/Xcode>`_ and other Apple development `Xcode IDE <https://en.wikipedia.org/wiki/Xcode>`_ and other Apple development
tools that are required for building C++ applications on OS X. tools that are required for building C++ applications on OS X.
@ -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. | | `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, 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 .. code-block:: bash
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOc' solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOcmu'
The order of steps is significant and affects the quality of the output. 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, Moreover, applying a step may uncover new optimization opportunities for others that were already applied,
@ -570,7 +570,7 @@ It is not applied to loop iteration-condition, because the loop control flow doe
this "outlining" of the inner expressions in all cases. We can sidestep this limitation by applying this "outlining" of the inner expressions in all cases. We can sidestep this limitation by applying
:ref:`for-loop-condition-into-body` to move the iteration condition into loop body. :ref:`for-loop-condition-into-body` to move the iteration condition into loop body.
The final program should be in a form such that (with the exception of loop conditions) The final program should be in an *expression-split form*, where (with the exception of loop conditions)
function calls cannot appear nested inside expressions function calls cannot appear nested inside expressions
and all function call arguments have to be variables. and all function call arguments have to be variables.
@ -1192,7 +1192,7 @@ This component can only be used on sources with unique names.
FullInliner FullInliner
^^^^^^^^^^^ ^^^^^^^^^^^
The Full Inliner replaces certain calls of certain functions The FullInliner replaces certain calls of certain functions
by the function's body. This is not very helpful in most cases, because by the function's body. This is not very helpful in most cases, because
it just increases the code size but does not have a benefit. Furthermore, it just increases the code size but does not have a benefit. Furthermore,
code is usually very expensive and we would often rather have shorter code is usually very expensive and we would often rather have shorter
@ -1216,6 +1216,11 @@ we can run the optimizer on this specialized function. If it
results in heavy gains, the specialized function is kept, results in heavy gains, the specialized function is kept,
otherwise the original function is used instead. otherwise the original function is used instead.
FunctionHoister and ExpressionSplitter are recommended as prerequisites since they make the step
more efficient, but are not required for correctness.
In particular, function calls with other function calls as arguments are not inlined, but running
ExpressionSplitter beforehand ensures that there are no such calls in the input.
Cleanup Cleanup
------- -------

View File

@ -30,6 +30,8 @@ Semantic Only Changes
This section lists the changes that are semantic-only, thus potentially This section lists the changes that are semantic-only, thus potentially
hiding new and different behavior in existing code. hiding new and different behavior in existing code.
.. _state-variable-initialization-order:
- The order of state variable initialization has changed in case of inheritance. - The order of state variable initialization has changed in case of inheritance.
The order used to be: The order used to be:

View File

@ -1,27 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <svg width="100" height="160" viewBox="0 0 100 160" fill="#2B247C" xmlns="http://www.w3.org/2000/svg">
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <path opacity="0.8" d="M50 44.3013L25 1L0 44.3013L25 87.6025L50 44.3013Z" />
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <path opacity="0.45" d="M50 44.3091L75 1.00781L25 1.00781L0 44.3091H50Z" />
<svg version="1.1" id="Layer_1" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" <path opacity="0.6" d="M75 1.00781L25 1.00781L50 44.3091H100L75 1.00781Z" />
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1300px" height="1300px" <path opacity="0.8" d="M50 115.699L75 159L100 115.699L75 72.3975L50 115.699Z" />
viewBox="0 0 1300 1300" enable-background="new 0 0 1300 1300" xml:space="preserve"> <path opacity="0.45" d="M50 115.691L25 158.993H75L100 115.691L50 115.691Z" />
<title>Vector 1</title> <path opacity="0.6" d="M25 158.993H75L50 115.691L0 115.691L25 158.993Z" />
<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> </svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 574 B

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``. 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 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/iterable_mapping.sol``. Loader, which will then look in ``/project/dapp-bin/library/math.sol``.
.. warning:: .. warning::

View File

@ -71,7 +71,7 @@ Editor Integrations
* Visual Studio Code (VS Code) * Visual Studio Code (VS Code)
* `Ethereum Remix Visual Studio Code extension <https://marketplace.visualstudio.com/items?itemName=RemixProject.ethereum-remix>`_ * `Ethereum Remix Visual Studio Code extension <https://github.com/ethereum/remix-vscode>`_
Ethereum Remix extension pack for VS Code Ethereum Remix extension pack for VS Code
* `Solidity Visual Studio Code extension, by Juan Blanco <https://juan.blanco.ws/solidity-contracts-in-visual-studio-code/>`_ * `Solidity Visual Studio Code extension, by Juan Blanco <https://juan.blanco.ws/solidity-contracts-in-visual-studio-code/>`_
@ -113,9 +113,6 @@ Solidity Tools
* `leafleth <https://github.com/clemlak/leafleth>`_ * `leafleth <https://github.com/clemlak/leafleth>`_
A documentation generator for Solidity smart-contracts. A documentation generator for Solidity smart-contracts.
* `PIET <https://piet.slock.it/>`_
A tool to develop, audit and use Solidity smart contracts through a simple graphical interface.
* `Scaffold-ETH <https://github.com/scaffold-eth/scaffold-eth>`_ * `Scaffold-ETH <https://github.com/scaffold-eth/scaffold-eth>`_
Forkable Ethereum development stack focused on fast product iterations. Forkable Ethereum development stack focused on fast product iterations.

View File

@ -636,7 +636,7 @@ expression type.
It is also helpful to cast the called contract's variable as the type of the It is also helpful to cast the called contract's variable as the type of the
most derived type in case of inheritance. most derived type in case of inheritance.
.. code-block:: solidity .. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0; pragma solidity >=0.8.0;
@ -697,8 +697,9 @@ storage for ``address`` variables, therefore if ``B.a`` had type ``address``
the encoding would assume that its storage does not change in between the encoding would assume that its storage does not change in between
transactions to ``B``. transactions to ``B``.
.. code-block:: solidity .. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0; pragma solidity >=0.8.0;
contract A { contract A {

27
docs/solidity_logo.svg Normal file
View File

@ -0,0 +1,27 @@
<?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>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

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

View File

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

View File

@ -380,7 +380,7 @@ The following properties are available for a contract type ``C``:
In addition to the properties above, the following properties are available In addition to the properties above, the following properties are available
for an interface type ``I``: for an interface type ``I``:
``type(I).interfaceId``: ``type(I).interfaceId``
A ``bytes4`` value containing the `EIP-165 <https://eips.ethereum.org/EIPS/eip-165>`_ A ``bytes4`` value containing the `EIP-165 <https://eips.ethereum.org/EIPS/eip-165>`_
interface identifier of the given interface ``I``. This identifier is defined as the ``XOR`` of all interface identifier of the given interface ``I``. This identifier is defined as the ``XOR`` of all
function selectors defined within the interface itself - excluding all inherited functions. function selectors defined within the interface itself - excluding all inherited functions.

View File

@ -316,7 +316,8 @@ Input Description
}, },
// Version of the EVM to compile for. // Version of the EVM to compile for.
// Affects type checking and code generation. Can be homestead, // Affects type checking and code generation. Can be homestead,
// tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg, istanbul, berlin, london or paris // tangerineWhistle, spuriousDragon, byzantium, constantinople,
// petersburg, istanbul, berlin, london, paris or shanghai (default)
"evmVersion": "byzantium", "evmVersion": "byzantium",
// Optional: Change compilation pipeline to go through the Yul intermediate representation. // Optional: Change compilation pipeline to go through the Yul intermediate representation.
// This is false by default. // This is false by default.
@ -358,7 +359,7 @@ Input Description
// Addresses of the libraries. If not all libraries are given here, // Addresses of the libraries. If not all libraries are given here,
// it can result in unlinked objects whose output data is different. // it can result in unlinked objects whose output data is different.
"libraries": { "libraries": {
// The top level key is the the name of the source file where the library is used. // The top level key is the name of the source file where the library is used.
// If remappings are used, this source file should match the global path // If remappings are used, this source file should match the global path
// after remappings were applied. // after remappings were applied.
// If this key is an empty string, that refers to a global level. // If this key is an empty string, that refers to a global level.
@ -407,7 +408,7 @@ Input Description
// evm.methodIdentifiers - The list of function hashes // evm.methodIdentifiers - The list of function hashes
// evm.gasEstimates - Function gas estimates // evm.gasEstimates - Function gas estimates
// //
// Note that using a using `evm`, `evm.bytecode`, etc. will select every // Note that using `evm`, `evm.bytecode`, etc. will select every
// target part of that output. Additionally, `*` can be used as a wildcard to request everything. // target part of that output. Additionally, `*` can be used as a wildcard to request everything.
// //
"outputSelection": { "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 default dialect of Yul currently is the EVM dialect for the currently selected version of the EVM.
with a version of the EVM. The only type available in this dialect The only type available in this dialect
is ``u256``, the 256-bit native type of the Ethereum Virtual Machine. 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. Since it is the default type of this dialect, it can be omitted.

View File

@ -42,7 +42,6 @@
#include <fstream> #include <fstream>
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -77,7 +76,7 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
namespace namespace
{ {
string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) std::string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location)
{ {
if (!_location.hasText() || _sourceCodes.empty()) if (!_location.hasText() || _sourceCodes.empty())
return {}; return {};
@ -92,7 +91,7 @@ string locationFromSources(StringMap const& _sourceCodes, SourceLocation const&
class Functionalizer class Functionalizer
{ {
public: public:
Functionalizer (ostream& _out, string const& _prefix, StringMap const& _sourceCodes, Assembly const& _assembly): Functionalizer (std::ostream& _out, std::string const& _prefix, StringMap const& _sourceCodes, Assembly const& _assembly):
m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes), m_assembly(_assembly) m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes), m_assembly(_assembly)
{} {}
@ -105,7 +104,7 @@ public:
printLocation(_debugInfoSelection); printLocation(_debugInfoSelection);
} }
string expression = _item.toAssemblyText(m_assembly); std::string expression = _item.toAssemblyText(m_assembly);
if (!( if (!(
_item.canBeFunctional() && _item.canBeFunctional() &&
@ -114,7 +113,7 @@ public:
)) ))
{ {
flush(); flush();
m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << endl; m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << std::endl;
return; return;
} }
if (_item.arguments() > 0) if (_item.arguments() > 0)
@ -137,8 +136,8 @@ public:
void flush() void flush()
{ {
for (string const& expression: m_pending) for (std::string const& expression: m_pending)
m_out << m_prefix << " " << expression << endl; m_out << m_prefix << " " << expression << std::endl;
m_pending.clear(); m_pending.clear();
} }
@ -154,7 +153,7 @@ public:
if (m_location.sourceName) if (m_location.sourceName)
m_out << " " + escapeAndQuoteString(*m_location.sourceName); m_out << " " + escapeAndQuoteString(*m_location.sourceName);
if (m_location.hasText()) if (m_location.hasText())
m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end); m_out << ":" << std::to_string(m_location.start) + ":" + std::to_string(m_location.end);
} }
if (_debugInfoSelection.snippet) if (_debugInfoSelection.snippet)
@ -165,15 +164,15 @@ public:
m_out << locationFromSources(m_sourceCodes, m_location); m_out << locationFromSources(m_sourceCodes, m_location);
} }
m_out << " */" << endl; m_out << " */" << std::endl;
} }
private: private:
strings m_pending; strings m_pending;
SourceLocation m_location; SourceLocation m_location;
ostream& m_out; std::ostream& m_out;
string const& m_prefix; std::string const& m_prefix;
StringMap const& m_sourceCodes; StringMap const& m_sourceCodes;
Assembly const& m_assembly; Assembly const& m_assembly;
}; };
@ -181,9 +180,9 @@ private:
} }
void Assembly::assemblyStream( void Assembly::assemblyStream(
ostream& _out, std::ostream& _out,
DebugInfoSelection const& _debugInfoSelection, DebugInfoSelection const& _debugInfoSelection,
string const& _prefix, std::string const& _prefix,
StringMap const& _sourceCodes StringMap const& _sourceCodes
) const ) const
{ {
@ -195,34 +194,34 @@ void Assembly::assemblyStream(
if (!m_data.empty() || !m_subs.empty()) if (!m_data.empty() || !m_subs.empty())
{ {
_out << _prefix << "stop" << endl; _out << _prefix << "stop" << std::endl;
for (auto const& i: m_data) for (auto const& i: m_data)
if (u256(i.first) >= m_subs.size()) if (u256(i.first) >= m_subs.size())
_out << _prefix << "data_" << toHex(u256(i.first)) << " " << util::toHex(i.second) << endl; _out << _prefix << "data_" << toHex(u256(i.first)) << " " << util::toHex(i.second) << std::endl;
for (size_t i = 0; i < m_subs.size(); ++i) for (size_t i = 0; i < m_subs.size(); ++i)
{ {
_out << endl << _prefix << "sub_" << i << ": assembly {\n"; _out << std::endl << _prefix << "sub_" << i << ": assembly {\n";
m_subs[i]->assemblyStream(_out, _debugInfoSelection, _prefix + " ", _sourceCodes); m_subs[i]->assemblyStream(_out, _debugInfoSelection, _prefix + " ", _sourceCodes);
_out << _prefix << "}" << endl; _out << _prefix << "}" << std::endl;
} }
} }
if (m_auxiliaryData.size() > 0) if (m_auxiliaryData.size() > 0)
_out << endl << _prefix << "auxdata: 0x" << util::toHex(m_auxiliaryData) << endl; _out << std::endl << _prefix << "auxdata: 0x" << util::toHex(m_auxiliaryData) << std::endl;
} }
string Assembly::assemblyString( std::string Assembly::assemblyString(
DebugInfoSelection const& _debugInfoSelection, DebugInfoSelection const& _debugInfoSelection,
StringMap const& _sourceCodes StringMap const& _sourceCodes
) const ) const
{ {
ostringstream tmp; std::ostringstream tmp;
assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes); assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes);
return tmp.str(); return tmp.str();
} }
Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices, bool _includeSourceList) const Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourceIndices, bool _includeSourceList) const
{ {
Json::Value root; Json::Value root;
root[".code"] = Json::arrayValue; root[".code"] = Json::arrayValue;
@ -244,7 +243,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
jsonItem["end"] = item.location().end; jsonItem["end"] = item.location().end;
if (item.m_modifierDepth != 0) if (item.m_modifierDepth != 0)
jsonItem["modifierDepth"] = static_cast<int>(item.m_modifierDepth); jsonItem["modifierDepth"] = static_cast<int>(item.m_modifierDepth);
string jumpType = item.getJumpTypeAsString(); std::string jumpType = item.getJumpTypeAsString();
if (!jumpType.empty()) if (!jumpType.empty())
jsonItem["jumpType"] = jumpType; jsonItem["jumpType"] = jumpType;
if (name == "PUSHLIB") if (name == "PUSHLIB")
@ -286,8 +285,8 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
for (size_t i = 0; i < m_subs.size(); ++i) for (size_t i = 0; i < m_subs.size(); ++i)
{ {
stringstream hexStr; std::stringstream hexStr;
hexStr << hex << i; hexStr << std::hex << i;
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, /*_includeSourceList = */false); data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, /*_includeSourceList = */false);
} }
} }
@ -298,7 +297,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
return root; return root;
} }
AssemblyItem Assembly::namedTag(string const& _name, size_t _params, size_t _returns, optional<uint64_t> _sourceID) AssemblyItem Assembly::namedTag(std::string const& _name, size_t _params, size_t _returns, std::optional<uint64_t> _sourceID)
{ {
assertThrow(!_name.empty(), AssemblyException, "Empty named tag."); assertThrow(!_name.empty(), AssemblyException, "Empty named tag.");
if (m_namedTags.count(_name)) if (m_namedTags.count(_name))
@ -312,21 +311,21 @@ AssemblyItem Assembly::namedTag(string const& _name, size_t _params, size_t _ret
return AssemblyItem{Tag, m_namedTags.at(_name).id}; return AssemblyItem{Tag, m_namedTags.at(_name).id};
} }
AssemblyItem Assembly::newPushLibraryAddress(string const& _identifier) AssemblyItem Assembly::newPushLibraryAddress(std::string const& _identifier)
{ {
h256 h(util::keccak256(_identifier)); h256 h(util::keccak256(_identifier));
m_libraries[h] = _identifier; m_libraries[h] = _identifier;
return AssemblyItem{PushLibraryAddress, h}; return AssemblyItem{PushLibraryAddress, h};
} }
AssemblyItem Assembly::newPushImmutable(string const& _identifier) AssemblyItem Assembly::newPushImmutable(std::string const& _identifier)
{ {
h256 h(util::keccak256(_identifier)); h256 h(util::keccak256(_identifier));
m_immutables[h] = _identifier; m_immutables[h] = _identifier;
return AssemblyItem{PushImmutable, h}; return AssemblyItem{PushImmutable, h};
} }
AssemblyItem Assembly::newImmutableAssignment(string const& _identifier) AssemblyItem Assembly::newImmutableAssignment(std::string const& _identifier)
{ {
h256 h(util::keccak256(_identifier)); h256 h(util::keccak256(_identifier));
m_immutables[h] = _identifier; m_immutables[h] = _identifier;
@ -339,9 +338,9 @@ Assembly& Assembly::optimise(OptimiserSettings const& _settings)
return *this; return *this;
} }
map<u256, u256> const& Assembly::optimiseInternal( std::map<u256, u256> const& Assembly::optimiseInternal(
OptimiserSettings const& _settings, OptimiserSettings const& _settings,
set<size_t> _tagsReferencedFromOutside std::set<size_t> _tagsReferencedFromOutside
) )
{ {
if (m_tagReplacements) if (m_tagReplacements)
@ -352,7 +351,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
{ {
OptimiserSettings settings = _settings; OptimiserSettings settings = _settings;
Assembly& sub = *m_subs[subId]; Assembly& sub = *m_subs[subId];
map<u256, u256> const& subTagReplacements = sub.optimiseInternal( std::map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
settings, settings,
JumpdestRemover::referencedTags(m_items, subId) JumpdestRemover::referencedTags(m_items, subId)
); );
@ -360,7 +359,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId); BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId);
} }
map<u256, u256> tagReplacements; std::map<u256, u256> tagReplacements;
// Iterate until no new optimisation possibilities are found. // Iterate until no new optimisation possibilities are found.
for (unsigned count = 1; count > 0;) for (unsigned count = 1; count > 0;)
{ {
@ -401,7 +400,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
for (auto const& replacement: deduplicator.replacedTags()) for (auto const& replacement: deduplicator.replacedTags())
{ {
assertThrow( assertThrow(
replacement.first <= numeric_limits<size_t>::max() && replacement.second <= numeric_limits<size_t>::max(), replacement.first <= std::numeric_limits<size_t>::max() && replacement.second <= std::numeric_limits<size_t>::max(),
OptimizerException, OptimizerException,
"Invalid tag replacement." "Invalid tag replacement."
); );
@ -494,7 +493,7 @@ LinkerObject const& Assembly::assemble() const
LinkerObject& ret = m_assembledObject; LinkerObject& ret = m_assembledObject;
size_t subTagSize = 1; size_t subTagSize = 1;
map<u256, pair<string, vector<size_t>>> immutableReferencesBySub; std::map<u256, std::pair<std::string, std::vector<size_t>>> immutableReferencesBySub;
for (auto const& sub: m_subs) for (auto const& sub: m_subs)
{ {
auto const& linkerObject = sub->assemble(); auto const& linkerObject = sub->assemble();
@ -508,7 +507,7 @@ LinkerObject const& Assembly::assemble() const
immutableReferencesBySub = linkerObject.immutableReferences; immutableReferencesBySub = linkerObject.immutableReferences;
} }
for (size_t tagPos: sub->m_tagPositionsInBytecode) for (size_t tagPos: sub->m_tagPositionsInBytecode)
if (tagPos != numeric_limits<size_t>::max() && tagPos > subTagSize) if (tagPos != std::numeric_limits<size_t>::max() && tagPos > subTagSize)
subTagSize = tagPos; subTagSize = tagPos;
} }
@ -531,11 +530,11 @@ LinkerObject const& Assembly::assemble() const
); );
unsigned bytesRequiredForCode = codeSize(static_cast<unsigned>(subTagSize)); unsigned bytesRequiredForCode = codeSize(static_cast<unsigned>(subTagSize));
m_tagPositionsInBytecode = vector<size_t>(m_usedTags, numeric_limits<size_t>::max()); m_tagPositionsInBytecode = std::vector<size_t>(m_usedTags, std::numeric_limits<size_t>::max());
map<size_t, pair<size_t, size_t>> tagRef; std::map<size_t, std::pair<size_t, size_t>> tagRef;
multimap<h256, unsigned> dataRef; std::multimap<h256, unsigned> dataRef;
multimap<size_t, size_t> subRef; std::multimap<size_t, size_t> subRef;
vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted std::vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode); unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode);
uint8_t tagPush = static_cast<uint8_t>(pushInstruction(bytesPerTag)); uint8_t tagPush = static_cast<uint8_t>(pushInstruction(bytesPerTag));
@ -550,7 +549,7 @@ LinkerObject const& Assembly::assemble() const
for (AssemblyItem const& i: m_items) for (AssemblyItem const& i: m_items)
{ {
// store position of the invalid jump destination // store position of the invalid jump destination
if (i.type() != Tag && m_tagPositionsInBytecode[0] == numeric_limits<size_t>::max()) if (i.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits<size_t>::max())
m_tagPositionsInBytecode[0] = ret.bytecode.size(); m_tagPositionsInBytecode[0] = ret.bytecode.size();
switch (i.type()) switch (i.type())
@ -583,21 +582,21 @@ LinkerObject const& Assembly::assemble() const
} }
case PushData: case PushData:
ret.bytecode.push_back(dataRefPush); ret.bytecode.push_back(dataRefPush);
dataRef.insert(make_pair(h256(i.data()), ret.bytecode.size())); dataRef.insert(std::make_pair(h256(i.data()), ret.bytecode.size()));
ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef);
break; break;
case PushSub: case PushSub:
assertThrow(i.data() <= numeric_limits<size_t>::max(), AssemblyException, ""); assertThrow(i.data() <= std::numeric_limits<size_t>::max(), AssemblyException, "");
ret.bytecode.push_back(dataRefPush); ret.bytecode.push_back(dataRefPush);
subRef.insert(make_pair(static_cast<size_t>(i.data()), ret.bytecode.size())); subRef.insert(std::make_pair(static_cast<size_t>(i.data()), ret.bytecode.size()));
ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef); ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef);
break; break;
case PushSubSize: case PushSubSize:
{ {
assertThrow(i.data() <= numeric_limits<size_t>::max(), AssemblyException, ""); assertThrow(i.data() <= std::numeric_limits<size_t>::max(), AssemblyException, "");
auto s = subAssemblyById(static_cast<size_t>(i.data()))->assemble().bytecode.size(); auto s = subAssemblyById(static_cast<size_t>(i.data()))->assemble().bytecode.size();
i.setPushedValue(u256(s)); i.setPushedValue(u256(s));
unsigned b = max<unsigned>(1, numberEncodingSize(s)); unsigned b = std::max<unsigned>(1, numberEncodingSize(s));
ret.bytecode.push_back(static_cast<uint8_t>(pushInstruction(b))); ret.bytecode.push_back(static_cast<uint8_t>(pushInstruction(b)));
ret.bytecode.resize(ret.bytecode.size() + b); ret.bytecode.resize(ret.bytecode.size() + b);
bytesRef byr(&ret.bytecode.back() + 1 - b, b); bytesRef byr(&ret.bytecode.back() + 1 - b, b);
@ -618,7 +617,7 @@ LinkerObject const& Assembly::assemble() const
break; break;
case PushImmutable: case PushImmutable:
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::PUSH32)); ret.bytecode.push_back(static_cast<uint8_t>(Instruction::PUSH32));
// Maps keccak back to the "identifier" string of that immutable. // Maps keccak back to the "identifier" std::string of that immutable.
ret.immutableReferences[i.data()].first = m_immutables.at(i.data()); ret.immutableReferences[i.data()].first = m_immutables.at(i.data());
// Record the bytecode offset of the PUSH32 argument. // Record the bytecode offset of the PUSH32 argument.
ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size()); ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size());
@ -661,10 +660,10 @@ LinkerObject const& Assembly::assemble() const
case Tag: case Tag:
{ {
assertThrow(i.data() != 0, AssemblyException, "Invalid tag position."); assertThrow(i.data() != 0, AssemblyException, "Invalid tag position.");
assertThrow(i.splitForeignPushTag().first == numeric_limits<size_t>::max(), AssemblyException, "Foreign tag."); assertThrow(i.splitForeignPushTag().first == std::numeric_limits<size_t>::max(), AssemblyException, "Foreign tag.");
size_t tagId = static_cast<size_t>(i.data()); size_t tagId = static_cast<size_t>(i.data());
assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large.");
assertThrow(m_tagPositionsInBytecode[tagId] == numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position."); assertThrow(m_tagPositionsInBytecode[tagId] == std::numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position.");
m_tagPositionsInBytecode[tagId] = ret.bytecode.size(); m_tagPositionsInBytecode[tagId] = ret.bytecode.size();
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST)); ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
break; break;
@ -686,7 +685,7 @@ LinkerObject const& Assembly::assemble() const
// Append an INVALID here to help tests find miscompilation. // Append an INVALID here to help tests find miscompilation.
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::INVALID)); ret.bytecode.push_back(static_cast<uint8_t>(Instruction::INVALID));
map<LinkerObject, size_t> subAssemblyOffsets; std::map<LinkerObject, size_t> subAssemblyOffsets;
for (auto const& [subIdPath, bytecodeOffset]: subRef) for (auto const& [subIdPath, bytecodeOffset]: subRef)
{ {
LinkerObject subObject = subAssemblyById(subIdPath)->assemble(); LinkerObject subObject = subAssemblyById(subIdPath)->assemble();
@ -709,15 +708,15 @@ LinkerObject const& Assembly::assemble() const
{ {
size_t subId; size_t subId;
size_t tagId; size_t tagId;
tie(subId, tagId) = i.second; std::tie(subId, tagId) = i.second;
assertThrow(subId == numeric_limits<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id"); assertThrow(subId == std::numeric_limits<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id");
vector<size_t> const& tagPositions = std::vector<size_t> const& tagPositions =
subId == numeric_limits<size_t>::max() ? subId == std::numeric_limits<size_t>::max() ?
m_tagPositionsInBytecode : m_tagPositionsInBytecode :
m_subs[subId]->m_tagPositionsInBytecode; m_subs[subId]->m_tagPositionsInBytecode;
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag."); assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag.");
size_t pos = tagPositions[tagId]; size_t pos = tagPositions[tagId];
assertThrow(pos != numeric_limits<size_t>::max(), AssemblyException, "Reference to tag without position."); assertThrow(pos != std::numeric_limits<size_t>::max(), AssemblyException, "Reference to tag without position.");
assertThrow(numberEncodingSize(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space."); assertThrow(numberEncodingSize(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space.");
bytesRef r(ret.bytecode.data() + i.first, bytesPerTag); bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
toBigEndian(pos, r); toBigEndian(pos, r);
@ -725,7 +724,7 @@ LinkerObject const& Assembly::assemble() const
for (auto const& [name, tagInfo]: m_namedTags) for (auto const& [name, tagInfo]: m_namedTags)
{ {
size_t position = m_tagPositionsInBytecode.at(tagInfo.id); size_t position = m_tagPositionsInBytecode.at(tagInfo.id);
optional<size_t> tagIndex; std::optional<size_t> tagIndex;
for (auto&& [index, item]: m_items | ranges::views::enumerate) for (auto&& [index, item]: m_items | ranges::views::enumerate)
if (item.type() == Tag && static_cast<size_t>(item.data()) == tagInfo.id) if (item.type() == Tag && static_cast<size_t>(item.data()) == tagInfo.id)
{ {
@ -733,7 +732,7 @@ LinkerObject const& Assembly::assemble() const
break; break;
} }
ret.functionDebugData[name] = { ret.functionDebugData[name] = {
position == numeric_limits<size_t>::max() ? nullopt : optional<size_t>{position}, position == std::numeric_limits<size_t>::max() ? std::nullopt : std::optional<size_t>{position},
tagIndex, tagIndex,
tagInfo.sourceID, tagInfo.sourceID,
tagInfo.params, tagInfo.params,
@ -764,7 +763,7 @@ LinkerObject const& Assembly::assemble() const
return ret; return ret;
} }
vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const std::vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const
{ {
if (_subObjectId < m_subs.size()) if (_subObjectId < m_subs.size())
return {_subObjectId}; return {_subObjectId};
@ -779,7 +778,7 @@ vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const
return subIdPathIt->first; return subIdPathIt->first;
} }
size_t Assembly::encodeSubPath(vector<size_t> const& _subPath) size_t Assembly::encodeSubPath(std::vector<size_t> const& _subPath)
{ {
assertThrow(!_subPath.empty(), AssemblyException, ""); assertThrow(!_subPath.empty(), AssemblyException, "");
if (_subPath.size() == 1) if (_subPath.size() == 1)
@ -790,7 +789,7 @@ size_t Assembly::encodeSubPath(vector<size_t> const& _subPath)
if (m_subPaths.find(_subPath) == m_subPaths.end()) if (m_subPaths.find(_subPath) == m_subPaths.end())
{ {
size_t objectId = numeric_limits<size_t>::max() - m_subPaths.size(); size_t objectId = std::numeric_limits<size_t>::max() - m_subPaths.size();
assertThrow(objectId >= m_subs.size(), AssemblyException, ""); assertThrow(objectId >= m_subs.size(), AssemblyException, "");
m_subPaths[_subPath] = objectId; m_subPaths[_subPath] = objectId;
} }
@ -800,7 +799,7 @@ size_t Assembly::encodeSubPath(vector<size_t> const& _subPath)
Assembly const* Assembly::subAssemblyById(size_t _subId) const Assembly const* Assembly::subAssemblyById(size_t _subId) const
{ {
vector<size_t> subIds = decodeSubPath(_subId); std::vector<size_t> subIds = decodeSubPath(_subId);
Assembly const* currentAssembly = this; Assembly const* currentAssembly = this;
for (size_t currentSubId: subIds) for (size_t currentSubId: subIds)
{ {

View File

@ -30,7 +30,7 @@
#include <fstream> #include <fstream>
#include <limits> #include <limits>
using namespace std; using namespace std::literals;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -40,10 +40,10 @@ static_assert(sizeof(size_t) <= 8, "size_t must be at most 64-bits wide");
namespace namespace
{ {
string toStringInHex(u256 _value) std::string toStringInHex(u256 _value)
{ {
stringstream hexStr; std::stringstream hexStr;
hexStr << uppercase << hex << _value; hexStr << std::uppercase << std::hex << _value;
return hexStr.str(); return hexStr.str();
} }
@ -60,16 +60,16 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const
return r; return r;
} }
pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const std::pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const
{ {
assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); assertThrow(m_type == PushTag || m_type == Tag, util::Exception, "");
u256 combined = u256(data()); u256 combined = u256(data());
size_t subId = static_cast<size_t>((combined >> 64) - 1); size_t subId = static_cast<size_t>((combined >> 64) - 1);
size_t tag = static_cast<size_t>(combined & 0xffffffffffffffffULL); size_t tag = static_cast<size_t>(combined & 0xffffffffffffffffULL);
return make_pair(subId, tag); return std::make_pair(subId, tag);
} }
pair<string, string> AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const std::pair<std::string, std::string> AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const
{ {
switch (type()) switch (type())
{ {
@ -111,7 +111,7 @@ void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag)
{ {
assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); assertThrow(m_type == PushTag || m_type == Tag, util::Exception, "");
u256 data = _tag; u256 data = _tag;
if (_subId != numeric_limits<size_t>::max()) if (_subId != std::numeric_limits<size_t>::max())
data |= (u256(_subId) + 1) << 64; data |= (u256(_subId) + 1) << 64;
setData(data); setData(data);
} }
@ -124,7 +124,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision)
case Tag: // 1 byte for the JUMPDEST case Tag: // 1 byte for the JUMPDEST
return 1; return 1;
case Push: case Push:
return 1 + max<size_t>(1, numberEncodingSize(data())); return 1 + std::max<size_t>(1, numberEncodingSize(data()));
case PushSubSize: case PushSubSize:
case PushProgramSize: case PushProgramSize:
return 1 + 4; // worst case: a 16MB program return 1 + 4; // worst case: a 16MB program
@ -158,7 +158,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision)
return 2; return 2;
} }
case VerbatimBytecode: case VerbatimBytecode:
return get<2>(*m_verbatimBytecode).size(); return std::get<2>(*m_verbatimBytecode).size();
default: default:
break; break;
} }
@ -172,7 +172,7 @@ size_t AssemblyItem::arguments() const
// the same across all EVM versions except for the instruction name. // the same across all EVM versions except for the instruction name.
return static_cast<size_t>(instructionInfo(instruction(), EVMVersion()).args); return static_cast<size_t>(instructionInfo(instruction(), EVMVersion()).args);
else if (type() == VerbatimBytecode) else if (type() == VerbatimBytecode)
return get<0>(*m_verbatimBytecode); return std::get<0>(*m_verbatimBytecode);
else if (type() == AssignImmutable) else if (type() == AssignImmutable)
return 2; return 2;
else else
@ -200,7 +200,7 @@ size_t AssemblyItem::returnValues() const
case Tag: case Tag:
return 0; return 0;
case VerbatimBytecode: case VerbatimBytecode:
return get<1>(*m_verbatimBytecode); return std::get<1>(*m_verbatimBytecode);
default: default:
break; break;
} }
@ -233,7 +233,7 @@ bool AssemblyItem::canBeFunctional() const
return false; return false;
} }
string AssemblyItem::getJumpTypeAsString() const std::string AssemblyItem::getJumpTypeAsString() const
{ {
switch (m_jumpType) switch (m_jumpType)
{ {
@ -247,9 +247,9 @@ string AssemblyItem::getJumpTypeAsString() const
} }
} }
string AssemblyItem::toAssemblyText(Assembly const& _assembly) const std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
{ {
string text; std::string text;
switch (type()) switch (type())
{ {
case Operation: case Operation:
@ -265,26 +265,26 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
{ {
size_t sub{0}; size_t sub{0};
size_t tag{0}; size_t tag{0};
tie(sub, tag) = splitForeignPushTag(); std::tie(sub, tag) = splitForeignPushTag();
if (sub == numeric_limits<size_t>::max()) if (sub == std::numeric_limits<size_t>::max())
text = string("tag_") + to_string(tag); text = std::string("tag_") + std::to_string(tag);
else else
text = string("tag_") + to_string(sub) + "_" + to_string(tag); text = std::string("tag_") + std::to_string(sub) + "_" + std::to_string(tag);
break; break;
} }
case Tag: case Tag:
assertThrow(data() < 0x10000, AssemblyException, "Declaration of sub-assembly tag."); assertThrow(data() < 0x10000, AssemblyException, "Declaration of sub-assembly tag.");
text = string("tag_") + to_string(static_cast<size_t>(data())) + ":"; text = std::string("tag_") + std::to_string(static_cast<size_t>(data())) + ":";
break; break;
case PushData: case PushData:
text = string("data_") + toHex(data()); text = std::string("data_") + toHex(data());
break; break;
case PushSub: case PushSub:
case PushSubSize: case PushSubSize:
{ {
vector<string> subPathComponents; std::vector<std::string> subPathComponents;
for (size_t subPathComponentId: _assembly.decodeSubPath(static_cast<size_t>(data()))) for (size_t subPathComponentId: _assembly.decodeSubPath(static_cast<size_t>(data())))
subPathComponents.emplace_back("sub_" + to_string(subPathComponentId)); subPathComponents.emplace_back("sub_" + std::to_string(subPathComponentId));
text = text =
(type() == PushSub ? "dataOffset"s : "dataSize"s) + (type() == PushSub ? "dataOffset"s : "dataSize"s) +
"(" + "(" +
@ -293,25 +293,25 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
break; break;
} }
case PushProgramSize: case PushProgramSize:
text = string("bytecodeSize"); text = std::string("bytecodeSize");
break; break;
case PushLibraryAddress: case PushLibraryAddress:
text = string("linkerSymbol(\"") + toHex(data()) + string("\")"); text = std::string("linkerSymbol(\"") + toHex(data()) + std::string("\")");
break; break;
case PushDeployTimeAddress: case PushDeployTimeAddress:
text = string("deployTimeAddress()"); text = std::string("deployTimeAddress()");
break; break;
case PushImmutable: case PushImmutable:
text = string("immutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")"; text = std::string("immutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")";
break; break;
case AssignImmutable: case AssignImmutable:
text = string("assignImmutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")"; text = std::string("assignImmutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")";
break; break;
case UndefinedItem: case UndefinedItem:
assertThrow(false, AssemblyException, "Invalid assembly item."); assertThrow(false, AssemblyException, "Invalid assembly item.");
break; break;
case VerbatimBytecode: case VerbatimBytecode:
text = string("verbatimbytecode_") + util::toHex(get<2>(*m_verbatimBytecode)); text = std::string("verbatimbytecode_") + util::toHex(std::get<2>(*m_verbatimBytecode));
break; break;
default: default:
assertThrow(false, InvalidOpcode, ""); assertThrow(false, InvalidOpcode, "");
@ -328,7 +328,7 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
} }
// Note: This method is exclusively used for debugging. // Note: This method is exclusively used for debugging.
ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item) std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem const& _item)
{ {
switch (_item.type()) switch (_item.type())
{ {
@ -338,12 +338,12 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
_out << "\t" << _item.getJumpTypeAsString(); _out << "\t" << _item.getJumpTypeAsString();
break; break;
case Push: case Push:
_out << " PUSH " << hex << _item.data() << dec; _out << " PUSH " << std::hex << _item.data() << std::dec;
break; break;
case PushTag: case PushTag:
{ {
size_t subId = _item.splitForeignPushTag().first; size_t subId = _item.splitForeignPushTag().first;
if (subId == numeric_limits<size_t>::max()) if (subId == std::numeric_limits<size_t>::max())
_out << " PushTag " << _item.splitForeignPushTag().second; _out << " PushTag " << _item.splitForeignPushTag().second;
else else
_out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second; _out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second;
@ -353,20 +353,20 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " Tag " << _item.data(); _out << " Tag " << _item.data();
break; break;
case PushData: case PushData:
_out << " PushData " << hex << static_cast<unsigned>(_item.data()) << dec; _out << " PushData " << std::hex << static_cast<unsigned>(_item.data()) << std::dec;
break; break;
case PushSub: case PushSub:
_out << " PushSub " << hex << static_cast<size_t>(_item.data()) << dec; _out << " PushSub " << std::hex << static_cast<size_t>(_item.data()) << std::dec;
break; break;
case PushSubSize: case PushSubSize:
_out << " PushSubSize " << hex << static_cast<size_t>(_item.data()) << dec; _out << " PushSubSize " << std::hex << static_cast<size_t>(_item.data()) << std::dec;
break; break;
case PushProgramSize: case PushProgramSize:
_out << " PushProgramSize"; _out << " PushProgramSize";
break; break;
case PushLibraryAddress: case PushLibraryAddress:
{ {
string hash(util::h256((_item.data())).hex()); std::string hash(util::h256((_item.data())).hex());
_out << " PushLibraryAddress " << hash.substr(0, 8) + "..." + hash.substr(hash.length() - 8); _out << " PushLibraryAddress " << hash.substr(0, 8) + "..." + hash.substr(hash.length() - 8);
break; break;
} }
@ -411,12 +411,12 @@ size_t AssemblyItem::opcodeCount() const noexcept
} }
} }
string AssemblyItem::computeSourceMapping( std::string AssemblyItem::computeSourceMapping(
AssemblyItems const& _items, AssemblyItems const& _items,
map<string, unsigned> const& _sourceIndicesMap std::map<std::string, unsigned> const& _sourceIndicesMap
) )
{ {
string ret; std::string ret;
int prevStart = -1; int prevStart = -1;
int prevLength = -1; int prevLength = -1;
@ -465,17 +465,17 @@ string AssemblyItem::computeSourceMapping(
if (components-- > 0) if (components-- > 0)
{ {
if (location.start != prevStart) if (location.start != prevStart)
ret += to_string(location.start); ret += std::to_string(location.start);
if (components-- > 0) if (components-- > 0)
{ {
ret += ':'; ret += ':';
if (length != prevLength) if (length != prevLength)
ret += to_string(length); ret += std::to_string(length);
if (components-- > 0) if (components-- > 0)
{ {
ret += ':'; ret += ':';
if (sourceIndex != prevSourceIndex) if (sourceIndex != prevSourceIndex)
ret += to_string(sourceIndex); ret += std::to_string(sourceIndex);
if (components-- > 0) if (components-- > 0)
{ {
ret += ':'; ret += ':';
@ -485,7 +485,7 @@ string AssemblyItem::computeSourceMapping(
{ {
ret += ':'; ret += ':';
if (modifierDepth != prevModifierDepth) if (modifierDepth != prevModifierDepth)
ret += to_string(modifierDepth); ret += std::to_string(modifierDepth);
} }
} }
} }
@ -493,7 +493,7 @@ string AssemblyItem::computeSourceMapping(
} }
if (item.opcodeCount() > 1) if (item.opcodeCount() > 1)
ret += string(item.opcodeCount() - 1, ';'); ret += std::string(item.opcodeCount() - 1, ';');
prevStart = location.start; prevStart = location.start;
prevLength = length; prevLength = length;

View File

@ -30,7 +30,6 @@
#include <functional> #include <functional>
#include <set> #include <set>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -49,7 +48,7 @@ bool BlockDeduplicator::deduplicate()
) )
return false; return false;
function<bool(size_t, size_t)> comparator = [&](size_t _i, size_t _j) std::function<bool(size_t, size_t)> comparator = [&](size_t _i, size_t _j)
{ {
if (_i == _j) if (_i == _j)
return false; return false;
@ -81,7 +80,7 @@ bool BlockDeduplicator::deduplicate()
for (; ; ++iterations) for (; ; ++iterations)
{ {
//@todo this should probably be optimized. //@todo this should probably be optimized.
set<size_t, function<bool(size_t, size_t)>> blocksSeen(comparator); std::set<size_t, std::function<bool(size_t, size_t)>> blocksSeen(comparator);
for (size_t i = 0; i < m_items.size(); ++i) for (size_t i = 0; i < m_items.size(); ++i)
{ {
if (m_items.at(i).type() != Tag) if (m_items.at(i).type() != Tag)
@ -101,7 +100,7 @@ bool BlockDeduplicator::deduplicate()
bool BlockDeduplicator::applyTagReplacement( bool BlockDeduplicator::applyTagReplacement(
AssemblyItems& _items, AssemblyItems& _items,
map<u256, u256> const& _replacements, std::map<u256, u256> const& _replacements,
size_t _subId size_t _subId
) )
{ {
@ -111,7 +110,7 @@ bool BlockDeduplicator::applyTagReplacement(
{ {
size_t subId; size_t subId;
size_t tagId; size_t tagId;
tie(subId, tagId) = item.splitForeignPushTag(); std::tie(subId, tagId) = item.splitForeignPushTag();
if (subId != _subId) if (subId != _subId)
continue; continue;
auto it = _replacements.find(tagId); auto it = _replacements.find(tagId);

View File

@ -30,12 +30,11 @@
#include <range/v3/view/reverse.hpp> #include <range/v3/view/reverse.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems() std::vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
{ {
optimizeBreakingItem(); optimizeBreakingItem();
@ -52,11 +51,11 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
m_state = std::move(nextState); m_state = std::move(nextState);
}); });
map<int, Id> initialStackContents; std::map<int, Id> initialStackContents;
map<int, Id> targetStackContents; std::map<int, Id> targetStackContents;
int minHeight = m_state.stackHeight() + 1; int minHeight = m_state.stackHeight() + 1;
if (!m_state.stackElements().empty()) if (!m_state.stackElements().empty())
minHeight = min(minHeight, m_state.stackElements().begin()->first); minHeight = std::min(minHeight, m_state.stackElements().begin()->first);
for (int height = minHeight; height <= m_initialState.stackHeight(); ++height) for (int height = minHeight; height <= m_initialState.stackHeight(); ++height)
initialStackContents[height] = m_initialState.stackElement(height, SourceLocation()); initialStackContents[height] = m_initialState.stackElement(height, SourceLocation());
for (int height = minHeight; height <= m_state.stackHeight(); ++height) for (int height = minHeight; height <= m_state.stackHeight(); ++height)
@ -125,19 +124,19 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
CSECodeGenerator::CSECodeGenerator( CSECodeGenerator::CSECodeGenerator(
ExpressionClasses& _expressionClasses, ExpressionClasses& _expressionClasses,
vector<CSECodeGenerator::StoreOperation> const& _storeOperations std::vector<CSECodeGenerator::StoreOperation> const& _storeOperations
): ):
m_expressionClasses(_expressionClasses) m_expressionClasses(_expressionClasses)
{ {
for (auto const& store: _storeOperations) for (auto const& store: _storeOperations)
m_storeOperations[make_pair(store.target, store.slot)].push_back(store); m_storeOperations[std::make_pair(store.target, store.slot)].push_back(store);
} }
AssemblyItems CSECodeGenerator::generateCode( AssemblyItems CSECodeGenerator::generateCode(
unsigned _initialSequenceNumber, unsigned _initialSequenceNumber,
int _initialStackHeight, int _initialStackHeight,
map<int, Id> const& _initialStack, std::map<int, Id> const& _initialStack,
map<int, Id> const& _targetStackContents std::map<int, Id> const& _targetStackContents
) )
{ {
m_stackHeight = _initialStackHeight; m_stackHeight = _initialStackHeight;
@ -156,7 +155,7 @@ AssemblyItems CSECodeGenerator::generateCode(
} }
// store all needed sequenced expressions // store all needed sequenced expressions
set<pair<unsigned, Id>> sequencedExpressions; std::set<std::pair<unsigned, Id>> sequencedExpressions;
for (auto const& p: m_neededBy) for (auto const& p: m_neededBy)
for (auto id: {p.first, p.second}) for (auto id: {p.first, p.second})
if (unsigned seqNr = m_expressionClasses.representative(id).sequenceNumber) if (unsigned seqNr = m_expressionClasses.representative(id).sequenceNumber)
@ -165,7 +164,7 @@ AssemblyItems CSECodeGenerator::generateCode(
// @todo quick fix for now. Proper fix needs to choose representative with higher // @todo quick fix for now. Proper fix needs to choose representative with higher
// sequence number during dependency analysis. // sequence number during dependency analysis.
assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, util::stackTooDeepString); assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, util::stackTooDeepString);
sequencedExpressions.insert(make_pair(seqNr, id)); sequencedExpressions.insert(std::make_pair(seqNr, id));
} }
// Perform all operations on storage and memory in order, if they are needed. // Perform all operations on storage and memory in order, if they are needed.
@ -230,7 +229,7 @@ void CSECodeGenerator::addDependencies(Id _c)
for (Id argument: expr.arguments) for (Id argument: expr.arguments)
{ {
addDependencies(argument); addDependencies(argument);
m_neededBy.insert(make_pair(argument, _c)); m_neededBy.insert(std::make_pair(argument, _c));
} }
if (expr.item && expr.item->type() == Operation && ( if (expr.item && expr.item->type() == Operation && (
expr.item->instruction() == Instruction::SLOAD || expr.item->instruction() == Instruction::SLOAD ||
@ -294,7 +293,7 @@ void CSECodeGenerator::addDependencies(Id _c)
if (it->sequenceNumber < expr.sequenceNumber) if (it->sequenceNumber < expr.sequenceNumber)
latestStore = it->expression; latestStore = it->expression;
addDependencies(latestStore); addDependencies(latestStore);
m_neededBy.insert(make_pair(latestStore, _c)); m_neededBy.insert(std::make_pair(latestStore, _c));
} }
} }
} }
@ -331,7 +330,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
OptimizerException, OptimizerException,
"Undefined item requested but not available." "Undefined item requested but not available."
); );
vector<Id> const& arguments = expr.arguments; std::vector<Id> const& arguments = expr.arguments;
for (Id arg: arguments | ranges::views::reverse) for (Id arg: arguments | ranges::views::reverse)
generateClassElement(arg); generateClassElement(arg);
@ -495,7 +494,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons
m_classPositions[m_stack[m_stackHeight]].insert(_fromPosition); m_classPositions[m_stack[m_stackHeight]].insert(_fromPosition);
m_classPositions[m_stack[_fromPosition]].erase(_fromPosition); m_classPositions[m_stack[_fromPosition]].erase(_fromPosition);
m_classPositions[m_stack[_fromPosition]].insert(m_stackHeight); m_classPositions[m_stack[_fromPosition]].insert(m_stackHeight);
swap(m_stack[m_stackHeight], m_stack[_fromPosition]); std::swap(m_stack[m_stackHeight], m_stack[_fromPosition]);
} }
if (m_generatedItems.size() >= 2 && if (m_generatedItems.size() >= 2 &&
SemanticInformation::isSwapInstruction(m_generatedItems.back()) && SemanticInformation::isSwapInstruction(m_generatedItems.back()) &&

View File

@ -24,7 +24,6 @@
#include <libevmasm/Assembly.h> #include <libevmasm/Assembly.h>
#include <libevmasm/GasMeter.h> #include <libevmasm/GasMeter.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -39,11 +38,11 @@ unsigned ConstantOptimisationMethod::optimiseConstants(
AssemblyItems& _items = _assembly.items(); AssemblyItems& _items = _assembly.items();
unsigned optimisations = 0; unsigned optimisations = 0;
map<AssemblyItem, size_t> pushes; std::map<AssemblyItem, size_t> pushes;
for (AssemblyItem const& item: _items) for (AssemblyItem const& item: _items)
if (item.type() == Push) if (item.type() == Push)
pushes[item]++; pushes[item]++;
map<u256, AssemblyItems> pendingReplacements; std::map<u256, AssemblyItems> pendingReplacements;
for (auto it: pushes) for (auto it: pushes)
{ {
AssemblyItem const& item = it.first; AssemblyItem const& item = it.first;
@ -108,7 +107,7 @@ size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
void ConstantOptimisationMethod::replaceConstants( void ConstantOptimisationMethod::replaceConstants(
AssemblyItems& _items, AssemblyItems& _items,
map<u256, AssemblyItems> const& _replacements std::map<u256, AssemblyItems> const& _replacements
) )
{ {
AssemblyItems replaced; AssemblyItems replaced;
@ -255,7 +254,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const
{ {
// This is a tiny EVM that can only evaluate some instructions. // This is a tiny EVM that can only evaluate some instructions.
vector<u256> stack; std::vector<u256> stack;
for (AssemblyItem const& item: _routine) for (AssemblyItem const& item: _routine)
{ {
switch (item.type()) switch (item.type())

View File

@ -31,7 +31,6 @@
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
#include <libevmasm/KnownState.h> #include <libevmasm/KnownState.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -64,7 +63,7 @@ void ControlFlowGraph::findLargestTag()
{ {
// Assert that it can be converted. // Assert that it can be converted.
BlockId(item.data()); BlockId(item.data());
m_lastUsedId = max(unsigned(item.data()), m_lastUsedId); m_lastUsedId = std::max(unsigned(item.data()), m_lastUsedId);
} }
} }
@ -111,7 +110,7 @@ void ControlFlowGraph::splitBlocks()
void ControlFlowGraph::resolveNextLinks() void ControlFlowGraph::resolveNextLinks()
{ {
map<unsigned, BlockId> blockByBeginPos; std::map<unsigned, BlockId> blockByBeginPos;
for (auto const& idAndBlock: m_blocks) for (auto const& idAndBlock: m_blocks)
if (idAndBlock.second.begin != idAndBlock.second.end) if (idAndBlock.second.begin != idAndBlock.second.end)
blockByBeginPos[idAndBlock.second.begin] = idAndBlock.first; blockByBeginPos[idAndBlock.second.begin] = idAndBlock.first;
@ -138,8 +137,8 @@ void ControlFlowGraph::resolveNextLinks()
void ControlFlowGraph::removeUnusedBlocks() void ControlFlowGraph::removeUnusedBlocks()
{ {
vector<BlockId> blocksToProcess{BlockId::initial()}; std::vector<BlockId> blocksToProcess{BlockId::initial()};
set<BlockId> neededBlocks{BlockId::initial()}; std::set<BlockId> neededBlocks{BlockId::initial()};
while (!blocksToProcess.empty()) while (!blocksToProcess.empty())
{ {
BasicBlock const& block = m_blocks.at(blocksToProcess.back()); BasicBlock const& block = m_blocks.at(blocksToProcess.back());
@ -219,16 +218,16 @@ void ControlFlowGraph::gatherKnowledge()
{ {
// @todo actually we know that memory is filled with zeros at the beginning, // @todo actually we know that memory is filled with zeros at the beginning,
// we could make use of that. // we could make use of that.
KnownStatePointer emptyState = make_shared<KnownState>(); KnownStatePointer emptyState = std::make_shared<KnownState>();
bool unknownJumpEncountered = false; bool unknownJumpEncountered = false;
struct WorkQueueItem { struct WorkQueueItem {
BlockId blockId; BlockId blockId;
KnownStatePointer state; KnownStatePointer state;
set<BlockId> blocksSeen; std::set<BlockId> blocksSeen;
}; };
vector<WorkQueueItem> workQueue{WorkQueueItem{BlockId::initial(), emptyState->copy(), set<BlockId>()}}; std::vector<WorkQueueItem> workQueue{WorkQueueItem{BlockId::initial(), emptyState->copy(), std::set<BlockId>()}};
auto addWorkQueueItem = [&](WorkQueueItem const& _currentItem, BlockId _to, KnownStatePointer const& _state) auto addWorkQueueItem = [&](WorkQueueItem const& _currentItem, BlockId _to, KnownStatePointer const& _state)
{ {
WorkQueueItem item; WorkQueueItem item;
@ -275,7 +274,7 @@ void ControlFlowGraph::gatherKnowledge()
assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, ""); assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, "");
//@todo in the case of JUMPI, add knowledge about the condition to the state //@todo in the case of JUMPI, add knowledge about the condition to the state
// (for both values of the condition) // (for both values of the condition)
set<u256> tags = state->tagsInExpression( std::set<u256> tags = state->tagsInExpression(
state->stackElement(state->stackHeight(), langutil::SourceLocation{}) state->stackElement(state->stackHeight(), langutil::SourceLocation{})
); );
state->feedItem(m_items.at(pc++)); state->feedItem(m_items.at(pc++));
@ -289,7 +288,7 @@ void ControlFlowGraph::gatherKnowledge()
unknownJumpEncountered = true; unknownJumpEncountered = true;
for (auto const& it: m_blocks) for (auto const& it: m_blocks)
if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag) if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag)
workQueue.push_back(WorkQueueItem{it.first, emptyState->copy(), set<BlockId>()}); workQueue.push_back(WorkQueueItem{it.first, emptyState->copy(), std::set<BlockId>()});
} }
} }
else else
@ -321,16 +320,16 @@ void ControlFlowGraph::gatherKnowledge()
BasicBlocks ControlFlowGraph::rebuildCode() BasicBlocks ControlFlowGraph::rebuildCode()
{ {
map<BlockId, unsigned> pushes; std::map<BlockId, unsigned> pushes;
for (auto& idAndBlock: m_blocks) for (auto& idAndBlock: m_blocks)
for (BlockId ref: idAndBlock.second.pushedTags) for (BlockId ref: idAndBlock.second.pushedTags)
if (m_blocks.count(ref)) if (m_blocks.count(ref))
pushes[ref]++; pushes[ref]++;
set<BlockId> blocksToAdd; std::set<BlockId> blocksToAdd;
for (auto it: m_blocks) for (auto it: m_blocks)
blocksToAdd.insert(it.first); blocksToAdd.insert(it.first);
set<BlockId> blocksAdded; std::set<BlockId> blocksAdded;
BasicBlocks blocks; BasicBlocks blocks;
for ( for (

View File

@ -22,7 +22,6 @@
#include <libsolutil/CommonIO.h> #include <libsolutil/CommonIO.h>
#include <functional> #include <functional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -31,7 +30,7 @@ using namespace solidity::evmasm;
void solidity::evmasm::eachInstruction( void solidity::evmasm::eachInstruction(
bytes const& _mem, bytes const& _mem,
langutil::EVMVersion _evmVersion, langutil::EVMVersion _evmVersion,
function<void(Instruction,u256 const&)> const& _onInstruction std::function<void(Instruction,u256 const&)> const& _onInstruction
) )
{ {
for (auto it = _mem.begin(); it < _mem.end(); ++it) for (auto it = _mem.begin(); it < _mem.end(); ++it)
@ -58,9 +57,9 @@ void solidity::evmasm::eachInstruction(
} }
} }
string solidity::evmasm::disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, string const& _delimiter) std::string solidity::evmasm::disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, std::string const& _delimiter)
{ {
stringstream ret; std::stringstream ret;
eachInstruction(_mem, _evmVersion, [&](Instruction _instr, u256 const& _data) { eachInstruction(_mem, _evmVersion, [&](Instruction _instr, u256 const& _data) {
if (!isValidInstruction(_instr)) if (!isValidInstruction(_instr))
ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter; ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter;

View File

@ -34,7 +34,6 @@
#include <limits> #include <limits>
#include <tuple> #include <tuple>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -58,10 +57,10 @@ bool ExpressionClasses::Expression::operator==(ExpressionClasses::Expression con
std::tie(_other.item->data(), _other.arguments, _other.sequenceNumber); std::tie(_other.item->data(), _other.arguments, _other.sequenceNumber);
} }
std::size_t ExpressionClasses::Expression::ExpressionHash::operator()(Expression const& _expression) const size_t ExpressionClasses::Expression::ExpressionHash::operator()(Expression const& _expression) const
{ {
assertThrow(!!_expression.item, OptimizerException, ""); assertThrow(!!_expression.item, OptimizerException, "");
std::size_t seed = 0; size_t seed = 0;
auto type = _expression.item->type(); auto type = _expression.item->type();
boost::hash_combine(seed, type); boost::hash_combine(seed, type);
@ -171,7 +170,7 @@ bool ExpressionClasses::knownNonZero(Id _c)
u256 const* ExpressionClasses::knownConstant(Id _c) u256 const* ExpressionClasses::knownConstant(Id _c)
{ {
map<unsigned, Expression const*> matchGroups; std::map<unsigned, Expression const*> matchGroups;
Pattern constant(Push); Pattern constant(Push);
constant.setMatchGroup(1, matchGroups); constant.setMatchGroup(1, matchGroups);
if (!constant.matches(representative(_c), *this)) if (!constant.matches(representative(_c), *this))
@ -181,15 +180,15 @@ u256 const* ExpressionClasses::knownConstant(Id _c)
AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item) AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item)
{ {
m_spareAssemblyItems.push_back(make_shared<AssemblyItem>(_item)); m_spareAssemblyItems.push_back(std::make_shared<AssemblyItem>(_item));
return m_spareAssemblyItems.back().get(); return m_spareAssemblyItems.back().get();
} }
string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const std::string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
{ {
Expression const& expr = representative(_id); Expression const& expr = representative(_id);
stringstream str; std::stringstream str;
str << dec << expr.id << ":"; str << std::dec << expr.id << ":";
if (expr.item) if (expr.item)
{ {
str << *expr.item << "("; str << *expr.item << "(";
@ -212,25 +211,25 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr)
_expr.item->type() != Operation || _expr.item->type() != Operation ||
!SemanticInformation::isDeterministic(*_expr.item) !SemanticInformation::isDeterministic(*_expr.item)
) )
return numeric_limits<unsigned>::max(); return std::numeric_limits<unsigned>::max();
if (auto match = rules.findFirstMatch(_expr, *this)) if (auto match = rules.findFirstMatch(_expr, *this))
{ {
// Debug info // Debug info
if (false) if (false)
{ {
cout << "Simplifying " << *_expr.item << "("; std::cout << "Simplifying " << *_expr.item << "(";
for (Id arg: _expr.arguments) for (Id arg: _expr.arguments)
cout << fullDAGToString(arg) << ", "; std::cout << fullDAGToString(arg) << ", ";
cout << ")" << endl; std::cout << ")" << std::endl;
cout << "with rule " << match->pattern.toString() << endl; std::cout << "with rule " << match->pattern.toString() << std::endl;
cout << "to " << match->action().toString() << endl; std::cout << "to " << match->action().toString() << std::endl;
} }
return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location())); return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location()));
} }
return numeric_limits<unsigned>::max(); return std::numeric_limits<unsigned>::max();
} }
ExpressionClasses::Id ExpressionClasses::rebuildExpression(ExpressionTemplate const& _template) ExpressionClasses::Id ExpressionClasses::rebuildExpression(ExpressionTemplate const& _template)

View File

@ -20,7 +20,6 @@
#include <libevmasm/KnownState.h> #include <libevmasm/KnownState.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -32,7 +31,7 @@ GasMeter::GasConsumption& GasMeter::GasConsumption::operator+=(GasConsumption co
if (isInfinite) if (isInfinite)
return *this; return *this;
bigint v = bigint(value) + _other.value; bigint v = bigint(value) + _other.value;
if (v > numeric_limits<u256>::max()) if (v > std::numeric_limits<u256>::max())
*this = infinite(); *this = infinite();
else else
value = u256(v); value = u256(v);

View File

@ -38,7 +38,6 @@
#include <optional> #include <optional>
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -54,7 +53,7 @@ u256 executionCost(RangeType const& _itemRange, langutil::EVMVersion _evmVersion
[&gasMeter](auto const& _item) { return gasMeter.estimateMax(_item, false); } [&gasMeter](auto const& _item) { return gasMeter.estimateMax(_item, false); }
), GasMeter::GasConsumption()); ), GasMeter::GasConsumption());
if (gasConsumption.isInfinite) if (gasConsumption.isInfinite)
return numeric_limits<u256>::max(); return std::numeric_limits<u256>::max();
else else
return gasConsumption.value; return gasConsumption.value;
} }
@ -66,14 +65,14 @@ uint64_t codeSize(RangeType const& _itemRange)
[](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); } [](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); }
), 0u); ), 0u);
} }
/// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, nullopt otherwise. /// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, std::nullopt otherwise.
optional<size_t> getLocalTag(AssemblyItem const& _item) std::optional<size_t> getLocalTag(AssemblyItem const& _item)
{ {
if (_item.type() != PushTag && _item.type() != Tag) if (_item.type() != PushTag && _item.type() != Tag)
return nullopt; return std::nullopt;
auto [subId, tag] = _item.splitForeignPushTag(); auto [subId, tag] = _item.splitForeignPushTag();
if (subId != numeric_limits<size_t>::max()) if (subId != std::numeric_limits<size_t>::max())
return nullopt; return std::nullopt;
return tag; return tag;
} }
} }
@ -99,7 +98,7 @@ bool Inliner::isInlineCandidate(size_t _tag, ranges::span<AssemblyItem const> _i
return true; return true;
} }
map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyItems const& _items) const std::map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyItems const& _items) const
{ {
std::map<size_t, ranges::span<AssemblyItem const>> inlinableBlockItems; std::map<size_t, ranges::span<AssemblyItem const>> inlinableBlockItems;
std::map<size_t, uint64_t> numPushTags; std::map<size_t, uint64_t> numPushTags;
@ -108,7 +107,7 @@ map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyI
{ {
// The number of PushTags approximates the number of calls to a block. // The number of PushTags approximates the number of calls to a block.
if (item.type() == PushTag) if (item.type() == PushTag)
if (optional<size_t> tag = getLocalTag(item)) if (std::optional<size_t> tag = getLocalTag(item))
++numPushTags[*tag]; ++numPushTags[*tag];
// We can only inline blocks with straight control flow that end in a jump. // We can only inline blocks with straight control flow that end in a jump.
@ -116,7 +115,7 @@ map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyI
if (lastTag && SemanticInformation::breaksCSEAnalysisBlock(item, false)) if (lastTag && SemanticInformation::breaksCSEAnalysisBlock(item, false))
{ {
ranges::span<AssemblyItem const> block = _items | ranges::views::slice(*lastTag + 1, index + 1); ranges::span<AssemblyItem const> block = _items | ranges::views::slice(*lastTag + 1, index + 1);
if (optional<size_t> tag = getLocalTag(_items[*lastTag])) if (std::optional<size_t> tag = getLocalTag(_items[*lastTag]))
if (isInlineCandidate(*tag, block)) if (isInlineCandidate(*tag, block))
inlinableBlockItems[*tag] = block; inlinableBlockItems[*tag] = block;
lastTag.reset(); lastTag.reset();
@ -130,7 +129,7 @@ map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyI
} }
// Store the number of PushTags alongside the assembly items and discard tags that are never pushed. // Store the number of PushTags alongside the assembly items and discard tags that are never pushed.
map<size_t, InlinableBlock> result; std::map<size_t, InlinableBlock> result;
for (auto&& [tag, items]: inlinableBlockItems) for (auto&& [tag, items]: inlinableBlockItems)
if (uint64_t const* numPushes = util::valueOrNullptr(numPushTags, tag)) if (uint64_t const* numPushes = util::valueOrNullptr(numPushTags, tag))
result.emplace(tag, InlinableBlock{items, *numPushes}); result.emplace(tag, InlinableBlock{items, *numPushes});
@ -199,7 +198,7 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span<AssemblyIte
return false; return false;
} }
optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _jump, InlinableBlock const& _block) const std::optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _jump, InlinableBlock const& _block) const
{ {
assertThrow(_jump == Instruction::JUMP, OptimizerException, ""); assertThrow(_jump == Instruction::JUMP, OptimizerException, "");
AssemblyItem blockExit = _block.items.back(); AssemblyItem blockExit = _block.items.back();
@ -232,7 +231,7 @@ optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _j
return blockExit; return blockExit;
} }
return nullopt; return std::nullopt;
} }
@ -252,7 +251,7 @@ void Inliner::optimise()
AssemblyItem const& nextItem = *next(it); AssemblyItem const& nextItem = *next(it);
if (item.type() == PushTag && nextItem == Instruction::JUMP) if (item.type() == PushTag && nextItem == Instruction::JUMP)
{ {
if (optional<size_t> tag = getLocalTag(item)) if (std::optional<size_t> tag = getLocalTag(item))
if (auto* inlinableBlock = util::valueOrNullptr(inlinableBlocks, *tag)) if (auto* inlinableBlock = util::valueOrNullptr(inlinableBlocks, *tag))
if (auto exitItem = shouldInline(*tag, nextItem, *inlinableBlock)) if (auto exitItem = shouldInline(*tag, nextItem, *inlinableBlock))
{ {
@ -264,7 +263,7 @@ void Inliner::optimise()
// We might increase the number of push tags to other blocks. // We might increase the number of push tags to other blocks.
for (AssemblyItem const& inlinedItem: inlinableBlock->items) for (AssemblyItem const& inlinedItem: inlinableBlock->items)
if (inlinedItem.type() == PushTag) if (inlinedItem.type() == PushTag)
if (optional<size_t> duplicatedTag = getLocalTag(inlinedItem)) if (std::optional<size_t> duplicatedTag = getLocalTag(inlinedItem))
if (auto* block = util::valueOrNullptr(inlinableBlocks, *duplicatedTag)) if (auto* block = util::valueOrNullptr(inlinableBlocks, *duplicatedTag))
++block->pushTagCount; ++block->pushTagCount;

View File

@ -22,7 +22,6 @@
#include <libevmasm/Instruction.h> #include <libevmasm/Instruction.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -335,7 +334,7 @@ InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst, langutil::E
} }
catch (...) catch (...)
{ {
return InstructionInfo({"<INVALID_INSTRUCTION: " + to_string(static_cast<unsigned>(_inst)) + ">", 0, 0, 0, false, Tier::Invalid}); return InstructionInfo({"<INVALID_INSTRUCTION: " + std::to_string(static_cast<unsigned>(_inst)) + ">", 0, 0, 0, false, Tier::Invalid});
} }
} }

View File

@ -26,14 +26,13 @@
#include <limits> #include <limits>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside) bool JumpdestRemover::optimise(std::set<size_t> const& _tagsReferencedFromOutside)
{ {
set<size_t> references{referencedTags(m_items, numeric_limits<size_t>::max())}; std::set<size_t> references{referencedTags(m_items, std::numeric_limits<size_t>::max())};
references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end());
size_t initialSize = m_items.size(); size_t initialSize = m_items.size();
@ -46,7 +45,7 @@ bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
if (_item.type() != Tag) if (_item.type() != Tag)
return false; return false;
auto asmIdAndTag = _item.splitForeignPushTag(); auto asmIdAndTag = _item.splitForeignPushTag();
assertThrow(asmIdAndTag.first == numeric_limits<size_t>::max(), OptimizerException, "Sub-assembly tag used as label."); assertThrow(asmIdAndTag.first == std::numeric_limits<size_t>::max(), OptimizerException, "Sub-assembly tag used as label.");
size_t tag = asmIdAndTag.second; size_t tag = asmIdAndTag.second;
return !references.count(tag); return !references.count(tag);
} }
@ -55,9 +54,9 @@ bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
return m_items.size() != initialSize; return m_items.size() != initialSize;
} }
set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId) std::set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId)
{ {
set<size_t> ret; std::set<size_t> ret;
for (auto const& item: _items) for (auto const& item: _items)
if (item.type() == PushTag) if (item.type() == PushTag)
{ {

View File

@ -28,17 +28,16 @@
#include <functional> #include <functional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
ostream& KnownState::stream(ostream& _out) const std::ostream& KnownState::stream(std::ostream& _out) const
{ {
auto streamExpressionClass = [this](ostream& _out, Id _id) auto streamExpressionClass = [this](std::ostream& _out, Id _id)
{ {
auto const& expr = m_expressionClasses->representative(_id); auto const& expr = m_expressionClasses->representative(_id);
_out << " " << dec << _id << ": "; _out << " " << std::dec << _id << ": ";
if (!expr.item) if (!expr.item)
_out << " no item"; _out << " no item";
else if (expr.item->type() == UndefinedItem) else if (expr.item->type() == UndefinedItem)
@ -46,26 +45,26 @@ ostream& KnownState::stream(ostream& _out) const
else else
_out << *expr.item; _out << *expr.item;
if (expr.sequenceNumber) if (expr.sequenceNumber)
_out << "@" << dec << expr.sequenceNumber; _out << "@" << std::dec << expr.sequenceNumber;
_out << "("; _out << "(";
for (Id arg: expr.arguments) for (Id arg: expr.arguments)
_out << dec << arg << ","; _out << std::dec << arg << ",";
_out << ")" << endl; _out << ")" << std::endl;
}; };
_out << "=== State ===" << endl; _out << "=== State ===" << std::endl;
_out << "Stack height: " << dec << m_stackHeight << endl; _out << "Stack height: " << std::dec << m_stackHeight << std::endl;
_out << "Equivalence classes:" << endl; _out << "Equivalence classes:" << std::endl;
for (Id eqClass = 0; eqClass < m_expressionClasses->size(); ++eqClass) for (Id eqClass = 0; eqClass < m_expressionClasses->size(); ++eqClass)
streamExpressionClass(_out, eqClass); streamExpressionClass(_out, eqClass);
_out << "Stack:" << endl; _out << "Stack:" << std::endl;
for (auto const& it: m_stackElements) for (auto const& it: m_stackElements)
{ {
_out << " " << dec << it.first << ": "; _out << " " << std::dec << it.first << ": ";
streamExpressionClass(_out, it.second); streamExpressionClass(_out, it.second);
} }
_out << "Storage:" << endl; _out << "Storage:" << std::endl;
for (auto const& it: m_storageContent) for (auto const& it: m_storageContent)
{ {
_out << " "; _out << " ";
@ -73,7 +72,7 @@ ostream& KnownState::stream(ostream& _out) const
_out << ": "; _out << ": ";
streamExpressionClass(_out, it.second); streamExpressionClass(_out, it.second);
} }
_out << "Memory:" << endl; _out << "Memory:" << std::endl;
for (auto const& it: m_memoryContent) for (auto const& it: m_memoryContent)
{ {
_out << " "; _out << " ";
@ -149,7 +148,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
); );
else if (instruction != Instruction::POP) else if (instruction != Instruction::POP)
{ {
vector<Id> arguments(static_cast<size_t>(info.args)); std::vector<Id> arguments(static_cast<size_t>(info.args));
for (size_t i = 0; i < static_cast<size_t>(info.args); ++i) for (size_t i = 0; i < static_cast<size_t>(info.args); ++i)
arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location()); arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location());
switch (_item.instruction()) switch (_item.instruction())
@ -233,8 +232,8 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other, bool _combine
++it; ++it;
else else
{ {
set<u256> theseTags = tagsInExpression(it->second); std::set<u256> theseTags = tagsInExpression(it->second);
set<u256> otherTags = tagsInExpression(other); std::set<u256> otherTags = tagsInExpression(other);
if (!theseTags.empty() && !otherTags.empty()) if (!theseTags.empty() && !otherTags.empty())
{ {
theseTags.insert(otherTags.begin(), otherTags.end()); theseTags.insert(otherTags.begin(), otherTags.end());
@ -251,7 +250,7 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other, bool _combine
// Use the smaller stack height. Essential to terminate in case of loops. // Use the smaller stack height. Essential to terminate in case of loops.
if (m_stackHeight > _other.m_stackHeight) if (m_stackHeight > _other.m_stackHeight)
{ {
map<int, Id> shiftedStack; std::map<int, Id> shiftedStack;
for (auto const& stackElement: m_stackElements) for (auto const& stackElement: m_stackElements)
shiftedStack[stackElement.first - stackDiff] = stackElement.second; shiftedStack[stackElement.first - stackDiff] = stackElement.second;
m_stackElements = std::move(shiftedStack); m_stackElements = std::move(shiftedStack);
@ -261,7 +260,7 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other, bool _combine
intersect(m_storageContent, _other.m_storageContent); intersect(m_storageContent, _other.m_storageContent);
intersect(m_memoryContent, _other.m_memoryContent); intersect(m_memoryContent, _other.m_memoryContent);
if (_combineSequenceNumbers) if (_combineSequenceNumbers)
m_sequenceNumber = max(m_sequenceNumber, _other.m_sequenceNumber); m_sequenceNumber = std::max(m_sequenceNumber, _other.m_sequenceNumber);
} }
bool KnownState::operator==(KnownState const& _other) const bool KnownState::operator==(KnownState const& _other) const
@ -316,7 +315,7 @@ void KnownState::swapStackElements(
stackElement(_stackHeightA, _location); stackElement(_stackHeightA, _location);
stackElement(_stackHeightB, _location); stackElement(_stackHeightB, _location);
swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); std::swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]);
} }
KnownState::StoreOperation KnownState::storeInStorage( KnownState::StoreOperation KnownState::storeInStorage(
@ -400,7 +399,7 @@ KnownState::Id KnownState::applyKeccak256(
if (!l || *l > 128) if (!l || *l > 128)
return m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber); return m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber);
unsigned length = unsigned(*l); unsigned length = unsigned(*l);
vector<Id> arguments; std::vector<Id> arguments;
for (unsigned i = 0; i < length; i += 32) for (unsigned i = 0; i < length; i += 32)
{ {
Id slot = m_expressionClasses->find( Id slot = m_expressionClasses->find(
@ -426,19 +425,19 @@ KnownState::Id KnownState::applyKeccak256(
return m_knownKeccak256Hashes[{arguments, length}] = v; return m_knownKeccak256Hashes[{arguments, length}] = v;
} }
set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId) std::set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId)
{ {
if (m_tagUnions.left.count(_expressionId)) if (m_tagUnions.left.count(_expressionId))
return m_tagUnions.left.at(_expressionId); return m_tagUnions.left.at(_expressionId);
// Might be a tag, then return the set of itself. // Might be a tag, then return the set of itself.
ExpressionClasses::Expression expr = m_expressionClasses->representative(_expressionId); ExpressionClasses::Expression expr = m_expressionClasses->representative(_expressionId);
if (expr.item && expr.item->type() == PushTag) if (expr.item && expr.item->type() == PushTag)
return set<u256>({expr.item->data()}); return std::set<u256>({expr.item->data()});
else else
return set<u256>(); return std::set<u256>();
} }
KnownState::Id KnownState::tagUnion(set<u256> _tags) KnownState::Id KnownState::tagUnion(std::set<u256> _tags)
{ {
if (m_tagUnions.right.count(_tags)) if (m_tagUnions.right.count(_tags))
return m_tagUnions.right.at(_tags); return m_tagUnions.right.at(_tags);

View File

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

View File

@ -24,7 +24,6 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/Keccak256.h> #include <libsolutil/Keccak256.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -36,24 +35,24 @@ void LinkerObject::append(LinkerObject const& _other)
bytecode += _other.bytecode; bytecode += _other.bytecode;
} }
void LinkerObject::link(map<string, h160> const& _libraryAddresses) void LinkerObject::link(std::map<std::string, h160> const& _libraryAddresses)
{ {
std::map<size_t, std::string> remainingRefs; std::map<size_t, std::string> remainingRefs;
for (auto const& linkRef: linkReferences) for (auto const& linkRef: linkReferences)
if (h160 const* address = matchLibrary(linkRef.second, _libraryAddresses)) if (h160 const* address = matchLibrary(linkRef.second, _libraryAddresses))
copy(address->data(), address->data() + 20, bytecode.begin() + vector<uint8_t>::difference_type(linkRef.first)); copy(address->data(), address->data() + 20, bytecode.begin() + std::vector<uint8_t>::difference_type(linkRef.first));
else else
remainingRefs.insert(linkRef); remainingRefs.insert(linkRef);
linkReferences.swap(remainingRefs); linkReferences.swap(remainingRefs);
} }
string LinkerObject::toHex() const std::string LinkerObject::toHex() const
{ {
string hex = solidity::util::toHex(bytecode); std::string hex = solidity::util::toHex(bytecode);
for (auto const& ref: linkReferences) for (auto const& ref: linkReferences)
{ {
size_t pos = ref.first * 2; size_t pos = ref.first * 2;
string hash = libraryPlaceholder(ref.second); std::string hash = libraryPlaceholder(ref.second);
hex[pos] = hex[pos + 1] = hex[pos + 38] = hex[pos + 39] = '_'; hex[pos] = hex[pos + 1] = hex[pos + 38] = hex[pos + 39] = '_';
for (size_t i = 0; i < 36; ++i) for (size_t i = 0; i < 36; ++i)
hex[pos + 2 + i] = hash.at(i); hex[pos + 2 + i] = hash.at(i);
@ -61,15 +60,15 @@ string LinkerObject::toHex() const
return hex; return hex;
} }
string LinkerObject::libraryPlaceholder(string const& _libraryName) std::string LinkerObject::libraryPlaceholder(std::string const& _libraryName)
{ {
return "$" + keccak256(_libraryName).hex().substr(0, 34) + "$"; return "$" + keccak256(_libraryName).hex().substr(0, 34) + "$";
} }
h160 const* h160 const*
LinkerObject::matchLibrary( LinkerObject::matchLibrary(
string const& _linkRefName, std::string const& _linkRefName,
map<string, h160> const& _libraryAddresses std::map<std::string, h160> const& _libraryAddresses
) )
{ {
auto it = _libraryAddresses.find(_linkRefName); auto it = _libraryAddresses.find(_linkRefName);

View File

@ -24,7 +24,6 @@
#include <libevmasm/KnownState.h> #include <libevmasm/KnownState.h>
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -38,17 +37,17 @@ PathGasMeter::PathGasMeter(AssemblyItems const& _items, langutil::EVMVersion _ev
GasMeter::GasConsumption PathGasMeter::estimateMax( GasMeter::GasConsumption PathGasMeter::estimateMax(
size_t _startIndex, size_t _startIndex,
shared_ptr<KnownState> const& _state std::shared_ptr<KnownState> const& _state
) )
{ {
auto path = make_unique<GasPath>(); auto path = std::make_unique<GasPath>();
path->index = _startIndex; path->index = _startIndex;
path->state = _state->copy(); path->state = _state->copy();
queue(std::move(path)); queue(std::move(path));
GasMeter::GasConsumption gas; GasMeter::GasConsumption gas;
while (!m_queue.empty() && !gas.isInfinite) while (!m_queue.empty() && !gas.isInfinite)
gas = max(gas, handleQueueItem()); gas = std::max(gas, handleQueueItem());
return gas; return gas;
} }
@ -67,10 +66,10 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
{ {
assertThrow(!m_queue.empty(), OptimizerException, ""); assertThrow(!m_queue.empty(), OptimizerException, "");
unique_ptr<GasPath> path = std::move(m_queue.rbegin()->second); std::unique_ptr<GasPath> path = std::move(m_queue.rbegin()->second);
m_queue.erase(--m_queue.end()); m_queue.erase(--m_queue.end());
shared_ptr<KnownState> state = path->state; std::shared_ptr<KnownState> state = path->state;
GasMeter meter(state, m_evmVersion, path->largestMemoryAccess); GasMeter meter(state, m_evmVersion, path->largestMemoryAccess);
ExpressionClasses& classes = state->expressionClasses(); ExpressionClasses& classes = state->expressionClasses();
GasMeter::GasConsumption gas = path->gas; GasMeter::GasConsumption gas = path->gas;
@ -82,7 +81,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
// return the current gas value. // return the current gas value.
return gas; return gas;
set<u256> jumpTags; std::set<u256> jumpTags;
for (; index < m_items.size() && !gas.isInfinite; ++index) for (; index < m_items.size() && !gas.isInfinite; ++index)
{ {
bool branchStops = false; bool branchStops = false;
@ -121,7 +120,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
for (u256 const& tag: jumpTags) for (u256 const& tag: jumpTags)
{ {
auto newPath = make_unique<GasPath>(); auto newPath = std::make_unique<GasPath>();
newPath->index = m_items.size(); newPath->index = m_items.size();
if (m_tagPositions.count(tag)) if (m_tagPositions.count(tag))
newPath->index = m_tagPositions.at(tag); newPath->index = m_tagPositions.at(tag);

View File

@ -25,7 +25,6 @@
#include <libevmasm/AssemblyItem.h> #include <libevmasm/AssemblyItem.h>
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
@ -38,7 +37,7 @@ struct OptimiserState
{ {
AssemblyItems const& items; AssemblyItems const& items;
size_t i; size_t i;
back_insert_iterator<AssemblyItems> out; std::back_insert_iterator<AssemblyItems> out;
}; };
template<typename FunctionType> template<typename FunctionType>
@ -55,8 +54,8 @@ struct SimplePeepholeOptimizerMethod
template <size_t... Indices> template <size_t... Indices>
static bool applyRule( static bool applyRule(
AssemblyItems::const_iterator _in, AssemblyItems::const_iterator _in,
back_insert_iterator<AssemblyItems> _out, std::back_insert_iterator<AssemblyItems> _out,
index_sequence<Indices...> std::index_sequence<Indices...>
) )
{ {
return Method::applySimple(_in[Indices]..., _out); return Method::applySimple(_in[Indices]..., _out);
@ -66,7 +65,7 @@ struct SimplePeepholeOptimizerMethod
static constexpr size_t WindowSize = FunctionParameterCount<decltype(Method::applySimple)>::value - 1; static constexpr size_t WindowSize = FunctionParameterCount<decltype(Method::applySimple)>::value - 1;
if ( if (
_state.i + WindowSize <= _state.items.size() && _state.i + WindowSize <= _state.items.size() &&
applyRule(_state.items.begin() + static_cast<ptrdiff_t>(_state.i), _state.out, make_index_sequence<WindowSize>{}) applyRule(_state.items.begin() + static_cast<ptrdiff_t>(_state.i), _state.out, std::make_index_sequence<WindowSize>{})
) )
{ {
_state.i += WindowSize; _state.i += WindowSize;
@ -81,7 +80,7 @@ struct Identity: SimplePeepholeOptimizerMethod<Identity>
{ {
static bool applySimple( static bool applySimple(
AssemblyItem const& _item, AssemblyItem const& _item,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
*_out = _item; *_out = _item;
@ -94,7 +93,7 @@ struct PushPop: SimplePeepholeOptimizerMethod<PushPop>
static bool applySimple( static bool applySimple(
AssemblyItem const& _push, AssemblyItem const& _push,
AssemblyItem const& _pop, AssemblyItem const& _pop,
back_insert_iterator<AssemblyItems> std::back_insert_iterator<AssemblyItems>
) )
{ {
auto t = _push.type(); auto t = _push.type();
@ -111,7 +110,7 @@ struct OpPop: SimplePeepholeOptimizerMethod<OpPop>
static bool applySimple( static bool applySimple(
AssemblyItem const& _op, AssemblyItem const& _op,
AssemblyItem const& _pop, AssemblyItem const& _pop,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if (_pop == Instruction::POP && _op.type() == Operation) if (_pop == Instruction::POP && _op.type() == Operation)
@ -133,7 +132,7 @@ struct OpStop: SimplePeepholeOptimizerMethod<OpStop>
static bool applySimple( static bool applySimple(
AssemblyItem const& _op, AssemblyItem const& _op,
AssemblyItem const& _stop, AssemblyItem const& _stop,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if (_stop == Instruction::STOP) if (_stop == Instruction::STOP)
@ -164,7 +163,7 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod<OpReturnRevert>
AssemblyItem const& _push, AssemblyItem const& _push,
AssemblyItem const& _pushOrDup, AssemblyItem const& _pushOrDup,
AssemblyItem const& _returnRevert, AssemblyItem const& _returnRevert,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if ( if (
@ -191,7 +190,7 @@ struct DoubleSwap: SimplePeepholeOptimizerMethod<DoubleSwap>
static size_t applySimple( static size_t applySimple(
AssemblyItem const& _s1, AssemblyItem const& _s1,
AssemblyItem const& _s2, AssemblyItem const& _s2,
back_insert_iterator<AssemblyItems> std::back_insert_iterator<AssemblyItems>
) )
{ {
return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1); return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1);
@ -203,7 +202,7 @@ struct DoublePush: SimplePeepholeOptimizerMethod<DoublePush>
static bool applySimple( static bool applySimple(
AssemblyItem const& _push1, AssemblyItem const& _push1,
AssemblyItem const& _push2, AssemblyItem const& _push2,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data()) if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data())
@ -222,7 +221,7 @@ struct CommutativeSwap: SimplePeepholeOptimizerMethod<CommutativeSwap>
static bool applySimple( static bool applySimple(
AssemblyItem const& _swap, AssemblyItem const& _swap,
AssemblyItem const& _op, AssemblyItem const& _op,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
// Remove SWAP1 if following instruction is commutative // Remove SWAP1 if following instruction is commutative
@ -244,10 +243,10 @@ struct SwapComparison: SimplePeepholeOptimizerMethod<SwapComparison>
static bool applySimple( static bool applySimple(
AssemblyItem const& _swap, AssemblyItem const& _swap,
AssemblyItem const& _op, AssemblyItem const& _op,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
static map<Instruction, Instruction> const swappableOps{ static std::map<Instruction, Instruction> const swappableOps{
{ Instruction::LT, Instruction::GT }, { Instruction::LT, Instruction::GT },
{ Instruction::GT, Instruction::LT }, { Instruction::GT, Instruction::LT },
{ Instruction::SLT, Instruction::SGT }, { Instruction::SLT, Instruction::SGT },
@ -274,7 +273,7 @@ struct DupSwap: SimplePeepholeOptimizerMethod<DupSwap>
static size_t applySimple( static size_t applySimple(
AssemblyItem const& _dupN, AssemblyItem const& _dupN,
AssemblyItem const& _swapN, AssemblyItem const& _swapN,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if ( if (
@ -299,7 +298,7 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI>
AssemblyItem const& _iszero2, AssemblyItem const& _iszero2,
AssemblyItem const& _pushTag, AssemblyItem const& _pushTag,
AssemblyItem const& _jumpi, AssemblyItem const& _jumpi,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if ( if (
@ -325,7 +324,7 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
AssemblyItem const& _iszero, AssemblyItem const& _iszero,
AssemblyItem const& _pushTag, AssemblyItem const& _pushTag,
AssemblyItem const& _jumpi, AssemblyItem const& _jumpi,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if ( if (
@ -354,7 +353,7 @@ struct DoubleJump: SimplePeepholeOptimizerMethod<DoubleJump>
AssemblyItem const& _pushTag2, AssemblyItem const& _pushTag2,
AssemblyItem const& _jump, AssemblyItem const& _jump,
AssemblyItem const& _tag1, AssemblyItem const& _tag1,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if ( if (
@ -383,7 +382,7 @@ struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>
AssemblyItem const& _pushTag, AssemblyItem const& _pushTag,
AssemblyItem const& _jump, AssemblyItem const& _jump,
AssemblyItem const& _tag, AssemblyItem const& _tag,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if ( if (
@ -409,7 +408,7 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions>
AssemblyItem const& _pushTag, AssemblyItem const& _pushTag,
AssemblyItem const& _pushConstant, AssemblyItem const& _pushConstant,
AssemblyItem const& _and, AssemblyItem const& _and,
back_insert_iterator<AssemblyItems> _out std::back_insert_iterator<AssemblyItems> _out
) )
{ {
if (_and != Instruction::AND) if (_and != Instruction::AND)
@ -444,7 +443,7 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd>
AssemblyItem const& _push, AssemblyItem const& _push,
AssemblyItem const& _not, AssemblyItem const& _not,
AssemblyItem const& _and, AssemblyItem const& _and,
back_insert_iterator<AssemblyItems> std::back_insert_iterator<AssemblyItems>
) )
{ {
return ( return (

View File

@ -25,11 +25,10 @@
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
#include <libevmasm/AssemblyItem.h> #include <libevmasm/AssemblyItem.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(Instruction _instruction) std::vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(Instruction _instruction)
{ {
switch (_instruction) switch (_instruction)
{ {
@ -111,7 +110,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
case Instruction::DELEGATECALL: case Instruction::DELEGATECALL:
{ {
size_t paramCount = static_cast<size_t>(instructionInfo(_instruction, langutil::EVMVersion()).args); size_t paramCount = static_cast<size_t>(instructionInfo(_instruction, langutil::EVMVersion()).args);
vector<Operation> operations{ std::vector<Operation> operations{
Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}}, Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}},
Operation{Location::Storage, Effect::Read, {}, {}, {}} Operation{Location::Storage, Effect::Read, {}, {}, {}}
}; };
@ -130,7 +129,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
} }
case Instruction::CREATE: case Instruction::CREATE:
case Instruction::CREATE2: case Instruction::CREATE2:
return vector<Operation>{ return std::vector<Operation>{
Operation{ Operation{
Location::Memory, Location::Memory,
Effect::Read, Effect::Read,
@ -143,7 +142,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
}; };
case Instruction::MSIZE: case Instruction::MSIZE:
// This is just to satisfy the assert below. // This is just to satisfy the assert below.
return vector<Operation>{}; return std::vector<Operation>{};
default: default:
assertThrow(storage(_instruction) == None && memory(_instruction) == None, AssemblyException, ""); assertThrow(storage(_instruction) == None && memory(_instruction) == None, AssemblyException, "");
} }

View File

@ -32,7 +32,6 @@
#include <utility> #include <utility>
#include <functional> #include <functional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -92,7 +91,7 @@ Rules::Rules()
Y.setMatchGroup(6, m_matchGroups); Y.setMatchGroup(6, m_matchGroups);
Z.setMatchGroup(7, m_matchGroups); Z.setMatchGroup(7, m_matchGroups);
addRules(simplificationRuleList(nullopt, A, B, C, W, X, Y, Z)); addRules(simplificationRuleList(std::nullopt, A, B, C, W, X, Y, Z));
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
} }
@ -103,7 +102,7 @@ Pattern::Pattern(Instruction _instruction, std::initializer_list<Pattern> _argum
{ {
} }
void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _matchGroups) void Pattern::setMatchGroup(unsigned _group, std::map<unsigned, Expression const*>& _matchGroups)
{ {
m_matchGroup = _group; m_matchGroup = _group;
m_matchGroups = &_matchGroups; m_matchGroups = &_matchGroups;
@ -135,9 +134,9 @@ AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const
return AssemblyItem(m_type, data(), _location); return AssemblyItem(m_type, data(), _location);
} }
string Pattern::toString() const std::string Pattern::toString() const
{ {
stringstream s; std::stringstream s;
switch (m_type) switch (m_type)
{ {
case Operation: case Operation:
@ -146,7 +145,7 @@ string Pattern::toString() const
break; break;
case Push: case Push:
if (m_data) if (m_data)
s << "PUSH " << hex << data(); s << "PUSH " << std::hex << data();
else else
s << "PUSH "; s << "PUSH ";
break; break;
@ -155,15 +154,15 @@ string Pattern::toString() const
break; break;
default: default:
if (m_data) if (m_data)
s << "t=" << dec << m_type << " d=" << hex << data(); s << "t=" << std::dec << m_type << " d=" << std::hex << data();
else else
s << "t=" << dec << m_type << " d: nullptr"; s << "t=" << std::dec << m_type << " d: nullptr";
break; break;
} }
if (!m_requireDataMatch) if (!m_requireDataMatch)
s << " ~"; s << " ~";
if (m_matchGroup) if (m_matchGroup)
s << "[" << dec << m_matchGroup << "]"; s << "[" << std::dec << m_matchGroup << "]";
s << "("; s << "(";
for (Pattern const& p: m_arguments) for (Pattern const& p: m_arguments)
s << p.toString() << ", "; s << p.toString() << ", ";
@ -216,9 +215,9 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation c
arguments.emplace_back(arg, _location); arguments.emplace_back(arg, _location);
} }
string ExpressionTemplate::toString() const std::string ExpressionTemplate::toString() const
{ {
stringstream s; std::stringstream s;
if (hasId) if (hasId)
s << id; s << id;
else else

View File

@ -51,7 +51,6 @@
#include <liblangutil/CharStream.h> #include <liblangutil/CharStream.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -79,21 +78,21 @@ char CharStream::setPosition(size_t _location)
return get(); return get();
} }
string CharStream::lineAtPosition(int _position) const std::string CharStream::lineAtPosition(int _position) const
{ {
// if _position points to \n, it returns the line before the \n // if _position points to \n, it returns the line before the \n
using size_type = string::size_type; using size_type = std::string::size_type;
size_type searchStart = min<size_type>(m_source.size(), size_type(_position)); size_type searchStart = std::min<size_type>(m_source.size(), size_type(_position));
if (searchStart > 0) if (searchStart > 0)
searchStart--; searchStart--;
size_type lineStart = m_source.rfind('\n', searchStart); size_type lineStart = m_source.rfind('\n', searchStart);
if (lineStart == string::npos) if (lineStart == std::string::npos)
lineStart = 0; lineStart = 0;
else else
lineStart++; lineStart++;
string line = m_source.substr( std::string line = m_source.substr(
lineStart, lineStart,
min(m_source.find('\n', lineStart), m_source.size()) - lineStart std::min(m_source.find('\n', lineStart), m_source.size()) - lineStart
); );
if (!line.empty() && line.back() == '\r') if (!line.empty() && line.back() == '\r')
line.pop_back(); line.pop_back();
@ -102,9 +101,9 @@ string CharStream::lineAtPosition(int _position) const
LineColumn CharStream::translatePositionToLineColumn(int _position) const LineColumn CharStream::translatePositionToLineColumn(int _position) const
{ {
using size_type = string::size_type; using size_type = std::string::size_type;
using diff_type = string::difference_type; using diff_type = std::string::difference_type;
size_type searchPosition = min<size_type>(m_source.size(), size_type(_position)); size_type searchPosition = std::min<size_type>(m_source.size(), size_type(_position));
int lineNumber = static_cast<int>(count(m_source.begin(), m_source.begin() + diff_type(searchPosition), '\n')); int lineNumber = static_cast<int>(count(m_source.begin(), m_source.begin() + diff_type(searchPosition), '\n'));
size_type lineStart; size_type lineStart;
if (searchPosition == 0) if (searchPosition == 0)
@ -112,24 +111,24 @@ LineColumn CharStream::translatePositionToLineColumn(int _position) const
else else
{ {
lineStart = m_source.rfind('\n', searchPosition - 1); lineStart = m_source.rfind('\n', searchPosition - 1);
lineStart = lineStart == string::npos ? 0 : lineStart + 1; lineStart = lineStart == std::string::npos ? 0 : lineStart + 1;
} }
return LineColumn{lineNumber, static_cast<int>(searchPosition - lineStart)}; return LineColumn{lineNumber, static_cast<int>(searchPosition - lineStart)};
} }
string_view CharStream::text(SourceLocation const& _location) const std::string_view CharStream::text(SourceLocation const& _location) const
{ {
if (!_location.hasText()) if (!_location.hasText())
return {}; return {};
solAssert(_location.sourceName && *_location.sourceName == m_name, ""); solAssert(_location.sourceName && *_location.sourceName == m_name, "");
solAssert(static_cast<size_t>(_location.end) <= m_source.size(), ""); solAssert(static_cast<size_t>(_location.end) <= m_source.size(), "");
return string_view{m_source}.substr( return std::string_view{m_source}.substr(
static_cast<size_t>(_location.start), static_cast<size_t>(_location.start),
static_cast<size_t>(_location.end - _location.start) static_cast<size_t>(_location.end - _location.start)
); );
} }
string CharStream::singleLineSnippet(string const& _sourceCode, SourceLocation const& _location) std::string CharStream::singleLineSnippet(std::string const& _sourceCode, SourceLocation const& _location)
{ {
if (!_location.hasText()) if (!_location.hasText())
return {}; return {};
@ -137,39 +136,39 @@ string CharStream::singleLineSnippet(string const& _sourceCode, SourceLocation c
if (static_cast<size_t>(_location.start) >= _sourceCode.size()) if (static_cast<size_t>(_location.start) >= _sourceCode.size())
return {}; return {};
string cut = _sourceCode.substr(static_cast<size_t>(_location.start), static_cast<size_t>(_location.end - _location.start)); std::string cut = _sourceCode.substr(static_cast<size_t>(_location.start), static_cast<size_t>(_location.end - _location.start));
auto newLinePos = cut.find_first_of("\n\r"); auto newLinePos = cut.find_first_of("\n\r");
if (newLinePos != string::npos) if (newLinePos != std::string::npos)
cut = cut.substr(0, newLinePos) + "..."; cut = cut.substr(0, newLinePos) + "...";
return cut; return cut;
} }
optional<int> CharStream::translateLineColumnToPosition(LineColumn const& _lineColumn) const std::optional<int> CharStream::translateLineColumnToPosition(LineColumn const& _lineColumn) const
{ {
return translateLineColumnToPosition(m_source, _lineColumn); return translateLineColumnToPosition(m_source, _lineColumn);
} }
optional<int> CharStream::translateLineColumnToPosition(std::string const& _text, LineColumn const& _input) std::optional<int> CharStream::translateLineColumnToPosition(std::string const& _text, LineColumn const& _input)
{ {
if (_input.line < 0) if (_input.line < 0)
return nullopt; return std::nullopt;
size_t offset = 0; size_t offset = 0;
for (int i = 0; i < _input.line; i++) for (int i = 0; i < _input.line; i++)
{ {
offset = _text.find('\n', offset); offset = _text.find('\n', offset);
if (offset == _text.npos) if (offset == _text.npos)
return nullopt; return std::nullopt;
offset++; // Skip linefeed. offset++; // Skip linefeed.
} }
size_t endOfLine = _text.find('\n', offset); size_t endOfLine = _text.find('\n', offset);
if (endOfLine == string::npos) if (endOfLine == std::string::npos)
endOfLine = _text.size(); endOfLine = _text.size();
if (offset + static_cast<size_t>(_input.column) > endOfLine) if (offset + static_cast<size_t>(_input.column) > endOfLine)
return nullopt; return std::nullopt;
return offset + static_cast<size_t>(_input.column); return offset + static_cast<size_t>(_input.column);
} }

View File

@ -30,7 +30,6 @@
#include <vector> #include <vector>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::util; using namespace solidity::util;
@ -50,7 +49,7 @@ DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _me
return result; return result;
} }
optional<DebugInfoSelection> DebugInfoSelection::fromString(string_view _input) std::optional<DebugInfoSelection> DebugInfoSelection::fromString(std::string_view _input)
{ {
// TODO: Make more stuff constexpr and make it a static_assert(). // TODO: Make more stuff constexpr and make it a static_assert().
solAssert(componentMap().count("all") == 0, ""); solAssert(componentMap().count("all") == 0, "");
@ -61,11 +60,11 @@ optional<DebugInfoSelection> DebugInfoSelection::fromString(string_view _input)
if (_input == "none") if (_input == "none")
return None(); return None();
return fromComponents(_input | ranges::views::split(',') | ranges::to<vector<string>>); return fromComponents(_input | ranges::views::split(',') | ranges::to<std::vector<std::string>>);
} }
optional<DebugInfoSelection> DebugInfoSelection::fromComponents( std::optional<DebugInfoSelection> DebugInfoSelection::fromComponents(
vector<string> const& _componentNames, std::vector<std::string> const& _componentNames,
bool _acceptWildcards bool _acceptWildcards
) )
{ {
@ -75,16 +74,16 @@ optional<DebugInfoSelection> DebugInfoSelection::fromComponents(
for (auto const& component: _componentNames) for (auto const& component: _componentNames)
{ {
if (component == "*") if (component == "*")
return (_acceptWildcards ? make_optional(DebugInfoSelection::All()) : nullopt); return (_acceptWildcards ? std::make_optional(DebugInfoSelection::All()) : std::nullopt);
if (!selection.enable(component)) if (!selection.enable(component))
return nullopt; return std::nullopt;
} }
return selection; return selection;
} }
bool DebugInfoSelection::enable(string _component) bool DebugInfoSelection::enable(std::string _component)
{ {
auto memberIt = componentMap().find(boost::trim_copy(_component)); auto memberIt = componentMap().find(boost::trim_copy(_component));
if (memberIt == componentMap().end()) if (memberIt == componentMap().end())
@ -146,9 +145,9 @@ bool DebugInfoSelection::operator==(DebugInfoSelection const& _other) const noex
return true; return true;
} }
ostream& langutil::operator<<(ostream& _stream, DebugInfoSelection const& _selection) std::ostream& langutil::operator<<(std::ostream& _stream, DebugInfoSelection const& _selection)
{ {
vector<string> selectedComponentNames; std::vector<std::string> selectedComponentNames;
for (auto const& [name, member]: _selection.componentMap()) for (auto const& [name, member]: _selection.componentMap())
if (_selection.*member) if (_selection.*member)
selectedComponentNames.push_back(name); selectedComponentNames.push_back(name);

View File

@ -25,7 +25,6 @@
#include <liblangutil/SourceLocation.h> #include <liblangutil/SourceLocation.h>
#include <memory> #include <memory>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -37,7 +36,7 @@ ErrorReporter& ErrorReporter::operator=(ErrorReporter const& _errorReporter)
return *this; return *this;
} }
void ErrorReporter::warning(ErrorId _error, string const& _description) void ErrorReporter::warning(ErrorId _error, std::string const& _description)
{ {
error(_error, Error::Type::Warning, SourceLocation(), _description); error(_error, Error::Type::Warning, SourceLocation(), _description);
} }
@ -45,7 +44,7 @@ void ErrorReporter::warning(ErrorId _error, string const& _description)
void ErrorReporter::warning( void ErrorReporter::warning(
ErrorId _error, ErrorId _error,
SourceLocation const& _location, SourceLocation const& _location,
string const& _description std::string const& _description
) )
{ {
error(_error, Error::Type::Warning, _location, _description); error(_error, Error::Type::Warning, _location, _description);
@ -54,27 +53,27 @@ void ErrorReporter::warning(
void ErrorReporter::warning( void ErrorReporter::warning(
ErrorId _error, ErrorId _error,
SourceLocation const& _location, SourceLocation const& _location,
string const& _description, std::string const& _description,
SecondarySourceLocation const& _secondaryLocation SecondarySourceLocation const& _secondaryLocation
) )
{ {
error(_error, Error::Type::Warning, _location, _secondaryLocation, _description); error(_error, Error::Type::Warning, _location, _secondaryLocation, _description);
} }
void ErrorReporter::error(ErrorId _errorId, Error::Type _type, SourceLocation const& _location, string const& _description) void ErrorReporter::error(ErrorId _errorId, Error::Type _type, SourceLocation const& _location, std::string const& _description)
{ {
if (checkForExcessiveErrors(_type)) if (checkForExcessiveErrors(_type))
return; return;
m_errorList.push_back(make_shared<Error>(_errorId, _type, _description, _location)); m_errorList.push_back(std::make_shared<Error>(_errorId, _type, _description, _location));
} }
void ErrorReporter::error(ErrorId _errorId, Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description) void ErrorReporter::error(ErrorId _errorId, Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description)
{ {
if (checkForExcessiveErrors(_type)) if (checkForExcessiveErrors(_type))
return; return;
m_errorList.push_back(make_shared<Error>(_errorId, _type, _description, _location, _secondaryLocation)); m_errorList.push_back(std::make_shared<Error>(_errorId, _type, _description, _location, _secondaryLocation));
} }
bool ErrorReporter::hasExcessiveErrors() const bool ErrorReporter::hasExcessiveErrors() const
@ -89,7 +88,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
m_warningCount++; m_warningCount++;
if (m_warningCount == c_maxWarningsAllowed) if (m_warningCount == c_maxWarningsAllowed)
m_errorList.push_back(make_shared<Error>(4591_error, Error::Type::Warning, "There are more than 256 warnings. Ignoring the rest.")); m_errorList.push_back(std::make_shared<Error>(4591_error, Error::Type::Warning, "There are more than 256 warnings. Ignoring the rest."));
if (m_warningCount >= c_maxWarningsAllowed) if (m_warningCount >= c_maxWarningsAllowed)
return true; return true;
@ -99,7 +98,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
m_infoCount++; m_infoCount++;
if (m_infoCount == c_maxInfosAllowed) if (m_infoCount == c_maxInfosAllowed)
m_errorList.push_back(make_shared<Error>(2833_error, Error::Type::Info, "There are more than 256 infos. Ignoring the rest.")); m_errorList.push_back(std::make_shared<Error>(2833_error, Error::Type::Info, "There are more than 256 infos. Ignoring the rest."));
if (m_infoCount >= c_maxInfosAllowed) if (m_infoCount >= c_maxInfosAllowed)
return true; return true;
@ -110,7 +109,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
if (m_errorCount > c_maxErrorsAllowed) if (m_errorCount > c_maxErrorsAllowed)
{ {
m_errorList.push_back(make_shared<Error>(4013_error, Error::Type::Warning, "There are more than 256 errors. Aborting.")); m_errorList.push_back(std::make_shared<Error>(4013_error, Error::Type::Warning, "There are more than 256 errors. Aborting."));
BOOST_THROW_EXCEPTION(FatalError()); BOOST_THROW_EXCEPTION(FatalError());
} }
} }
@ -118,13 +117,13 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
return false; return false;
} }
void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description) void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description)
{ {
error(_error, _type, _location, _secondaryLocation, _description); error(_error, _type, _location, _secondaryLocation, _description);
BOOST_THROW_EXCEPTION(FatalError()); BOOST_THROW_EXCEPTION(FatalError());
} }
void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, string const& _description) void ErrorReporter::fatalError(ErrorId _error, Error::Type _type, SourceLocation const& _location, std::string const& _description)
{ {
error(_error, _type, _location, _description); error(_error, _type, _location, _description);
BOOST_THROW_EXCEPTION(FatalError()); BOOST_THROW_EXCEPTION(FatalError());
@ -140,7 +139,7 @@ void ErrorReporter::clear()
m_errorList.clear(); m_errorList.clear();
} }
void ErrorReporter::declarationError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description) void ErrorReporter::declarationError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description)
{ {
error( error(
_error, _error,
@ -151,7 +150,7 @@ void ErrorReporter::declarationError(ErrorId _error, SourceLocation const& _loca
); );
} }
void ErrorReporter::declarationError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::declarationError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
error( error(
_error, _error,
@ -170,7 +169,7 @@ void ErrorReporter::fatalDeclarationError(ErrorId _error, SourceLocation const&
_description); _description);
} }
void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
error( error(
_error, _error,
@ -180,7 +179,7 @@ void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location,
); );
} }
void ErrorReporter::fatalParserError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
fatalError( fatalError(
_error, _error,
@ -190,7 +189,7 @@ void ErrorReporter::fatalParserError(ErrorId _error, SourceLocation const& _loca
); );
} }
void ErrorReporter::syntaxError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::syntaxError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
error( error(
_error, _error,
@ -200,7 +199,7 @@ void ErrorReporter::syntaxError(ErrorId _error, SourceLocation const& _location,
); );
} }
void ErrorReporter::typeError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description) void ErrorReporter::typeError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description)
{ {
error( error(
_error, _error,
@ -211,7 +210,7 @@ void ErrorReporter::typeError(ErrorId _error, SourceLocation const& _location, S
); );
} }
void ErrorReporter::typeError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::typeError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
error( error(
_error, _error,
@ -222,7 +221,7 @@ void ErrorReporter::typeError(ErrorId _error, SourceLocation const& _location, s
} }
void ErrorReporter::fatalTypeError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description) void ErrorReporter::fatalTypeError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description)
{ {
fatalError( fatalError(
_error, _error,
@ -233,7 +232,7 @@ void ErrorReporter::fatalTypeError(ErrorId _error, SourceLocation const& _locati
); );
} }
void ErrorReporter::fatalTypeError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::fatalTypeError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
fatalError( fatalError(
_error, _error,
@ -243,7 +242,7 @@ void ErrorReporter::fatalTypeError(ErrorId _error, SourceLocation const& _locati
); );
} }
void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const& _location, string const& _description) void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
error( error(
_error, _error,
@ -256,13 +255,13 @@ void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const&
void ErrorReporter::info( void ErrorReporter::info(
ErrorId _error, ErrorId _error,
SourceLocation const& _location, SourceLocation const& _location,
string const& _description std::string const& _description
) )
{ {
error(_error, Error::Type::Info, _location, _description); error(_error, Error::Type::Info, _location, _description);
} }
void ErrorReporter::info(ErrorId _error, string const& _description) void ErrorReporter::info(ErrorId _error, std::string const& _description)
{ {
error(_error, Error::Type::Info, SourceLocation(), _description); error(_error, Error::Type::Info, SourceLocation(), _description);
} }

View File

@ -26,7 +26,6 @@
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;

View File

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

View File

@ -25,7 +25,6 @@
#include <liblangutil/Scanner.h> #include <liblangutil/Scanner.h>
#include <liblangutil/ErrorReporter.h> #include <liblangutil/ErrorReporter.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -44,7 +43,7 @@ Token ParserBase::peekNextToken() const
return m_scanner->peekNextToken(); return m_scanner->peekNextToken();
} }
string ParserBase::currentLiteral() const std::string ParserBase::currentLiteral() const
{ {
return m_scanner->currentLiteral(); return m_scanner->currentLiteral();
} }
@ -54,7 +53,7 @@ Token ParserBase::advance()
return m_scanner->next(); return m_scanner->next();
} }
string ParserBase::tokenName(Token _token) std::string ParserBase::tokenName(Token _token)
{ {
if (_token == Token::Identifier) if (_token == Token::Identifier)
return "identifier"; return "identifier";
@ -75,56 +74,10 @@ void ParserBase::expectToken(Token _value, bool _advance)
{ {
Token tok = m_scanner->currentToken(); Token tok = m_scanner->currentToken();
if (tok != _value) if (tok != _value)
{ fatalParserError(
string const expectedToken = ParserBase::tokenName(_value); 2314_error,
if (m_parserErrorRecovery) "Expected " + ParserBase::tokenName(_value) + " but got " + tokenName(tok)
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, 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();
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));
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
{
string expectedToken = ParserBase::tokenName(_value);
parserWarning(3347_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
m_inParserRecovery = false;
}
if (_advance) if (_advance)
advance(); advance();
} }
@ -142,32 +95,32 @@ void ParserBase::decreaseRecursionDepth()
m_recursionDepth--; m_recursionDepth--;
} }
void ParserBase::parserWarning(ErrorId _error, string const& _description) void ParserBase::parserWarning(ErrorId _error, std::string const& _description)
{ {
m_errorReporter.warning(_error, currentLocation(), _description); m_errorReporter.warning(_error, currentLocation(), _description);
} }
void ParserBase::parserWarning(ErrorId _error, SourceLocation const& _location, string const& _description) void ParserBase::parserWarning(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
m_errorReporter.warning(_error, _location, _description); m_errorReporter.warning(_error, _location, _description);
} }
void ParserBase::parserError(ErrorId _error, SourceLocation const& _location, string const& _description) void ParserBase::parserError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
m_errorReporter.parserError(_error, _location, _description); m_errorReporter.parserError(_error, _location, _description);
} }
void ParserBase::parserError(ErrorId _error, string const& _description) void ParserBase::parserError(ErrorId _error, std::string const& _description)
{ {
parserError(_error, currentLocation(), _description); parserError(_error, currentLocation(), _description);
} }
void ParserBase::fatalParserError(ErrorId _error, string const& _description) void ParserBase::fatalParserError(ErrorId _error, std::string const& _description)
{ {
fatalParserError(_error, currentLocation(), _description); fatalParserError(_error, currentLocation(), _description);
} }
void ParserBase::fatalParserError(ErrorId _error, SourceLocation const& _location, string const& _description) void ParserBase::fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
{ {
m_errorReporter.fatalParserError(_error, _location, _description); m_errorReporter.fatalParserError(_error, _location, _description);
} }

View File

@ -38,14 +38,9 @@ struct ErrorId;
class ParserBase class ParserBase
{ {
public: public:
/// Set @a _parserErrorRecovery to true for additional error explicit ParserBase(ErrorReporter& errorReporter):
/// recovery. This is experimental and intended for use m_errorReporter(errorReporter)
/// 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; virtual ~ParserBase() = default;
@ -70,13 +65,9 @@ protected:
///@{ ///@{
///@name Helper functions ///@name Helper functions
/// If current token value is not @a _value, throw exception otherwise advance token /// If current token value is not @a _value, throw exception otherwise advance token
// @a if _advance is true and error recovery is in effect. // if @a _advance is true
void expectToken(Token _value, bool _advance = true); 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 currentToken() const;
Token peekNextToken() const; Token peekNextToken() const;
std::string tokenName(Token _token); std::string tokenName(Token _token);
@ -108,10 +99,6 @@ protected:
ErrorReporter& m_errorReporter; ErrorReporter& m_errorReporter;
/// Current recursion depth during parsing. /// Current recursion depth during parsing.
size_t m_recursionDepth = 0; 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

@ -61,12 +61,11 @@
#include <tuple> #include <tuple>
#include <array> #include <array>
using namespace std;
namespace solidity::langutil namespace solidity::langutil
{ {
string to_string(ScannerError _errorCode) std::string to_string(ScannerError _errorCode)
{ {
switch (_errorCode) switch (_errorCode)
{ {
@ -92,7 +91,7 @@ string to_string(ScannerError _errorCode)
} }
ostream& operator<<(ostream& os, ScannerError _errorCode) std::ostream& operator<<(std::ostream& os, ScannerError _errorCode)
{ {
return os << to_string(_errorCode); return os << to_string(_errorCode);
} }
@ -275,12 +274,12 @@ namespace
/// to the user. /// to the user.
static ScannerError validateBiDiMarkup(CharStream& _stream, size_t _startPosition) static ScannerError validateBiDiMarkup(CharStream& _stream, size_t _startPosition)
{ {
static array<pair<string_view, int>, 5> constexpr directionalSequences{ static std::array<std::pair<std::string_view, int>, 5> constexpr directionalSequences{
pair<string_view, int>{"\xE2\x80\xAD", 1}, // U+202D (LRO - Left-to-Right Override) std::pair<std::string_view, int>{"\xE2\x80\xAD", 1}, // U+202D (LRO - Left-to-Right Override)
pair<string_view, int>{"\xE2\x80\xAE", 1}, // U+202E (RLO - Right-to-Left Override) std::pair<std::string_view, int>{"\xE2\x80\xAE", 1}, // U+202E (RLO - Right-to-Left Override)
pair<string_view, int>{"\xE2\x80\xAA", 1}, // U+202A (LRE - Left-to-Right Embedding) std::pair<std::string_view, int>{"\xE2\x80\xAA", 1}, // U+202A (LRE - Left-to-Right Embedding)
pair<string_view, int>{"\xE2\x80\xAB", 1}, // U+202B (RLE - Right-to-Left Embedding) std::pair<std::string_view, int>{"\xE2\x80\xAB", 1}, // U+202B (RLE - Right-to-Left Embedding)
pair<string_view, int>{"\xE2\x80\xAC", -1} // U+202C (PDF - Pop Directional Formatting std::pair<std::string_view, int>{"\xE2\x80\xAC", -1} // U+202C (PDF - Pop Directional Formatting
}; };
size_t endPosition = _stream.position(); size_t endPosition = _stream.position();
@ -712,7 +711,7 @@ void Scanner::scanToken()
default: default:
if (isIdentifierStart(m_char)) if (isIdentifierStart(m_char))
{ {
tie(token, m, n) = scanIdentifierOrKeyword(); std::tie(token, m, n) = scanIdentifierOrKeyword();
// Special case for hexadecimal literals // Special case for hexadecimal literals
if (token == Token::Hex) if (token == Token::Hex)
@ -757,7 +756,7 @@ void Scanner::scanToken()
m_tokens[NextNext].location.end = static_cast<int>(sourcePos()); m_tokens[NextNext].location.end = static_cast<int>(sourcePos());
m_tokens[NextNext].location.sourceName = m_sourceName; m_tokens[NextNext].location.sourceName = m_sourceName;
m_tokens[NextNext].token = token; m_tokens[NextNext].token = token;
m_tokens[NextNext].extendedTokenInfo = make_tuple(m, n); m_tokens[NextNext].extendedTokenInfo = std::make_tuple(m, n);
} }
bool Scanner::scanEscape() bool Scanner::scanEscape()
@ -1011,7 +1010,7 @@ Token Scanner::scanNumber(char _charSeen)
return Token::Number; return Token::Number;
} }
tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword() std::tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
{ {
solAssert(isIdentifierStart(m_char), ""); solAssert(isIdentifierStart(m_char), "");
LiteralScope literal(this, LITERAL_TYPE_STRING); LiteralScope literal(this, LITERAL_TYPE_STRING);
@ -1020,15 +1019,28 @@ tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
while (isIdentifierPart(m_char) || (m_char == '.' && m_kind == ScannerKind::Yul)) while (isIdentifierPart(m_char) || (m_char == '.' && m_kind == ScannerKind::Yul))
addLiteralCharAndAdvance(); addLiteralCharAndAdvance();
literal.complete(); literal.complete();
auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal); auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal);
if (m_kind == ScannerKind::Yul) switch (m_kind)
{ {
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 // Turn Solidity identifier into a Yul keyword
if (m_tokens[NextNext].literal == "leave") if (m_tokens[NextNext].literal == "leave")
return std::make_tuple(Token::Leave, 0, 0); return std::make_tuple(Token::Leave, 0, 0);
// Turn non-Yul keywords into identifiers. // Turn non-Yul keywords into identifiers.
if (!TokenTraits::isYulKeyword(std::get<0>(token))) if (!TokenTraits::isYulKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0); 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; return token;
} }

View File

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

View File

@ -29,18 +29,18 @@
#include <limits> #include <limits>
#include <fmt/format.h> #include <fmt/format.h>
using namespace std; using namespace std::string_literals;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::util; using namespace solidity::util;
SemVerMatchExpressionParser::SemVerMatchExpressionParser(vector<Token> _tokens, vector<string> _literals): SemVerMatchExpressionParser::SemVerMatchExpressionParser(std::vector<Token> _tokens, std::vector<std::string> _literals):
m_tokens(std::move(_tokens)), m_literals(std::move(_literals)) m_tokens(std::move(_tokens)), m_literals(std::move(_literals))
{ {
solAssert(m_tokens.size() == m_literals.size(), ""); solAssert(m_tokens.size() == m_literals.size(), "");
} }
SemVerVersion::SemVerVersion(string const& _versionString) SemVerVersion::SemVerVersion(std::string const& _versionString)
{ {
auto i = _versionString.begin(); auto i = _versionString.begin();
auto end = _versionString.end(); auto end = _versionString.end();
@ -63,13 +63,13 @@ SemVerVersion::SemVerVersion(string const& _versionString)
{ {
auto prereleaseStart = ++i; auto prereleaseStart = ++i;
while (i != end && *i != '+') ++i; while (i != end && *i != '+') ++i;
prerelease = string(prereleaseStart, i); prerelease = std::string(prereleaseStart, i);
} }
if (i != end && *i == '+') if (i != end && *i == '+')
{ {
auto buildStart = ++i; auto buildStart = ++i;
while (i != end) ++i; while (i != end) ++i;
build = string(buildStart, i); build = std::string(buildStart, i);
} }
if (i != end) if (i != end)
solThrow(SemVerError, "Invalid versionString "s + _versionString); solThrow(SemVerError, "Invalid versionString "s + _versionString);

View File

@ -25,14 +25,13 @@
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace std;
SourceLocation solidity::langutil::parseSourceLocation(string const& _input, vector<shared_ptr<string const>> const& _sourceNames) SourceLocation solidity::langutil::parseSourceLocation(std::string const& _input, std::vector<std::shared_ptr<std::string const>> const& _sourceNames)
{ {
// Expected input: "start:length:sourceindex" // Expected input: "start:length:sourceindex"
enum SrcElem: size_t { Start, Length, Index }; enum SrcElem: size_t { Start, Length, Index };
vector<string> pos; std::vector<std::string> pos;
boost::algorithm::split(pos, _input, boost::is_any_of(":")); boost::algorithm::split(pos, _input, boost::is_any_of(":"));

View File

@ -24,7 +24,6 @@
#include <cmath> #include <cmath>
#include <variant> #include <variant>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -36,7 +35,7 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
{ {
SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception); SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
string const* message = boost::get_error_info<util::errinfo_comment>(_exception); std::string const* message = boost::get_error_info<util::errinfo_comment>(_exception);
SourceReference primary = extract(_charStreamProvider, location, message ? *message : ""); SourceReference primary = extract(_charStreamProvider, location, message ? *message : "");
std::vector<SourceReference> secondary; std::vector<SourceReference> secondary;
@ -45,7 +44,7 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
for (auto const& info: secondaryLocation->infos) for (auto const& info: secondaryLocation->infos)
secondary.emplace_back(extract(_charStreamProvider, &info.second, info.first)); secondary.emplace_back(extract(_charStreamProvider, &info.second, info.first));
return Message{std::move(primary), _typeOrSeverity, std::move(secondary), nullopt}; return Message{std::move(primary), _typeOrSeverity, std::move(secondary), std::nullopt};
} }
SourceReferenceExtractor::Message SourceReferenceExtractor::extract( SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
@ -78,7 +77,7 @@ SourceReference SourceReferenceExtractor::extract(
LineColumn end = charStream.translatePositionToLineColumn(_location->end); LineColumn end = charStream.translatePositionToLineColumn(_location->end);
bool const isMultiline = start.line != end.line; bool const isMultiline = start.line != end.line;
string line = charStream.lineAtPosition(_location->start); std::string line = charStream.lineAtPosition(_location->start);
int locationLength = int locationLength =
isMultiline ? isMultiline ?
@ -88,7 +87,7 @@ SourceReference SourceReferenceExtractor::extract(
if (locationLength > 150) if (locationLength > 150)
{ {
auto const lhs = static_cast<size_t>(start.column) + 35; auto const lhs = static_cast<size_t>(start.column) + 35;
string::size_type const rhs = (isMultiline ? line.length() : static_cast<size_t>(end.column)) - 35; std::string::size_type const rhs = (isMultiline ? line.length() : static_cast<size_t>(end.column)) - 35;
line = line.substr(0, lhs) + " ... " + line.substr(rhs); line = line.substr(0, lhs) + " ... " + line.substr(rhs);
end.column = start.column + 75; end.column = start.column + 75;
locationLength = 75; locationLength = 75;
@ -98,9 +97,9 @@ SourceReference SourceReferenceExtractor::extract(
{ {
int const len = static_cast<int>(line.length()); int const len = static_cast<int>(line.length());
line = line.substr( line = line.substr(
static_cast<size_t>(max(0, start.column - 35)), static_cast<size_t>(std::max(0, start.column - 35)),
static_cast<size_t>(min(start.column, 35)) + static_cast<size_t>( static_cast<size_t>(std::min(start.column, 35)) + static_cast<size_t>(
min(locationLength + 35, len - start.column) std::min(locationLength + 35, len - start.column)
) )
); );
if (start.column + locationLength + 35 < len) if (start.column + locationLength + 35 < len)
@ -119,7 +118,7 @@ SourceReference SourceReferenceExtractor::extract(
interest, interest,
isMultiline, isMultiline,
line, line,
min(start.column, static_cast<int>(line.length())), std::min(start.column, static_cast<int>(line.length())),
min(end.column, static_cast<int>(line.length())) std::min(end.column, static_cast<int>(line.length()))
}; };
} }

View File

@ -28,7 +28,6 @@
#include <string_view> #include <string_view>
#include <variant> #include <variant>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::util; using namespace solidity::util;
@ -114,15 +113,15 @@ void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref)
return; // No line available, nothing else to print return; // No line available, nothing else to print
} }
string line = std::to_string(_ref.position.line + 1); // one-based line number as string std::string line = std::to_string(_ref.position.line + 1); // one-based line number as string
string leftpad = string(line.size(), ' '); std::string leftpad = std::string(line.size(), ' ');
// line 0: source name // line 0: source name
m_stream << leftpad; m_stream << leftpad;
frameColored() << "-->"; frameColored() << "-->";
m_stream << ' ' << _ref.sourceName << ':' << line << ':' << (_ref.position.column + 1) << ":\n"; m_stream << ' ' << _ref.sourceName << ':' << line << ':' << (_ref.position.column + 1) << ":\n";
string_view text = _ref.text; std::string_view text = _ref.text;
if (m_charStreamProvider.charStream(_ref.sourceName).isImportedFromAST()) if (m_charStreamProvider.charStream(_ref.sourceName).isImportedFromAST())
return; return;

View File

@ -46,9 +46,16 @@ public:
bool _colored, bool _colored,
bool _withErrorIds 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. /// Prints source location if it is given.
void printSourceLocation(SourceReference const& _ref); void printSourceLocation(SourceReference const& _ref);
void printExceptionInformation(SourceReferenceExtractor::Message const& _msg); void printExceptionInformation(SourceReferenceExtractor::Message const& _msg);
@ -61,12 +68,11 @@ public:
util::Exception const& _exception, util::Exception const& _exception,
Error::Type _type, Error::Type _type,
CharStreamProvider const& _charStreamProvider, CharStreamProvider const& _charStreamProvider,
bool _colored = false, bool _colored = false
bool _withErrorIds = false
) )
{ {
std::ostringstream errorOutput; std::ostringstream errorOutput;
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds); SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, false /* _withErrorIds */);
formatter.printExceptionInformation(_exception, _type); formatter.printExceptionInformation(_exception, _type);
return errorOutput.str(); return errorOutput.str();
} }
@ -75,26 +81,39 @@ public:
util::Exception const& _exception, util::Exception const& _exception,
Error::Severity _severity, Error::Severity _severity,
CharStreamProvider const& _charStreamProvider, CharStreamProvider const& _charStreamProvider,
bool _colored = false, bool _colored = false
bool _withErrorIds = false
) )
{ {
std::ostringstream errorOutput; std::ostringstream errorOutput;
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds); SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, false /* _withErrorIds */);
formatter.printExceptionInformation(_exception, _severity); formatter.printExceptionInformation(_exception, _severity);
return errorOutput.str(); return errorOutput.str();
} }
static std::string formatErrorInformation( static std::string formatErrorInformation(
Error const& _error, Error const& _error,
CharStreamProvider const& _charStreamProvider CharStreamProvider const& _charStreamProvider,
bool _colored = false,
bool _withErrorIds = false
) )
{ {
return formatExceptionInformation( std::ostringstream errorOutput;
_error, SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
Error::errorSeverity(_error.type()), formatter.printErrorInformation(_error);
_charStreamProvider 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();
} }
static std::string formatErrorInformation(Error const& _error, CharStream const& _charStream); static std::string formatErrorInformation(Error const& _error, CharStream const& _charStream);

View File

@ -46,8 +46,6 @@
#include <map> #include <map>
using namespace std;
namespace solidity::langutil namespace solidity::langutil
{ {
@ -71,25 +69,25 @@ std::string ElementaryTypeNameToken::toString(bool const& tokenValue) const
void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second) void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second)
{ {
solAssert(TokenTraits::isElementaryTypeName(_baseType), "Expected elementary type name: " + string(TokenTraits::toString(_baseType))); solAssert(TokenTraits::isElementaryTypeName(_baseType), "Expected elementary type name: " + std::string(TokenTraits::toString(_baseType)));
if (_baseType == Token::BytesM) if (_baseType == Token::BytesM)
{ {
solAssert(_second == 0, "There should not be a second size argument to type bytesM."); solAssert(_second == 0, "There should not be a second size argument to type bytesM.");
solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + "."); solAssert(_first <= 32, "No elementary type bytes" + std::to_string(_first) + ".");
} }
else if (_baseType == Token::UIntM || _baseType == Token::IntM) else if (_baseType == Token::UIntM || _baseType == Token::IntM)
{ {
solAssert(_second == 0, "There should not be a second size argument to type " + string(TokenTraits::toString(_baseType)) + "."); solAssert(_second == 0, "There should not be a second size argument to type " + std::string(TokenTraits::toString(_baseType)) + ".");
solAssert( solAssert(
_first <= 256 && _first % 8 == 0, _first <= 256 && _first % 8 == 0,
"No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "." "No elementary type " + std::string(TokenTraits::toString(_baseType)) + std::to_string(_first) + "."
); );
} }
else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN) else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN)
{ {
solAssert( solAssert(
_first >= 8 && _first <= 256 && _first % 8 == 0 && _second <= 80, _first >= 8 && _first <= 256 && _first % 8 == 0 && _second <= 80,
"No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "." "No elementary type " + std::string(TokenTraits::toString(_baseType)) + std::to_string(_first) + "x" + std::to_string(_second) + "."
); );
} }
else else
@ -136,29 +134,29 @@ std::string friendlyName(Token tok)
} }
static Token keywordByName(string const& _name) static Token keywordByName(std::string const& _name)
{ {
// The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored // The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored
// and keywords to be put inside the keywords variable. // and keywords to be put inside the keywords variable.
#define KEYWORD(name, string, precedence) {string, Token::name}, #define KEYWORD(name, string, precedence) {string, Token::name},
#define TOKEN(name, string, precedence) #define TOKEN(name, string, precedence)
static map<string, Token> const keywords({TOKEN_LIST(TOKEN, KEYWORD)}); static std::map<std::string, Token> const keywords({TOKEN_LIST(TOKEN, KEYWORD)});
#undef KEYWORD #undef KEYWORD
#undef TOKEN #undef TOKEN
auto it = keywords.find(_name); auto it = keywords.find(_name);
return it == keywords.end() ? Token::Identifier : it->second; return it == keywords.end() ? Token::Identifier : it->second;
} }
bool isYulKeyword(string const& _literal) bool isYulKeyword(std::string const& _literal)
{ {
return _literal == "leave" || isYulKeyword(keywordByName(_literal)); return _literal == "leave" || isYulKeyword(keywordByName(_literal));
} }
tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(string const& _literal) std::tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(std::string const& _literal)
{ {
// Used for `bytesM`, `uintM`, `intM`, `fixedMxN`, `ufixedMxN`. // Used for `bytesM`, `uintM`, `intM`, `fixedMxN`, `ufixedMxN`.
// M/N must be shortest representation. M can never be 0. N can be zero. // M/N must be shortest representation. M can never be 0. N can be zero.
auto parseSize = [](string::const_iterator _begin, string::const_iterator _end) -> int auto parseSize = [](std::string::const_iterator _begin, std::string::const_iterator _end) -> int
{ {
// No number. // No number.
if (distance(_begin, _end) == 0) if (distance(_begin, _end) == 0)
@ -185,23 +183,23 @@ tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(string const& _
auto positionM = find_if(_literal.begin(), _literal.end(), util::isDigit); auto positionM = find_if(_literal.begin(), _literal.end(), util::isDigit);
if (positionM != _literal.end()) if (positionM != _literal.end())
{ {
string baseType(_literal.begin(), positionM); std::string baseType(_literal.begin(), positionM);
auto positionX = find_if_not(positionM, _literal.end(), util::isDigit); auto positionX = find_if_not(positionM, _literal.end(), util::isDigit);
int m = parseSize(positionM, positionX); int m = parseSize(positionM, positionX);
Token keyword = keywordByName(baseType); Token keyword = keywordByName(baseType);
if (keyword == Token::Bytes) if (keyword == Token::Bytes)
{ {
if (0 < m && m <= 32 && positionX == _literal.end()) if (0 < m && m <= 32 && positionX == _literal.end())
return make_tuple(Token::BytesM, m, 0); return std::make_tuple(Token::BytesM, m, 0);
} }
else if (keyword == Token::UInt || keyword == Token::Int) else if (keyword == Token::UInt || keyword == Token::Int)
{ {
if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end()) if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end())
{ {
if (keyword == Token::UInt) if (keyword == Token::UInt)
return make_tuple(Token::UIntM, m, 0); return std::make_tuple(Token::UIntM, m, 0);
else else
return make_tuple(Token::IntM, m, 0); return std::make_tuple(Token::IntM, m, 0);
} }
} }
else if (keyword == Token::UFixed || keyword == Token::Fixed) else if (keyword == Token::UFixed || keyword == Token::Fixed)
@ -218,16 +216,16 @@ tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(string const& _
0 <= n && n <= 80 0 <= n && n <= 80
) { ) {
if (keyword == Token::UFixed) if (keyword == Token::UFixed)
return make_tuple(Token::UFixedMxN, m, n); return std::make_tuple(Token::UFixedMxN, m, n);
else else
return make_tuple(Token::FixedMxN, m, n); return std::make_tuple(Token::FixedMxN, m, n);
} }
} }
} }
return make_tuple(Token::Identifier, 0, 0); return std::make_tuple(Token::Identifier, 0, 0);
} }
return make_tuple(keywordByName(_literal), 0, 0); return std::make_tuple(keywordByName(_literal), 0, 0);
} }
} }

View File

@ -268,6 +268,8 @@ namespace solidity::langutil
/* Yul-specific tokens, but not keywords. */ \ /* Yul-specific tokens, but not keywords. */ \
T(Leave, "leave", 0) \ 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. */ \ /* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \ T(Illegal, "ILLEGAL", 0) \
\ \
@ -323,6 +325,39 @@ namespace TokenTraits
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex; 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); bool isYulKeyword(std::string const& _literal);
Token AssignmentToBinaryOp(Token op); Token AssignmentToBinaryOp(Token op);

View File

@ -31,20 +31,19 @@
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::smtutil; using namespace solidity::smtutil;
CHCSmtLib2Interface::CHCSmtLib2Interface( CHCSmtLib2Interface::CHCSmtLib2Interface(
map<h256, string> const& _queryResponses, std::map<h256, std::string> const& _queryResponses,
ReadCallback::Callback _smtCallback, ReadCallback::Callback _smtCallback,
SMTSolverChoice _enabledSolvers, SMTSolverChoice _enabledSolvers,
optional<unsigned> _queryTimeout std::optional<unsigned> _queryTimeout
): ):
CHCSolverInterface(_queryTimeout), CHCSolverInterface(_queryTimeout),
m_smtlib2(make_unique<SMTLib2Interface>(_queryResponses, _smtCallback, m_queryTimeout)), m_smtlib2(std::make_unique<SMTLib2Interface>(_queryResponses, _smtCallback, m_queryTimeout)),
m_queryResponses(std::move(_queryResponses)), m_queryResponses(std::move(_queryResponses)),
m_smtCallback(_smtCallback), m_smtCallback(_smtCallback),
m_enabledSolvers(_enabledSolvers) m_enabledSolvers(_enabledSolvers)
@ -66,8 +65,8 @@ void CHCSmtLib2Interface::registerRelation(Expression const& _expr)
smtAssert(_expr.sort->kind == Kind::Function); smtAssert(_expr.sort->kind == Kind::Function);
if (!m_variables.count(_expr.name)) if (!m_variables.count(_expr.name))
{ {
auto fSort = dynamic_pointer_cast<FunctionSort>(_expr.sort); auto fSort = std::dynamic_pointer_cast<FunctionSort>(_expr.sort);
string domain = toSmtLibSort(fSort->domain); std::string domain = toSmtLibSort(fSort->domain);
// Relations are predicates which have implicit codomain Bool. // Relations are predicates which have implicit codomain Bool.
m_variables.insert(_expr.name); m_variables.insert(_expr.name);
write( write(
@ -89,10 +88,10 @@ void CHCSmtLib2Interface::addRule(Expression const& _expr, std::string const& /*
); );
} }
tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> CHCSmtLib2Interface::query(Expression const& _block) std::tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> CHCSmtLib2Interface::query(Expression const& _block)
{ {
string query = dumpQuery(_block); std::string query = dumpQuery(_block);
string response = querySolver(query); std::string response = querySolver(query);
CheckResult result; CheckResult result;
// TODO proper parsing // TODO proper parsing
@ -108,7 +107,7 @@ tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> CHCSmtLib2Interface
return {result, Expression(true), {}}; return {result, Expression(true), {}};
} }
void CHCSmtLib2Interface::declareVariable(string const& _name, SortPointer const& _sort) void CHCSmtLib2Interface::declareVariable(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort); smtAssert(_sort);
if (_sort->kind == Kind::Function) if (_sort->kind == Kind::Function)
@ -120,25 +119,25 @@ void CHCSmtLib2Interface::declareVariable(string const& _name, SortPointer const
} }
} }
string CHCSmtLib2Interface::toSmtLibSort(Sort const& _sort) std::string CHCSmtLib2Interface::toSmtLibSort(Sort const& _sort)
{ {
if (!m_sortNames.count(&_sort)) if (!m_sortNames.count(&_sort))
m_sortNames[&_sort] = m_smtlib2->toSmtLibSort(_sort); m_sortNames[&_sort] = m_smtlib2->toSmtLibSort(_sort);
return m_sortNames.at(&_sort); return m_sortNames.at(&_sort);
} }
string CHCSmtLib2Interface::toSmtLibSort(vector<SortPointer> const& _sorts) std::string CHCSmtLib2Interface::toSmtLibSort(std::vector<SortPointer> const& _sorts)
{ {
string ssort("("); std::string ssort("(");
for (auto const& sort: _sorts) for (auto const& sort: _sorts)
ssort += toSmtLibSort(*sort) + " "; ssort += toSmtLibSort(*sort) + " ";
ssort += ")"; ssort += ")";
return ssort; return ssort;
} }
string CHCSmtLib2Interface::forall() std::string CHCSmtLib2Interface::forall()
{ {
string vars("("); std::string vars("(");
for (auto const& [name, sort]: m_smtlib2->variables()) for (auto const& [name, sort]: m_smtlib2->variables())
{ {
solAssert(sort, ""); solAssert(sort, "");
@ -149,17 +148,17 @@ string CHCSmtLib2Interface::forall()
return vars; return vars;
} }
void CHCSmtLib2Interface::declareFunction(string const& _name, SortPointer const& _sort) void CHCSmtLib2Interface::declareFunction(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort); smtAssert(_sort);
smtAssert(_sort->kind == Kind::Function); smtAssert(_sort->kind == Kind::Function);
// TODO Use domain and codomain as key as well // TODO Use domain and codomain as key as well
if (!m_variables.count(_name)) if (!m_variables.count(_name))
{ {
auto fSort = dynamic_pointer_cast<FunctionSort>(_sort); auto fSort = std::dynamic_pointer_cast<FunctionSort>(_sort);
smtAssert(fSort->codomain); smtAssert(fSort->codomain);
string domain = toSmtLibSort(fSort->domain); std::string domain = toSmtLibSort(fSort->domain);
string codomain = toSmtLibSort(*fSort->codomain); std::string codomain = toSmtLibSort(*fSort->codomain);
m_variables.insert(_name); m_variables.insert(_name);
write( write(
"(declare-fun |" + "(declare-fun |" +
@ -173,12 +172,12 @@ void CHCSmtLib2Interface::declareFunction(string const& _name, SortPointer const
} }
} }
void CHCSmtLib2Interface::write(string _data) void CHCSmtLib2Interface::write(std::string _data)
{ {
m_accumulatedOutput += std::move(_data) + "\n"; m_accumulatedOutput += std::move(_data) + "\n";
} }
string CHCSmtLib2Interface::querySolver(string const& _input) std::string CHCSmtLib2Interface::querySolver(std::string const& _input)
{ {
util::h256 inputHash = util::keccak256(_input); util::h256 inputHash = util::keccak256(_input);
if (m_queryResponses.count(inputHash)) if (m_queryResponses.count(inputHash))
@ -212,7 +211,7 @@ std::string CHCSmtLib2Interface::dumpQuery(Expression const& _expr)
std::string CHCSmtLib2Interface::createHeaderAndDeclarations() { std::string CHCSmtLib2Interface::createHeaderAndDeclarations() {
std::stringstream s; std::stringstream s;
if (m_queryTimeout) if (m_queryTimeout)
s << "(set-option :timeout " + to_string(*m_queryTimeout) + ")\n"; s << "(set-option :timeout " + std::to_string(*m_queryTimeout) + ")\n";
s << "(set-logic HORN)" << std::endl; s << "(set-logic HORN)" << std::endl;
for (auto const& decl: m_smtlib2->userSorts() | ranges::views::values) for (auto const& decl: m_smtlib2->userSorts() | ranges::views::values)

View File

@ -23,12 +23,11 @@
#include <cvc4/util/bitvector.h> #include <cvc4/util/bitvector.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::smtutil; using namespace solidity::smtutil;
CVC4Interface::CVC4Interface(optional<unsigned> _queryTimeout): CVC4Interface::CVC4Interface(std::optional<unsigned> _queryTimeout):
SolverInterface(_queryTimeout), SolverInterface(_queryTimeout),
m_solver(&m_context) m_solver(&m_context)
{ {
@ -56,7 +55,7 @@ void CVC4Interface::pop()
m_solver.pop(); m_solver.pop();
} }
void CVC4Interface::declareVariable(string const& _name, SortPointer const& _sort) void CVC4Interface::declareVariable(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort, ""); smtAssert(_sort, "");
m_variables[_name] = m_context.mkVar(_name.c_str(), cvc4Sort(*_sort)); m_variables[_name] = m_context.mkVar(_name.c_str(), cvc4Sort(*_sort));
@ -86,10 +85,10 @@ void CVC4Interface::addAssertion(Expression const& _expr)
} }
} }
pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const& _expressionsToEvaluate) std::pair<CheckResult, std::vector<std::string>> CVC4Interface::check(std::vector<Expression> const& _expressionsToEvaluate)
{ {
CheckResult result; CheckResult result;
vector<string> values; std::vector<std::string> values;
try try
{ {
switch (m_solver.checkSat().isSat()) switch (m_solver.checkSat().isSat())
@ -119,7 +118,7 @@ pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const&
values.clear(); values.clear();
} }
return make_pair(result, values); return std::make_pair(result, values);
} }
CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr) CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
@ -128,13 +127,13 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
if (_expr.arguments.empty() && m_variables.count(_expr.name)) if (_expr.arguments.empty() && m_variables.count(_expr.name))
return m_variables.at(_expr.name); return m_variables.at(_expr.name);
vector<CVC4::Expr> arguments; std::vector<CVC4::Expr> arguments;
for (auto const& arg: _expr.arguments) for (auto const& arg: _expr.arguments)
arguments.push_back(toCVC4Expr(arg)); arguments.push_back(toCVC4Expr(arg));
try try
{ {
string const& n = _expr.name; std::string const& n = _expr.name;
// Function application // Function application
if (!arguments.empty() && m_variables.count(_expr.name)) if (!arguments.empty() && m_variables.count(_expr.name))
return m_context.mkExpr(CVC4::kind::APPLY_UF, m_variables.at(n), arguments); return m_context.mkExpr(CVC4::kind::APPLY_UF, m_variables.at(n), arguments);
@ -145,7 +144,7 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
return m_context.mkConst(true); return m_context.mkConst(true);
else if (n == "false") else if (n == "false")
return m_context.mkConst(false); return m_context.mkConst(false);
else if (auto sortSort = dynamic_pointer_cast<SortSort>(_expr.sort)) else if (auto sortSort = std::dynamic_pointer_cast<SortSort>(_expr.sort))
return m_context.mkVar(n, cvc4Sort(*sortSort->inner)); return m_context.mkVar(n, cvc4Sort(*sortSort->inner));
else else
try try
@ -224,7 +223,7 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
} }
else if (n == "bv2int") else if (n == "bv2int")
{ {
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort); auto intSort = std::dynamic_pointer_cast<IntSort>(_expr.sort);
smtAssert(intSort, ""); smtAssert(intSort, "");
auto nat = m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, arguments[0]); auto nat = m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, arguments[0]);
if (!intSort->isSigned) if (!intSort->isSigned)
@ -254,13 +253,13 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
return m_context.mkExpr(CVC4::kind::STORE, arguments[0], arguments[1], arguments[2]); return m_context.mkExpr(CVC4::kind::STORE, arguments[0], arguments[1], arguments[2]);
else if (n == "const_array") else if (n == "const_array")
{ {
shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort); std::shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort);
smtAssert(sortSort, ""); smtAssert(sortSort, "");
return m_context.mkConst(CVC4::ArrayStoreAll(cvc4Sort(*sortSort->inner), arguments[1])); return m_context.mkConst(CVC4::ArrayStoreAll(cvc4Sort(*sortSort->inner), arguments[1]));
} }
else if (n == "tuple_get") else if (n == "tuple_get")
{ {
shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.arguments[0].sort); std::shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.arguments[0].sort);
smtAssert(tupleSort, ""); smtAssert(tupleSort, "");
CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components)); CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components));
CVC4::Datatype const& dt = tt.getDatatype(); CVC4::Datatype const& dt = tt.getDatatype();
@ -270,7 +269,7 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
} }
else if (n == "tuple_constructor") else if (n == "tuple_constructor")
{ {
shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.sort); std::shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.sort);
smtAssert(tupleSort, ""); smtAssert(tupleSort, "");
CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components)); CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components));
CVC4::Datatype const& dt = tt.getDatatype(); CVC4::Datatype const& dt = tt.getDatatype();
@ -328,9 +327,9 @@ CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort)
return m_context.integerType(); return m_context.integerType();
} }
vector<CVC4::Type> CVC4Interface::cvc4Sort(vector<SortPointer> const& _sorts) std::vector<CVC4::Type> CVC4Interface::cvc4Sort(std::vector<SortPointer> const& _sorts)
{ {
vector<CVC4::Type> cvc4Sorts; std::vector<CVC4::Type> cvc4Sorts;
for (auto const& _sort: _sorts) for (auto const& _sort: _sorts)
cvc4Sorts.push_back(cvc4Sort(*_sort)); cvc4Sorts.push_back(cvc4Sort(*_sort));
return cvc4Sorts; return cvc4Sorts;

View File

@ -33,16 +33,15 @@
#include <string> #include <string>
#include <utility> #include <utility>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::smtutil; using namespace solidity::smtutil;
SMTLib2Interface::SMTLib2Interface( SMTLib2Interface::SMTLib2Interface(
map<h256, string> _queryResponses, std::map<h256, std::string> _queryResponses,
ReadCallback::Callback _smtCallback, ReadCallback::Callback _smtCallback,
optional<unsigned> _queryTimeout std::optional<unsigned> _queryTimeout
): ):
SolverInterface(_queryTimeout), SolverInterface(_queryTimeout),
m_queryResponses(std::move(_queryResponses)), m_queryResponses(std::move(_queryResponses)),
@ -59,7 +58,7 @@ void SMTLib2Interface::reset()
m_userSorts.clear(); m_userSorts.clear();
write("(set-option :produce-models true)"); write("(set-option :produce-models true)");
if (m_queryTimeout) if (m_queryTimeout)
write("(set-option :timeout " + to_string(*m_queryTimeout) + ")"); write("(set-option :timeout " + std::to_string(*m_queryTimeout) + ")");
write("(set-logic ALL)"); write("(set-logic ALL)");
} }
@ -74,7 +73,7 @@ void SMTLib2Interface::pop()
m_accumulatedOutput.pop_back(); m_accumulatedOutput.pop_back();
} }
void SMTLib2Interface::declareVariable(string const& _name, SortPointer const& _sort) void SMTLib2Interface::declareVariable(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort, ""); smtAssert(_sort, "");
if (_sort->kind == Kind::Function) if (_sort->kind == Kind::Function)
@ -86,16 +85,16 @@ void SMTLib2Interface::declareVariable(string const& _name, SortPointer const& _
} }
} }
void SMTLib2Interface::declareFunction(string const& _name, SortPointer const& _sort) void SMTLib2Interface::declareFunction(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort, ""); smtAssert(_sort, "");
smtAssert(_sort->kind == Kind::Function, ""); smtAssert(_sort->kind == Kind::Function, "");
// TODO Use domain and codomain as key as well // TODO Use domain and codomain as key as well
if (!m_variables.count(_name)) if (!m_variables.count(_name))
{ {
auto const& fSort = dynamic_pointer_cast<FunctionSort>(_sort); auto const& fSort = std::dynamic_pointer_cast<FunctionSort>(_sort);
string domain = toSmtLibSort(fSort->domain); std::string domain = toSmtLibSort(fSort->domain);
string codomain = toSmtLibSort(*fSort->codomain); std::string codomain = toSmtLibSort(*fSort->codomain);
m_variables.emplace(_name, _sort); m_variables.emplace(_name, _sort);
write( write(
"(declare-fun |" + "(declare-fun |" +
@ -114,9 +113,9 @@ void SMTLib2Interface::addAssertion(Expression const& _expr)
write("(assert " + toSExpr(_expr) + ")"); write("(assert " + toSExpr(_expr) + ")");
} }
pair<CheckResult, vector<string>> SMTLib2Interface::check(vector<Expression> const& _expressionsToEvaluate) std::pair<CheckResult, std::vector<std::string>> SMTLib2Interface::check(std::vector<Expression> const& _expressionsToEvaluate)
{ {
string response = querySolver( std::string response = querySolver(
boost::algorithm::join(m_accumulatedOutput, "\n") + boost::algorithm::join(m_accumulatedOutput, "\n") +
checkSatAndGetValuesCommand(_expressionsToEvaluate) checkSatAndGetValuesCommand(_expressionsToEvaluate)
); );
@ -132,13 +131,13 @@ pair<CheckResult, vector<string>> SMTLib2Interface::check(vector<Expression> con
else else
result = CheckResult::ERROR; result = CheckResult::ERROR;
vector<string> values; std::vector<std::string> values;
if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty()) if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty())
values = parseValues(find(response.cbegin(), response.cend(), '\n'), response.cend()); values = parseValues(find(response.cbegin(), response.cend(), '\n'), response.cend());
return make_pair(result, values); return std::make_pair(result, values);
} }
string SMTLib2Interface::toSExpr(Expression const& _expr) std::string SMTLib2Interface::toSExpr(Expression const& _expr)
{ {
if (_expr.arguments.empty()) if (_expr.arguments.empty())
return _expr.name; return _expr.name;
@ -148,16 +147,16 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
{ {
size_t size = std::stoul(_expr.arguments[1].name); size_t size = std::stoul(_expr.arguments[1].name);
auto arg = toSExpr(_expr.arguments.front()); auto arg = toSExpr(_expr.arguments.front());
auto int2bv = "(_ int2bv " + to_string(size) + ")"; auto int2bv = "(_ int2bv " + std::to_string(size) + ")";
// Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed.
sexpr += string("ite ") + sexpr += std::string("ite ") +
"(>= " + arg + " 0) " + "(>= " + arg + " 0) " +
"(" + int2bv + " " + arg + ") " + "(" + int2bv + " " + arg + ") " +
"(bvneg (" + int2bv + " (- " + arg + ")))"; "(bvneg (" + int2bv + " (- " + arg + ")))";
} }
else if (_expr.name == "bv2int") else if (_expr.name == "bv2int")
{ {
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort); auto intSort = std::dynamic_pointer_cast<IntSort>(_expr.sort);
smtAssert(intSort, ""); smtAssert(intSort, "");
auto arg = toSExpr(_expr.arguments.front()); auto arg = toSExpr(_expr.arguments.front());
@ -166,13 +165,13 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
if (!intSort->isSigned) if (!intSort->isSigned)
return nat; return nat;
auto bvSort = dynamic_pointer_cast<BitVectorSort>(_expr.arguments.front().sort); auto bvSort = std::dynamic_pointer_cast<BitVectorSort>(_expr.arguments.front().sort);
smtAssert(bvSort, ""); smtAssert(bvSort, "");
auto size = to_string(bvSort->size); auto size = std::to_string(bvSort->size);
auto pos = to_string(bvSort->size - 1); auto pos = std::to_string(bvSort->size - 1);
// Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed.
sexpr += string("ite ") + sexpr += std::string("ite ") +
"(= ((_ extract " + pos + " " + pos + ")" + arg + ") #b0) " + "(= ((_ extract " + pos + " " + pos + ")" + arg + ") #b0) " +
nat + " " + nat + " " +
"(- (bv2nat (bvneg " + arg + ")))"; "(- (bv2nat (bvneg " + arg + ")))";
@ -182,7 +181,7 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
smtAssert(_expr.arguments.size() == 2, ""); smtAssert(_expr.arguments.size() == 2, "");
auto sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments.at(0).sort); auto sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments.at(0).sort);
smtAssert(sortSort, ""); smtAssert(sortSort, "");
auto arraySort = dynamic_pointer_cast<ArraySort>(sortSort->inner); auto arraySort = std::dynamic_pointer_cast<ArraySort>(sortSort->inner);
smtAssert(arraySort, ""); smtAssert(arraySort, "");
sexpr += "(as const " + toSmtLibSort(*arraySort) + ") "; sexpr += "(as const " + toSmtLibSort(*arraySort) + ") ";
sexpr += toSExpr(_expr.arguments.at(1)); sexpr += toSExpr(_expr.arguments.at(1));
@ -190,14 +189,14 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
else if (_expr.name == "tuple_get") else if (_expr.name == "tuple_get")
{ {
smtAssert(_expr.arguments.size() == 2, ""); smtAssert(_expr.arguments.size() == 2, "");
auto tupleSort = dynamic_pointer_cast<TupleSort>(_expr.arguments.at(0).sort); auto tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.arguments.at(0).sort);
size_t index = std::stoul(_expr.arguments.at(1).name); size_t index = std::stoul(_expr.arguments.at(1).name);
smtAssert(index < tupleSort->members.size(), ""); smtAssert(index < tupleSort->members.size(), "");
sexpr += "|" + tupleSort->members.at(index) + "| " + toSExpr(_expr.arguments.at(0)); sexpr += "|" + tupleSort->members.at(index) + "| " + toSExpr(_expr.arguments.at(0));
} }
else if (_expr.name == "tuple_constructor") else if (_expr.name == "tuple_constructor")
{ {
auto tupleSort = dynamic_pointer_cast<TupleSort>(_expr.sort); auto tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.sort);
smtAssert(tupleSort, ""); smtAssert(tupleSort, "");
sexpr += "|" + tupleSort->name + "|"; sexpr += "|" + tupleSort->name + "|";
for (auto const& arg: _expr.arguments) for (auto const& arg: _expr.arguments)
@ -213,7 +212,7 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
return sexpr; return sexpr;
} }
string SMTLib2Interface::toSmtLibSort(Sort const& _sort) std::string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
{ {
switch (_sort.kind) switch (_sort.kind)
{ {
@ -222,7 +221,7 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
case Kind::Bool: case Kind::Bool:
return "Bool"; return "Bool";
case Kind::BitVector: case Kind::BitVector:
return "(_ BitVec " + to_string(dynamic_cast<BitVectorSort const&>(_sort).size) + ")"; return "(_ BitVec " + std::to_string(dynamic_cast<BitVectorSort const&>(_sort).size) + ")";
case Kind::Array: case Kind::Array:
{ {
auto const& arraySort = dynamic_cast<ArraySort const&>(_sort); auto const& arraySort = dynamic_cast<ArraySort const&>(_sort);
@ -232,11 +231,11 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
case Kind::Tuple: case Kind::Tuple:
{ {
auto const& tupleSort = dynamic_cast<TupleSort const&>(_sort); auto const& tupleSort = dynamic_cast<TupleSort const&>(_sort);
string tupleName = "|" + tupleSort.name + "|"; std::string tupleName = "|" + tupleSort.name + "|";
auto isName = [&](auto entry) { return entry.first == tupleName; }; auto isName = [&](auto entry) { return entry.first == tupleName; };
if (ranges::find_if(m_userSorts, isName) == m_userSorts.end()) if (ranges::find_if(m_userSorts, isName) == m_userSorts.end())
{ {
string decl("(declare-datatypes ((" + tupleName + " 0)) (((" + tupleName); std::string decl("(declare-datatypes ((" + tupleName + " 0)) (((" + tupleName);
smtAssert(tupleSort.members.size() == tupleSort.components.size(), ""); smtAssert(tupleSort.members.size() == tupleSort.components.size(), "");
for (unsigned i = 0; i < tupleSort.members.size(); ++i) for (unsigned i = 0; i < tupleSort.members.size(); ++i)
decl += " (|" + tupleSort.members.at(i) + "| " + toSmtLibSort(*tupleSort.components.at(i)) + ")"; decl += " (|" + tupleSort.members.at(i) + "| " + toSmtLibSort(*tupleSort.components.at(i)) + ")";
@ -252,24 +251,24 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
} }
} }
string SMTLib2Interface::toSmtLibSort(vector<SortPointer> const& _sorts) std::string SMTLib2Interface::toSmtLibSort(std::vector<SortPointer> const& _sorts)
{ {
string ssort("("); std::string ssort("(");
for (auto const& sort: _sorts) for (auto const& sort: _sorts)
ssort += toSmtLibSort(*sort) + " "; ssort += toSmtLibSort(*sort) + " ";
ssort += ")"; ssort += ")";
return ssort; return ssort;
} }
void SMTLib2Interface::write(string _data) void SMTLib2Interface::write(std::string _data)
{ {
smtAssert(!m_accumulatedOutput.empty(), ""); smtAssert(!m_accumulatedOutput.empty(), "");
m_accumulatedOutput.back() += std::move(_data) + "\n"; m_accumulatedOutput.back() += std::move(_data) + "\n";
} }
string SMTLib2Interface::checkSatAndGetValuesCommand(vector<Expression> const& _expressionsToEvaluate) std::string SMTLib2Interface::checkSatAndGetValuesCommand(std::vector<Expression> const& _expressionsToEvaluate)
{ {
string command; std::string command;
if (_expressionsToEvaluate.empty()) if (_expressionsToEvaluate.empty())
command = "(check-sat)\n"; command = "(check-sat)\n";
else else
@ -279,22 +278,22 @@ string SMTLib2Interface::checkSatAndGetValuesCommand(vector<Expression> const& _
{ {
auto const& e = _expressionsToEvaluate.at(i); auto const& e = _expressionsToEvaluate.at(i);
smtAssert(e.sort->kind == Kind::Int || e.sort->kind == Kind::Bool, "Invalid sort for expression to evaluate."); smtAssert(e.sort->kind == Kind::Int || e.sort->kind == Kind::Bool, "Invalid sort for expression to evaluate.");
command += "(declare-const |EVALEXPR_" + to_string(i) + "| " + (e.sort->kind == Kind::Int ? "Int" : "Bool") + ")\n"; command += "(declare-const |EVALEXPR_" + std::to_string(i) + "| " + (e.sort->kind == Kind::Int ? "Int" : "Bool") + ")\n";
command += "(assert (= |EVALEXPR_" + to_string(i) + "| " + toSExpr(e) + "))\n"; command += "(assert (= |EVALEXPR_" + std::to_string(i) + "| " + toSExpr(e) + "))\n";
} }
command += "(check-sat)\n"; command += "(check-sat)\n";
command += "(get-value ("; command += "(get-value (";
for (size_t i = 0; i < _expressionsToEvaluate.size(); i++) for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
command += "|EVALEXPR_" + to_string(i) + "| "; command += "|EVALEXPR_" + std::to_string(i) + "| ";
command += "))\n"; command += "))\n";
} }
return command; return command;
} }
vector<string> SMTLib2Interface::parseValues(string::const_iterator _start, string::const_iterator _end) std::vector<std::string> SMTLib2Interface::parseValues(std::string::const_iterator _start, std::string::const_iterator _end)
{ {
vector<string> values; std::vector<std::string> values;
while (_start < _end) while (_start < _end)
{ {
auto valStart = find(_start, _end, ' '); auto valStart = find(_start, _end, ' ');
@ -308,7 +307,7 @@ vector<string> SMTLib2Interface::parseValues(string::const_iterator _start, stri
return values; return values;
} }
string SMTLib2Interface::querySolver(string const& _input) std::string SMTLib2Interface::querySolver(std::string const& _input)
{ {
h256 inputHash = keccak256(_input); h256 inputHash = keccak256(_input);
if (m_queryResponses.count(inputHash)) if (m_queryResponses.count(inputHash))
@ -323,7 +322,7 @@ string SMTLib2Interface::querySolver(string const& _input)
return "unknown\n"; return "unknown\n";
} }
string SMTLib2Interface::dumpQuery(vector<Expression> const& _expressionsToEvaluate) std::string SMTLib2Interface::dumpQuery(std::vector<Expression> const& _expressionsToEvaluate)
{ {
return boost::algorithm::join(m_accumulatedOutput, "\n") + return boost::algorithm::join(m_accumulatedOutput, "\n") +
checkSatAndGetValuesCommand(_expressionsToEvaluate); checkSatAndGetValuesCommand(_expressionsToEvaluate);

View File

@ -26,31 +26,30 @@
#endif #endif
#include <libsmtutil/SMTLib2Interface.h> #include <libsmtutil/SMTLib2Interface.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::smtutil; using namespace solidity::smtutil;
SMTPortfolio::SMTPortfolio( SMTPortfolio::SMTPortfolio(
map<h256, string> _smtlib2Responses, std::map<h256, std::string> _smtlib2Responses,
frontend::ReadCallback::Callback _smtCallback, frontend::ReadCallback::Callback _smtCallback,
[[maybe_unused]] SMTSolverChoice _enabledSolvers, [[maybe_unused]] SMTSolverChoice _enabledSolvers,
optional<unsigned> _queryTimeout, std::optional<unsigned> _queryTimeout,
bool _printQuery bool _printQuery
): ):
SolverInterface(_queryTimeout) SolverInterface(_queryTimeout)
{ {
solAssert(!_printQuery || _enabledSolvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries"); solAssert(!_printQuery || _enabledSolvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries");
if (_enabledSolvers.smtlib2) if (_enabledSolvers.smtlib2)
m_solvers.emplace_back(make_unique<SMTLib2Interface>(std::move(_smtlib2Responses), std::move(_smtCallback), m_queryTimeout)); m_solvers.emplace_back(std::make_unique<SMTLib2Interface>(std::move(_smtlib2Responses), std::move(_smtCallback), m_queryTimeout));
#ifdef HAVE_Z3 #ifdef HAVE_Z3
if (_enabledSolvers.z3 && Z3Interface::available()) if (_enabledSolvers.z3 && Z3Interface::available())
m_solvers.emplace_back(make_unique<Z3Interface>(m_queryTimeout)); m_solvers.emplace_back(std::make_unique<Z3Interface>(m_queryTimeout));
#endif #endif
#ifdef HAVE_CVC4 #ifdef HAVE_CVC4
if (_enabledSolvers.cvc4) if (_enabledSolvers.cvc4)
m_solvers.emplace_back(make_unique<CVC4Interface>(m_queryTimeout)); m_solvers.emplace_back(std::make_unique<CVC4Interface>(m_queryTimeout));
#endif #endif
} }
@ -72,7 +71,7 @@ void SMTPortfolio::pop()
s->pop(); s->pop();
} }
void SMTPortfolio::declareVariable(string const& _name, SortPointer const& _sort) void SMTPortfolio::declareVariable(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort, ""); smtAssert(_sort, "");
for (auto const& s: m_solvers) for (auto const& s: m_solvers)
@ -115,14 +114,14 @@ void SMTPortfolio::addAssertion(Expression const& _expr)
* *
* If all solvers return ERROR, the result is ERROR. * If all solvers return ERROR, the result is ERROR.
*/ */
pair<CheckResult, vector<string>> SMTPortfolio::check(vector<Expression> const& _expressionsToEvaluate) std::pair<CheckResult, std::vector<std::string>> SMTPortfolio::check(std::vector<Expression> const& _expressionsToEvaluate)
{ {
CheckResult lastResult = CheckResult::ERROR; CheckResult lastResult = CheckResult::ERROR;
vector<string> finalValues; std::vector<std::string> finalValues;
for (auto const& s: m_solvers) for (auto const& s: m_solvers)
{ {
CheckResult result; CheckResult result;
vector<string> values; std::vector<std::string> values;
tie(result, values) = s->check(_expressionsToEvaluate); tie(result, values) = s->check(_expressionsToEvaluate);
if (solverAnswered(result)) if (solverAnswered(result))
{ {
@ -140,10 +139,10 @@ pair<CheckResult, vector<string>> SMTPortfolio::check(vector<Expression> const&
else if (result == CheckResult::UNKNOWN && lastResult == CheckResult::ERROR) else if (result == CheckResult::UNKNOWN && lastResult == CheckResult::ERROR)
lastResult = result; lastResult = result;
} }
return make_pair(lastResult, finalValues); return std::make_pair(lastResult, finalValues);
} }
vector<string> SMTPortfolio::unhandledQueries() std::vector<std::string> SMTPortfolio::unhandledQueries()
{ {
// This code assumes that the constructor guarantees that // This code assumes that the constructor guarantees that
// SmtLib2Interface is in position 0, if enabled. // SmtLib2Interface is in position 0, if enabled.
@ -158,7 +157,7 @@ bool SMTPortfolio::solverAnswered(CheckResult result)
return result == CheckResult::SATISFIABLE || result == CheckResult::UNSATISFIABLE; return result == CheckResult::SATISFIABLE || result == CheckResult::UNSATISFIABLE;
} }
string SMTPortfolio::dumpQuery(vector<Expression> const& _expressionsToEvaluate) std::string SMTPortfolio::dumpQuery(std::vector<Expression> const& _expressionsToEvaluate)
{ {
// This code assumes that the constructor guarantees that // This code assumes that the constructor guarantees that
// SmtLib2Interface is in position 0, if enabled. // SmtLib2Interface is in position 0, if enabled.

View File

@ -19,22 +19,20 @@
#include <libsmtutil/Sorts.h> #include <libsmtutil/Sorts.h>
using namespace std;
namespace solidity::smtutil namespace solidity::smtutil
{ {
shared_ptr<Sort> const SortProvider::boolSort{make_shared<Sort>(Kind::Bool)}; std::shared_ptr<Sort> const SortProvider::boolSort{std::make_shared<Sort>(Kind::Bool)};
shared_ptr<IntSort> const SortProvider::uintSort{make_shared<IntSort>(false)}; std::shared_ptr<IntSort> const SortProvider::uintSort{std::make_shared<IntSort>(false)};
shared_ptr<IntSort> const SortProvider::sintSort{make_shared<IntSort>(true)}; std::shared_ptr<IntSort> const SortProvider::sintSort{std::make_shared<IntSort>(true)};
shared_ptr<IntSort> SortProvider::intSort(bool _signed) std::shared_ptr<IntSort> SortProvider::intSort(bool _signed)
{ {
if (_signed) if (_signed)
return sintSort; return sintSort;
return uintSort; return uintSort;
} }
shared_ptr<BitVectorSort> const SortProvider::bitVectorSort{make_shared<BitVectorSort>(256)}; std::shared_ptr<BitVectorSort> const SortProvider::bitVectorSort{std::make_shared<BitVectorSort>(256)};
} }

View File

@ -23,21 +23,20 @@
#include <set> #include <set>
#include <stack> #include <stack>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::smtutil; using namespace solidity::smtutil;
Z3CHCInterface::Z3CHCInterface(optional<unsigned> _queryTimeout): Z3CHCInterface::Z3CHCInterface(std::optional<unsigned> _queryTimeout):
CHCSolverInterface(_queryTimeout), CHCSolverInterface(_queryTimeout),
m_z3Interface(make_unique<Z3Interface>(m_queryTimeout)), m_z3Interface(std::make_unique<Z3Interface>(m_queryTimeout)),
m_context(m_z3Interface->context()), m_context(m_z3Interface->context()),
m_solver(*m_context) m_solver(*m_context)
{ {
Z3_get_version( Z3_get_version(
&get<0>(m_version), &std::get<0>(m_version),
&get<1>(m_version), &std::get<1>(m_version),
&get<2>(m_version), &std::get<2>(m_version),
&get<3>(m_version) &std::get<3>(m_version)
); );
// These need to be set globally. // These need to be set globally.
@ -51,7 +50,7 @@ Z3CHCInterface::Z3CHCInterface(optional<unsigned> _queryTimeout):
setSpacerOptions(); setSpacerOptions();
} }
void Z3CHCInterface::declareVariable(string const& _name, SortPointer const& _sort) void Z3CHCInterface::declareVariable(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort, ""); smtAssert(_sort, "");
m_z3Interface->declareVariable(_name, _sort); m_z3Interface->declareVariable(_name, _sort);
@ -62,7 +61,7 @@ void Z3CHCInterface::registerRelation(Expression const& _expr)
m_solver.register_relation(m_z3Interface->functions().at(_expr.name)); m_solver.register_relation(m_z3Interface->functions().at(_expr.name));
} }
void Z3CHCInterface::addRule(Expression const& _expr, string const& _name) void Z3CHCInterface::addRule(Expression const& _expr, std::string const& _name)
{ {
z3::expr rule = m_z3Interface->toZ3Expr(_expr); z3::expr rule = m_z3Interface->toZ3Expr(_expr);
if (m_z3Interface->constants().empty()) if (m_z3Interface->constants().empty())
@ -77,7 +76,7 @@ void Z3CHCInterface::addRule(Expression const& _expr, string const& _name)
} }
} }
tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> Z3CHCInterface::query(Expression const& _expr) std::tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> Z3CHCInterface::query(Expression const& _expr)
{ {
CheckResult result; CheckResult result;
try try
@ -90,7 +89,7 @@ tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> Z3CHCInterface::que
result = CheckResult::SATISFIABLE; result = CheckResult::SATISFIABLE;
// z3 version 4.8.8 modified Spacer to also return // z3 version 4.8.8 modified Spacer to also return
// proofs containing nonlinear clauses. // proofs containing nonlinear clauses.
if (m_version >= tuple(4, 8, 8, 0)) if (m_version >= std::tuple(4, 8, 8, 0))
{ {
auto proof = m_solver.get_answer(); auto proof = m_solver.get_answer();
return {result, Expression(true), cexGraph(proof)}; return {result, Expression(true), cexGraph(proof)};
@ -113,7 +112,7 @@ tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> Z3CHCInterface::que
} }
catch (z3::exception const& _err) catch (z3::exception const& _err)
{ {
set<string> msgs{ std::set<std::string> msgs{
/// Resource limit (rlimit) exhausted. /// Resource limit (rlimit) exhausted.
"max. resource limit exceeded", "max. resource limit exceeded",
/// User given timeout exhausted. /// User given timeout exhausted.
@ -178,13 +177,13 @@ CHCSolverInterface::CexGraph Z3CHCInterface::cexGraph(z3::expr const& _proof)
CexGraph graph; CexGraph graph;
stack<z3::expr> proofStack; std::stack<z3::expr> proofStack;
proofStack.push(_proof.arg(0)); proofStack.push(_proof.arg(0));
auto const& root = proofStack.top(); auto const& root = proofStack.top();
graph.nodes.emplace(root.id(), m_z3Interface->fromZ3Expr(fact(root))); graph.nodes.emplace(root.id(), m_z3Interface->fromZ3Expr(fact(root)));
set<unsigned> visited; std::set<unsigned> visited;
visited.insert(root.id()); visited.insert(root.id());
while (!proofStack.empty()) while (!proofStack.empty())
@ -227,16 +226,16 @@ z3::expr Z3CHCInterface::fact(z3::expr const& _node)
return _node.arg(_node.num_args() - 1); return _node.arg(_node.num_args() - 1);
} }
string Z3CHCInterface::name(z3::expr const& _predicate) std::string Z3CHCInterface::name(z3::expr const& _predicate)
{ {
smtAssert(_predicate.is_app(), ""); smtAssert(_predicate.is_app(), "");
return _predicate.decl().name().str(); return _predicate.decl().name().str();
} }
vector<string> Z3CHCInterface::arguments(z3::expr const& _predicate) std::vector<std::string> Z3CHCInterface::arguments(z3::expr const& _predicate)
{ {
smtAssert(_predicate.is_app(), ""); smtAssert(_predicate.is_app(), "");
vector<string> args; std::vector<std::string> args;
for (unsigned i = 0; i < _predicate.num_args(); ++i) for (unsigned i = 0; i < _predicate.num_args(); ++i)
args.emplace_back(_predicate.arg(i).to_string()); args.emplace_back(_predicate.arg(i).to_string());
return args; return args;

View File

@ -26,7 +26,6 @@
#include <libsmtutil/Z3Loader.h> #include <libsmtutil/Z3Loader.h>
#endif #endif
using namespace std;
using namespace solidity::smtutil; using namespace solidity::smtutil;
using namespace solidity::util; using namespace solidity::util;
@ -69,7 +68,7 @@ void Z3Interface::pop()
m_solver.pop(); m_solver.pop();
} }
void Z3Interface::declareVariable(string const& _name, SortPointer const& _sort) void Z3Interface::declareVariable(std::string const& _name, SortPointer const& _sort)
{ {
smtAssert(_sort, ""); smtAssert(_sort, "");
if (_sort->kind == Kind::Function) if (_sort->kind == Kind::Function)
@ -80,7 +79,7 @@ void Z3Interface::declareVariable(string const& _name, SortPointer const& _sort)
m_constants.emplace(_name, m_context.constant(_name.c_str(), z3Sort(*_sort))); m_constants.emplace(_name, m_context.constant(_name.c_str(), z3Sort(*_sort)));
} }
void Z3Interface::declareFunction(string const& _name, Sort const& _sort) void Z3Interface::declareFunction(std::string const& _name, Sort const& _sort)
{ {
smtAssert(_sort.kind == Kind::Function, ""); smtAssert(_sort.kind == Kind::Function, "");
FunctionSort fSort = dynamic_cast<FunctionSort const&>(_sort); FunctionSort fSort = dynamic_cast<FunctionSort const&>(_sort);
@ -95,10 +94,10 @@ void Z3Interface::addAssertion(Expression const& _expr)
m_solver.add(toZ3Expr(_expr)); m_solver.add(toZ3Expr(_expr));
} }
pair<CheckResult, vector<string>> Z3Interface::check(vector<Expression> const& _expressionsToEvaluate) std::pair<CheckResult, std::vector<std::string>> Z3Interface::check(std::vector<Expression> const& _expressionsToEvaluate)
{ {
CheckResult result; CheckResult result;
vector<string> values; std::vector<std::string> values;
try try
{ {
switch (m_solver.check()) switch (m_solver.check())
@ -123,7 +122,7 @@ pair<CheckResult, vector<string>> Z3Interface::check(vector<Expression> const& _
} }
catch (z3::exception const& _err) catch (z3::exception const& _err)
{ {
set<string> msgs{ std::set<std::string> msgs{
/// Resource limit (rlimit) exhausted. /// Resource limit (rlimit) exhausted.
"max. resource limit exceeded", "max. resource limit exceeded",
/// User given timeout exhausted. /// User given timeout exhausted.
@ -137,7 +136,7 @@ pair<CheckResult, vector<string>> Z3Interface::check(vector<Expression> const& _
values.clear(); values.clear();
} }
return make_pair(result, values); return std::make_pair(result, values);
} }
z3::expr Z3Interface::toZ3Expr(Expression const& _expr) z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
@ -150,7 +149,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
try try
{ {
string const& n = _expr.name; std::string const& n = _expr.name;
if (m_functions.count(n)) if (m_functions.count(n))
return m_functions.at(n)(arguments); return m_functions.at(n)(arguments);
else if (m_constants.count(n)) else if (m_constants.count(n))
@ -166,7 +165,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
return m_context.bool_val(false); return m_context.bool_val(false);
else if (_expr.sort->kind == Kind::Sort) else if (_expr.sort->kind == Kind::Sort)
{ {
auto sortSort = dynamic_pointer_cast<SortSort>(_expr.sort); auto sortSort = std::dynamic_pointer_cast<SortSort>(_expr.sort);
smtAssert(sortSort, ""); smtAssert(sortSort, "");
return m_context.constant(n.c_str(), z3Sort(*sortSort->inner)); return m_context.constant(n.c_str(), z3Sort(*sortSort->inner));
} }
@ -233,7 +232,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
} }
else if (n == "bv2int") else if (n == "bv2int")
{ {
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort); auto intSort = std::dynamic_pointer_cast<IntSort>(_expr.sort);
smtAssert(intSort, ""); smtAssert(intSort, "");
return z3::bv2int(arguments[0], intSort->isSigned); return z3::bv2int(arguments[0], intSort->isSigned);
} }
@ -243,9 +242,9 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
return z3::store(arguments[0], arguments[1], arguments[2]); return z3::store(arguments[0], arguments[1], arguments[2]);
else if (n == "const_array") else if (n == "const_array")
{ {
shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort); std::shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort);
smtAssert(sortSort, ""); smtAssert(sortSort, "");
auto arraySort = dynamic_pointer_cast<ArraySort>(sortSort->inner); auto arraySort = std::dynamic_pointer_cast<ArraySort>(sortSort->inner);
smtAssert(arraySort && arraySort->domain, ""); smtAssert(arraySort && arraySort->domain, "");
return z3::const_array(z3Sort(*arraySort->domain), arguments[1]); return z3::const_array(z3Sort(*arraySort->domain), arguments[1]);
} }
@ -285,7 +284,7 @@ Expression Z3Interface::fromZ3Expr(z3::expr const& _expr)
if (_expr.is_quantifier()) if (_expr.is_quantifier())
{ {
string quantifierName; std::string quantifierName;
if (_expr.is_exists()) if (_expr.is_exists())
quantifierName = "exists"; quantifierName = "exists";
else if (_expr.is_forall()) else if (_expr.is_forall())
@ -297,7 +296,7 @@ Expression Z3Interface::fromZ3Expr(z3::expr const& _expr)
return Expression(quantifierName, {fromZ3Expr(_expr.body())}, sort); return Expression(quantifierName, {fromZ3Expr(_expr.body())}, sort);
} }
smtAssert(_expr.is_app(), ""); smtAssert(_expr.is_app(), "");
vector<Expression> arguments; std::vector<Expression> arguments;
for (unsigned i = 0; i < _expr.num_args(); ++i) for (unsigned i = 0; i < _expr.num_args(); ++i)
arguments.push_back(fromZ3Expr(_expr.arg(i))); arguments.push_back(fromZ3Expr(_expr.arg(i)));
@ -370,12 +369,12 @@ Expression Z3Interface::fromZ3Expr(z3::expr const& _expr)
return Expression::store(arguments[0], arguments[1], arguments[2]); return Expression::store(arguments[0], arguments[1], arguments[2]);
else if (kind == Z3_OP_CONST_ARRAY) else if (kind == Z3_OP_CONST_ARRAY)
{ {
auto sortSort = make_shared<SortSort>(fromZ3Sort(_expr.get_sort())); auto sortSort = std::make_shared<SortSort>(fromZ3Sort(_expr.get_sort()));
return Expression::const_array(Expression(sortSort), arguments[0]); return Expression::const_array(Expression(sortSort), arguments[0]);
} }
else if (kind == Z3_OP_DT_CONSTRUCTOR) else if (kind == Z3_OP_DT_CONSTRUCTOR)
{ {
auto sortSort = make_shared<SortSort>(fromZ3Sort(_expr.get_sort())); auto sortSort = std::make_shared<SortSort>(fromZ3Sort(_expr.get_sort()));
return Expression::tuple_constructor(Expression(sortSort), arguments); return Expression::tuple_constructor(Expression(sortSort), arguments);
} }
else if (kind == Z3_OP_DT_ACCESSOR) else if (kind == Z3_OP_DT_ACCESSOR)
@ -412,12 +411,12 @@ z3::sort Z3Interface::z3Sort(Sort const& _sort)
case Kind::Tuple: case Kind::Tuple:
{ {
auto const& tupleSort = dynamic_cast<TupleSort const&>(_sort); auto const& tupleSort = dynamic_cast<TupleSort const&>(_sort);
vector<char const*> cMembers; std::vector<char const*> cMembers;
for (auto const& member: tupleSort.members) for (auto const& member: tupleSort.members)
cMembers.emplace_back(member.c_str()); cMembers.emplace_back(member.c_str());
/// Using this instead of the function below because with that one /// Using this instead of the function below because with that one
/// we can't use `&sorts[0]` here. /// we can't use `&sorts[0]` here.
vector<z3::sort> sorts; std::vector<z3::sort> sorts;
for (auto const& sort: tupleSort.components) for (auto const& sort: tupleSort.components)
sorts.push_back(z3Sort(*sort)); sorts.push_back(z3Sort(*sort));
z3::func_decl_vector projs(m_context); z3::func_decl_vector projs(m_context);
@ -439,7 +438,7 @@ z3::sort Z3Interface::z3Sort(Sort const& _sort)
return m_context.int_sort(); return m_context.int_sort();
} }
z3::sort_vector Z3Interface::z3Sort(vector<SortPointer> const& _sorts) z3::sort_vector Z3Interface::z3Sort(std::vector<SortPointer> const& _sorts)
{ {
z3::sort_vector z3Sorts(m_context); z3::sort_vector z3Sorts(m_context);
for (auto const& _sort: _sorts) for (auto const& _sort: _sorts)
@ -454,27 +453,27 @@ SortPointer Z3Interface::fromZ3Sort(z3::sort const& _sort)
if (_sort.is_int()) if (_sort.is_int())
return SortProvider::sintSort; return SortProvider::sintSort;
if (_sort.is_bv()) if (_sort.is_bv())
return make_shared<BitVectorSort>(_sort.bv_size()); return std::make_shared<BitVectorSort>(_sort.bv_size());
if (_sort.is_array()) if (_sort.is_array())
return make_shared<ArraySort>(fromZ3Sort(_sort.array_domain()), fromZ3Sort(_sort.array_range())); return std::make_shared<ArraySort>(fromZ3Sort(_sort.array_domain()), fromZ3Sort(_sort.array_range()));
if (_sort.is_datatype()) if (_sort.is_datatype())
{ {
auto name = _sort.name().str(); auto name = _sort.name().str();
auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, _sort)); auto constructor = z3::func_decl(m_context, Z3_get_tuple_sort_mk_decl(m_context, _sort));
vector<string> memberNames; std::vector<std::string> memberNames;
vector<SortPointer> memberSorts; std::vector<SortPointer> memberSorts;
for (unsigned i = 0; i < constructor.arity(); ++i) for (unsigned i = 0; i < constructor.arity(); ++i)
{ {
auto accessor = z3::func_decl(m_context, Z3_get_tuple_sort_field_decl(m_context, _sort, i)); auto accessor = z3::func_decl(m_context, Z3_get_tuple_sort_field_decl(m_context, _sort, i));
memberNames.push_back(accessor.name().str()); memberNames.push_back(accessor.name().str());
memberSorts.push_back(fromZ3Sort(accessor.range())); memberSorts.push_back(fromZ3Sort(accessor.range()));
} }
return make_shared<TupleSort>(name, memberNames, memberSorts); return std::make_shared<TupleSort>(name, memberNames, memberSorts);
} }
smtAssert(false, ""); smtAssert(false, "");
} }
vector<SortPointer> Z3Interface::fromZ3Sort(z3::sort_vector const& _sorts) std::vector<SortPointer> Z3Interface::fromZ3Sort(z3::sort_vector const& _sorts)
{ {
return applyMap(_sorts, [this](auto const& sort) { return fromZ3Sort(sort); }); return applyMap(_sorts, [this](auto const& sort) { return fromZ3Sort(sort); });
} }

View File

@ -27,7 +27,6 @@
#endif #endif
#include <dlfcn.h> #include <dlfcn.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::smtutil; using namespace solidity::smtutil;
@ -41,7 +40,7 @@ void* Z3Loader::loadSymbol(char const* _name) const
{ {
smtAssert(m_handle, "Attempted to use dynamically loaded Z3, even though it is not available."); smtAssert(m_handle, "Attempted to use dynamically loaded Z3, even though it is not available.");
void* sym = dlsym(m_handle, _name); void* sym = dlsym(m_handle, _name);
smtAssert(sym, string("Symbol \"") + _name + "\" not found in libz3.so"); smtAssert(sym, std::string("Symbol \"") + _name + "\" not found in libz3.so");
return sym; return sym;
} }
@ -59,7 +58,7 @@ bool Z3Loader::available() const
Z3Loader::Z3Loader() Z3Loader::Z3Loader()
{ {
string libname{"libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION)}; std::string libname{"libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION)};
m_handle = dlmopen(LM_ID_NEWLM, libname.c_str(), RTLD_NOW); m_handle = dlmopen(LM_ID_NEWLM, libname.c_str(), RTLD_NOW);
} }

View File

@ -32,7 +32,6 @@
#include "license.h" #include "license.h"
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
@ -42,21 +41,21 @@ using solidity::frontend::StandardCompiler;
namespace namespace
{ {
// The strings in this list must not be resized after they have been added here (via solidity_alloc()), because // The std::strings in this list must not be resized after they have been added here (via solidity_alloc()), because
// this may potentially change the pointer that was passed to the caller from solidity_alloc(). // this may potentially change the pointer that was passed to the caller from solidity_alloc().
static list<string> solidityAllocations; static std::list<std::string> solidityAllocations;
/// Find the equivalent to @p _data in the list of allocations of solidity_alloc(), /// Find the equivalent to @p _data in the list of allocations of solidity_alloc(),
/// removes it from the list and returns its value. /// removes it from the list and returns its value.
/// ///
/// If any invalid argument is being passed, it is considered a programming error /// If any invalid argument is being passed, it is considered a programming error
/// on the caller-side and hence, will call abort() then. /// on the caller-side and hence, will call abort() then.
string takeOverAllocation(char const* _data) std::string takeOverAllocation(char const* _data)
{ {
for (auto iter = begin(solidityAllocations); iter != end(solidityAllocations); ++iter) for (auto iter = begin(solidityAllocations); iter != end(solidityAllocations); ++iter)
if (iter->data() == _data) if (iter->data() == _data)
{ {
string chunk = std::move(*iter); std::string chunk = std::move(*iter);
solidityAllocations.erase(iter); solidityAllocations.erase(iter);
return chunk; return chunk;
} }
@ -64,11 +63,11 @@ string takeOverAllocation(char const* _data)
abort(); abort();
} }
/// Resizes a std::string to the proper length based on the occurrence of a zero terminator. /// Resizes a std::std::string to the proper length based on the occurrence of a zero terminator.
void truncateCString(string& _data) void truncateCString(std::string& _data)
{ {
size_t pos = _data.find('\0'); size_t pos = _data.find('\0');
if (pos != string::npos) if (pos != std::string::npos)
_data.resize(pos); _data.resize(pos);
} }
@ -77,7 +76,7 @@ ReadCallback::Callback wrapReadCallback(CStyleReadFileCallback _readCallback, vo
ReadCallback::Callback readCallback; ReadCallback::Callback readCallback;
if (_readCallback) if (_readCallback)
{ {
readCallback = [=](string const& _kind, string const& _data) readCallback = [=](std::string const& _kind, std::string const& _data)
{ {
char* contents_c = nullptr; char* contents_c = nullptr;
char* error_c = nullptr; char* error_c = nullptr;
@ -106,7 +105,7 @@ ReadCallback::Callback wrapReadCallback(CStyleReadFileCallback _readCallback, vo
return readCallback; return readCallback;
} }
string compile(string _input, CStyleReadFileCallback _readCallback, void* _readContext) std::string compile(std::string _input, CStyleReadFileCallback _readCallback, void* _readContext)
{ {
StandardCompiler compiler(wrapReadCallback(_readCallback, _readContext)); StandardCompiler compiler(wrapReadCallback(_readCallback, _readContext));
return compiler.compile(std::move(_input)); return compiler.compile(std::move(_input));
@ -118,7 +117,7 @@ extern "C"
{ {
extern char const* solidity_license() noexcept extern char const* solidity_license() noexcept
{ {
static string fullLicenseText = otherLicenses + licenseText; static std::string fullLicenseText = otherLicenses + licenseText;
return fullLicenseText.c_str(); return fullLicenseText.c_str();
} }

View File

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

View File

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

View File

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

View File

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

View File

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

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