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

View File

@ -52,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
then
brew update
brew upgrade
brew install boost
brew install cmake
brew install wget

View File

@ -44,6 +44,9 @@ cd test-cases/
echo "Preparing input files"
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
interface=$(echo -e "standard-json\ncli" | circleci tests split)
echo "Selected interface: ${interface}"

View File

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

View File

@ -6,42 +6,16 @@ on:
- opened
env:
ORGANIZATION: Ethereum
DRY_RUN: false
jobs:
comment-external-pr:
runs-on: ubuntu-latest
steps:
- name: Get organization members
id: get_members
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
# Note: this step requires that the INTERNAL_CONTRIBUTORS environment variable
# is already defined in the repository with the current json list of internal contributors.
- 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:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.html_url }}

View File

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

View File

@ -51,11 +51,11 @@ To set indentation and tab width settings uniformly, the repository contains an
## 1. Namespaces
1. No `using namespace` declarations in header files.
2. Use `using namespace std;` in cpp files, but avoid importing namespaces from boost and others.
3. All symbols should be declared in a namespace except for final applications.
4. Use anonymous namespaces for helpers whose scope is a cpp file only.
5. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
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.
2. `using namespace solidity;` and other project local namespaces is fine in cpp files, and generally encouraged.
3. Avoid `using namespace` at file level for third party libraries, such as boost, ranges, etc.
4. All symbols should be declared in a namespace except for final applications.
5. Use anonymous namespaces for helpers whose scope is a cpp file only.
6. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
Only in the header:
```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
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:
* 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:
* 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.
* 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.
* 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 ``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.
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: 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 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.
* 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: 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.
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``.

View File

@ -3,9 +3,9 @@
### Requirements
- [ ] GitHub account with access to [solidity](https://github.com/ethereum/solidity), [solc-js](https://github.com/ethereum/solc-js),
[solc-bin](https://github.com/ethereum/solc-bin), [homebrew-ethereum](https://github.com/ethereum/homebrew-ethereum),
[solidity-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).
- [ ] 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).
- [ ] Ubuntu/Debian dependencies of the PPA scripts: ``devscripts``, ``debhelper``, ``dput``, ``git``, ``wget``, ``ca-certificates``.
- [ ] [npm Registry](https://www.npmjs.com) account added as a collaborator for the [``solc`` package](https://www.npmjs.com/package/solc).
@ -37,8 +37,8 @@ At least a day before the release:
- [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements.
### Blog Post
- [ ] Create a post on [solidity-blog](https://github.com/ethereum/solidity-blog) in the ``Releases`` category and explain some of the new features or concepts.
- [ ] Create a post on [solidity-blog](https://github.com/ethereum/solidity-blog) in the ``Security Alerts`` category in case of important bug(s).
- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Releases`` category and explain some of the new features or concepts.
- [ ] Create a post on [solidity-website](https://github.com/ethereum/solidity-website/tree/main/src/posts) in the ``Security Alerts`` category in case of important bug(s).
### Changelog
- [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it.
@ -104,9 +104,9 @@ At least a day before the release:
- [ ] Make sure the documentation for the new release has been published successfully.
Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default.
- [ ] Remove "still in progress" warning from the [release notes](https://github.com/ethereum/solidity/releases).
- [ ] Merge the [blog posts](https://github.com/ethereum/solidity-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.
- [ ] 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 [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post.
- [ ] Share the announcement on Reddit in [``/r/ethdev``](https://reddit.com/r/ethdev/), cross-posted to [``/r/ethereum``](https://reddit.com/r/ethereum/).

View File

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

View File

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

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 {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
/* css-3 */
white-space: pre-wrap;
/* Mozilla, since 1999 */
white-space: -moz-pre-wrap;
/* Opera 4-6 */
white-space: -pre-wrap;
/* Opera 7 */
white-space: -o-pre-wrap;
word-wrap: break-word;
font-family: 'Overpass Mono', monospace;
}
small,
small * {
font-size: 12px;
}
.wy-table-responsive table td,
@ -16,10 +180,6 @@ pre {
}
/* links */
.rst-content a:not(:visited) {
color: #002fa7;
}
.rst-content .highlighted {
background: #eac545;
}
@ -29,24 +189,12 @@ pre {
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) */
.wy-side-nav-search > div.version {
color: #272525;
}
/* menu section headers */
.wy-menu p.caption {
color: #65afff;
.wy-side-nav-search>div.version {
color: var(--color-b);
margin-top: 0;
margin-bottom: 0.5rem;
text-align: start;
}
/* Link to Remix IDE shown next to code snippets */
@ -58,18 +206,621 @@ pre {
}
.rst-content .remix-link-container a.remix-link {
display: inline-block;
font-size: 0.7em;
padding: 0.1em 0.4em;
background: #e1e4e5;
color: #707070;
}
.rst-content .remix-link-container a.remix-link:hover {
background: #c8cbcc;
padding: 0.1em 0.5em;
background: transparent;
color: var(--color-a) !important;
border: 1px solid var(--color-a);
text-decoration: none;
}
.rst-content div.highlight-solidity,
.rst-content div.highlight-yul {
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;
display: flex;
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,
@ -76,8 +83,6 @@ html.transition *:after {
transition-delay: 0 !important;
}
nav.wy-nav-side {
/* The default padding of 2em is too small and the "Keyword Index" link gets obscured
* by the version toggle. */
padding-bottom: 3em;
}
.wy-menu-vertical a:hover {
background-color: #0002;
}

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) {
var mode = (isDay ? "Day" : "Night");
localStorage.setItem("css-mode", mode);
// Update localStorage with new color scheme preference
localStorage.setItem(LS_COLOR_SCHEME, newMode);
var url_root = DOCUMENTATION_OPTIONS.URL_ROOT == "./" ? "" : DOCUMENTATION_OPTIONS.URL_ROOT;
var daysheet = $(`link[href="${url_root}_static/pygments.css"]`)[0].sheet;
daysheet.disabled = !isDay;
// Update the root element with the new color scheme preference
document
.querySelector(":root")
.setAttribute("style", `--color-scheme: ${newMode}`);
var nightsheet = $(`link[href="${url_root}_static/css/dark.css"]`)[0];
if (!isDay && nightsheet === undefined) {
var element = document.createElement("link");
element.setAttribute("rel", "stylesheet");
element.setAttribute("type", "text/css");
element.setAttribute("href", `${url_root}_static/css/dark.css`);
document.getElementsByTagName("head")[0].appendChild(element);
return;
}
if (nightsheet !== undefined) {
nightsheet.sheet.disabled = isDay;
}
// Update logo
document
.querySelector(`img.${SOLIDITY_LOGO_CLASS}`)
.setAttribute("src", newMode === LIGHT ? LIGHT_LOGO_PATH : DARK_LOGO_PATH);
// Update color mode toggle icon
document
.querySelector(`img.${COLOR_TOGGLE_ICON_CLASS}`)
.setAttribute("src", newMode === LIGHT ? MOON_ICON_PATH : SUN_ICON_PATH);
// 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";
var checkbox = document.querySelector('input[name=mode]');
toggleCssMode(initial);
checkbox.checked = initial;
checkbox.addEventListener('change', function() {
document.documentElement.classList.add('transition');
window.setTimeout(() => {
document.documentElement.classList.remove('transition');
}, 1000)
toggleCssMode(this.checked);
})
});
};
document
.querySelectorAll('[data-toggle="rst-versions"]')
.forEach((e) => handleClassToggle(e, MOBILE_MENU_TOGGLE_CLASS));
document
.querySelectorAll('[data-toggle="wy-nav-shift"]')
.forEach((e) => handleClassToggle(e, MOBILE_MENU_TOGGLE_CLASS));
handleClassToggle(document.querySelector(`.${WRAPPER_CLASS}`), "menu-open");
}

View File

@ -67,7 +67,7 @@ When using the Solidity logo, please respect the Solidity logo guidelines.
Solidity Logo Guidelines
========================
.. image:: logo.svg
.. image:: solidity_logo.svg
:width: 256
*(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",
"name": "StorageWriteRemovalBeforeConditionalTermination",

View File

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

View File

@ -151,7 +151,7 @@ Modifiers
- ``view`` for functions: Disallows modification of state.
- ``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.
- ``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.
- ``indexed`` for event parameters: Stores the parameter as topic.
- ``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('Yul', YulLexer)
sphinx.add_css_file('css/fonts.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 ------------------------------------------------
@ -132,7 +135,6 @@ html_theme = 'sphinx_rtd_theme'
# documentation.
html_theme_options = {
'logo_only': True,
'style_nav_header_background': '#65afff',
'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
# 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
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# 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,
# 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_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
# .htaccess) here, relative to this directory. These files are copied
@ -210,7 +212,7 @@ html_extra_templates = {
#html_show_sourcelink = 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.
#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
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.4;
pragma solidity ^0.8.21;
uint constant X = 32**22 + 8;
contract C {
string constant TEXT = "abc";
bytes32 constant MY_HASH = keccak256("abc");
uint immutable decimals;
uint immutable decimals = 18;
uint immutable maxBalance;
address immutable owner = msg.sender;
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.
maxBalance = ref.balance;
}
@ -74,10 +78,29 @@ Immutable
=========
Variables declared as ``immutable`` are a bit less restricted than those
declared as ``constant``: Immutable variables can be assigned an arbitrary
value in the constructor of the contract or at the point of their declaration.
They can be assigned only once and can, from that point on, be read even during
construction time.
declared as ``constant``: Immutable variables can be assigned a
value at construction time.
The value can be changed at any time before deployment and then it becomes permanent.
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
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
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>`.
.. 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.
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
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
accessible (forever as of now, but this might
change with Serenity). The Log and its event data is not accessible from within

View File

@ -132,7 +132,7 @@ variables are set to their :ref:`default values<default-value>` just as if the f
body.
The ``_`` symbol can appear in the modifier multiple times. Each occurrence is replaced with
the function body.
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,
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
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
sure the pragma version specifies this version as a minimum.

View File

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

View File

@ -323,7 +323,7 @@ The following are dependencies for all builds of Solidity:
| `CMake`_ (version 3.21.3+ on | Cross-platform build file generator. |
| Windows, 3.13+ otherwise) | |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.77 on | C++ libraries. |
| `Boost`_ (version 1.77+ on | C++ libraries. |
| Windows, 1.65+ otherwise) | |
+-----------------------------------+-------------------------------------------------------+
| `Git`_ | Command-line tool for retrieving source code. |
@ -380,7 +380,7 @@ Prerequisites - macOS
---------------------
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
`Xcode IDE <https://en.wikipedia.org/wiki/Xcode>`_ and other Apple development
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. |
+-----------------------------------+-------------------------------------------------------+
| `Boost`_ (version 1.77) | C++ libraries. |
| `Boost`_ (version 1.77+) | C++ libraries. |
+-----------------------------------+-------------------------------------------------------+
If you already have one IDE and only need the compiler and libraries,

View File

@ -338,7 +338,7 @@ You can override this sequence and supply your own using the ``--yul-optimizatio
.. code-block:: bash
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOc'
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOcmu'
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,
@ -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
: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
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
^^^^^^^^^^^
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
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
@ -1216,6 +1216,11 @@ we can run the optimizer on this specialized function. If it
results in heavy gains, the specialized function is kept,
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
-------

View File

@ -30,6 +30,8 @@ Semantic Only Changes
This section lists the changes that are semantic-only, thus potentially
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 used to be:

View File

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

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``.
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::

View File

@ -71,7 +71,7 @@ Editor Integrations
* 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
* `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>`_
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>`_
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
most derived type in case of inheritance.
.. code-block:: solidity
.. code-block:: solidity
// SPDX-License-Identifier: GPL-3.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
transactions to ``B``.
.. code-block:: solidity
.. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0;
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
// 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 {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // Triggering event

View File

@ -372,7 +372,7 @@ Array Members
.. note::
In EVM versions before Byzantium, it was not possible to access
dynamic arrays 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
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
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>`_
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.

View File

@ -316,7 +316,8 @@ Input Description
},
// Version of the EVM to compile for.
// 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",
// Optional: Change compilation pipeline to go through the Yul intermediate representation.
// This is false by default.
@ -358,7 +359,7 @@ Input Description
// Addresses of the libraries. If not all libraries are given here,
// it can result in unlinked objects whose output data is different.
"libraries": {
// The top level key is the 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
// after remappings were applied.
// 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.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.
//
"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.
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.
Since it is the default type of this dialect, it can be omitted.

View File

@ -42,7 +42,6 @@
#include <fstream>
#include <limits>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::langutil;
@ -77,7 +76,7 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
namespace
{
string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location)
std::string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location)
{
if (!_location.hasText() || _sourceCodes.empty())
return {};
@ -92,7 +91,7 @@ string locationFromSources(StringMap const& _sourceCodes, SourceLocation const&
class Functionalizer
{
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)
{}
@ -105,7 +104,7 @@ public:
printLocation(_debugInfoSelection);
}
string expression = _item.toAssemblyText(m_assembly);
std::string expression = _item.toAssemblyText(m_assembly);
if (!(
_item.canBeFunctional() &&
@ -114,7 +113,7 @@ public:
))
{
flush();
m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << endl;
m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << std::endl;
return;
}
if (_item.arguments() > 0)
@ -137,8 +136,8 @@ public:
void flush()
{
for (string const& expression: m_pending)
m_out << m_prefix << " " << expression << endl;
for (std::string const& expression: m_pending)
m_out << m_prefix << " " << expression << std::endl;
m_pending.clear();
}
@ -154,7 +153,7 @@ public:
if (m_location.sourceName)
m_out << " " + escapeAndQuoteString(*m_location.sourceName);
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)
@ -165,15 +164,15 @@ public:
m_out << locationFromSources(m_sourceCodes, m_location);
}
m_out << " */" << endl;
m_out << " */" << std::endl;
}
private:
strings m_pending;
SourceLocation m_location;
ostream& m_out;
string const& m_prefix;
std::ostream& m_out;
std::string const& m_prefix;
StringMap const& m_sourceCodes;
Assembly const& m_assembly;
};
@ -181,9 +180,9 @@ private:
}
void Assembly::assemblyStream(
ostream& _out,
std::ostream& _out,
DebugInfoSelection const& _debugInfoSelection,
string const& _prefix,
std::string const& _prefix,
StringMap const& _sourceCodes
) const
{
@ -195,34 +194,34 @@ void Assembly::assemblyStream(
if (!m_data.empty() || !m_subs.empty())
{
_out << _prefix << "stop" << endl;
_out << _prefix << "stop" << std::endl;
for (auto const& i: m_data)
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)
{
_out << endl << _prefix << "sub_" << i << ": assembly {\n";
_out << std::endl << _prefix << "sub_" << i << ": assembly {\n";
m_subs[i]->assemblyStream(_out, _debugInfoSelection, _prefix + " ", _sourceCodes);
_out << _prefix << "}" << endl;
_out << _prefix << "}" << std::endl;
}
}
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,
StringMap const& _sourceCodes
) const
{
ostringstream tmp;
std::ostringstream tmp;
assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes);
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;
root[".code"] = Json::arrayValue;
@ -244,7 +243,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
jsonItem["end"] = item.location().end;
if (item.m_modifierDepth != 0)
jsonItem["modifierDepth"] = static_cast<int>(item.m_modifierDepth);
string jumpType = item.getJumpTypeAsString();
std::string jumpType = item.getJumpTypeAsString();
if (!jumpType.empty())
jsonItem["jumpType"] = jumpType;
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)
{
stringstream hexStr;
hexStr << hex << i;
std::stringstream hexStr;
hexStr << std::hex << i;
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;
}
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.");
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};
}
AssemblyItem Assembly::newPushLibraryAddress(string const& _identifier)
AssemblyItem Assembly::newPushLibraryAddress(std::string const& _identifier)
{
h256 h(util::keccak256(_identifier));
m_libraries[h] = _identifier;
return AssemblyItem{PushLibraryAddress, h};
}
AssemblyItem Assembly::newPushImmutable(string const& _identifier)
AssemblyItem Assembly::newPushImmutable(std::string const& _identifier)
{
h256 h(util::keccak256(_identifier));
m_immutables[h] = _identifier;
return AssemblyItem{PushImmutable, h};
}
AssemblyItem Assembly::newImmutableAssignment(string const& _identifier)
AssemblyItem Assembly::newImmutableAssignment(std::string const& _identifier)
{
h256 h(util::keccak256(_identifier));
m_immutables[h] = _identifier;
@ -339,9 +338,9 @@ Assembly& Assembly::optimise(OptimiserSettings const& _settings)
return *this;
}
map<u256, u256> const& Assembly::optimiseInternal(
std::map<u256, u256> const& Assembly::optimiseInternal(
OptimiserSettings const& _settings,
set<size_t> _tagsReferencedFromOutside
std::set<size_t> _tagsReferencedFromOutside
)
{
if (m_tagReplacements)
@ -352,7 +351,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
{
OptimiserSettings settings = _settings;
Assembly& sub = *m_subs[subId];
map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
std::map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
settings,
JumpdestRemover::referencedTags(m_items, subId)
);
@ -360,7 +359,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId);
}
map<u256, u256> tagReplacements;
std::map<u256, u256> tagReplacements;
// Iterate until no new optimisation possibilities are found.
for (unsigned count = 1; count > 0;)
{
@ -401,7 +400,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
for (auto const& replacement: deduplicator.replacedTags())
{
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,
"Invalid tag replacement."
);
@ -494,7 +493,7 @@ LinkerObject const& Assembly::assemble() const
LinkerObject& ret = m_assembledObject;
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)
{
auto const& linkerObject = sub->assemble();
@ -508,7 +507,7 @@ LinkerObject const& Assembly::assemble() const
immutableReferencesBySub = linkerObject.immutableReferences;
}
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;
}
@ -531,11 +530,11 @@ LinkerObject const& Assembly::assemble() const
);
unsigned bytesRequiredForCode = codeSize(static_cast<unsigned>(subTagSize));
m_tagPositionsInBytecode = vector<size_t>(m_usedTags, numeric_limits<size_t>::max());
map<size_t, pair<size_t, size_t>> tagRef;
multimap<h256, unsigned> dataRef;
multimap<size_t, size_t> subRef;
vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
m_tagPositionsInBytecode = std::vector<size_t>(m_usedTags, std::numeric_limits<size_t>::max());
std::map<size_t, std::pair<size_t, size_t>> tagRef;
std::multimap<h256, unsigned> dataRef;
std::multimap<size_t, size_t> subRef;
std::vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode);
uint8_t tagPush = static_cast<uint8_t>(pushInstruction(bytesPerTag));
@ -550,7 +549,7 @@ LinkerObject const& Assembly::assemble() const
for (AssemblyItem const& i: m_items)
{
// 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();
switch (i.type())
@ -583,21 +582,21 @@ LinkerObject const& Assembly::assemble() const
}
case PushData:
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);
break;
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);
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);
break;
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();
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.resize(ret.bytecode.size() + b);
bytesRef byr(&ret.bytecode.back() + 1 - b, b);
@ -618,7 +617,7 @@ LinkerObject const& Assembly::assemble() const
break;
case PushImmutable:
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());
// Record the bytecode offset of the PUSH32 argument.
ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size());
@ -661,10 +660,10 @@ LinkerObject const& Assembly::assemble() const
case Tag:
{
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());
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();
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
break;
@ -686,7 +685,7 @@ LinkerObject const& Assembly::assemble() const
// Append an INVALID here to help tests find miscompilation.
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)
{
LinkerObject subObject = subAssemblyById(subIdPath)->assemble();
@ -709,15 +708,15 @@ LinkerObject const& Assembly::assemble() const
{
size_t subId;
size_t tagId;
tie(subId, tagId) = i.second;
assertThrow(subId == numeric_limits<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id");
vector<size_t> const& tagPositions =
subId == numeric_limits<size_t>::max() ?
std::tie(subId, tagId) = i.second;
assertThrow(subId == std::numeric_limits<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id");
std::vector<size_t> const& tagPositions =
subId == std::numeric_limits<size_t>::max() ?
m_tagPositionsInBytecode :
m_subs[subId]->m_tagPositionsInBytecode;
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag.");
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.");
bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
toBigEndian(pos, r);
@ -725,7 +724,7 @@ LinkerObject const& Assembly::assemble() const
for (auto const& [name, tagInfo]: m_namedTags)
{
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)
if (item.type() == Tag && static_cast<size_t>(item.data()) == tagInfo.id)
{
@ -733,7 +732,7 @@ LinkerObject const& Assembly::assemble() const
break;
}
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,
tagInfo.sourceID,
tagInfo.params,
@ -764,7 +763,7 @@ LinkerObject const& Assembly::assemble() const
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())
return {_subObjectId};
@ -779,7 +778,7 @@ vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const
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, "");
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())
{
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, "");
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
{
vector<size_t> subIds = decodeSubPath(_subId);
std::vector<size_t> subIds = decodeSubPath(_subId);
Assembly const* currentAssembly = this;
for (size_t currentSubId: subIds)
{

View File

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

View File

@ -30,7 +30,6 @@
#include <functional>
#include <set>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
@ -49,7 +48,7 @@ bool BlockDeduplicator::deduplicate()
)
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)
return false;
@ -81,7 +80,7 @@ bool BlockDeduplicator::deduplicate()
for (; ; ++iterations)
{
//@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)
{
if (m_items.at(i).type() != Tag)
@ -101,7 +100,7 @@ bool BlockDeduplicator::deduplicate()
bool BlockDeduplicator::applyTagReplacement(
AssemblyItems& _items,
map<u256, u256> const& _replacements,
std::map<u256, u256> const& _replacements,
size_t _subId
)
{
@ -111,7 +110,7 @@ bool BlockDeduplicator::applyTagReplacement(
{
size_t subId;
size_t tagId;
tie(subId, tagId) = item.splitForeignPushTag();
std::tie(subId, tagId) = item.splitForeignPushTag();
if (subId != _subId)
continue;
auto it = _replacements.find(tagId);

View File

@ -30,12 +30,11 @@
#include <range/v3/view/reverse.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::langutil;
vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
std::vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
{
optimizeBreakingItem();
@ -52,11 +51,11 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
m_state = std::move(nextState);
});
map<int, Id> initialStackContents;
map<int, Id> targetStackContents;
std::map<int, Id> initialStackContents;
std::map<int, Id> targetStackContents;
int minHeight = m_state.stackHeight() + 1;
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)
initialStackContents[height] = m_initialState.stackElement(height, SourceLocation());
for (int height = minHeight; height <= m_state.stackHeight(); ++height)
@ -125,19 +124,19 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
CSECodeGenerator::CSECodeGenerator(
ExpressionClasses& _expressionClasses,
vector<CSECodeGenerator::StoreOperation> const& _storeOperations
std::vector<CSECodeGenerator::StoreOperation> const& _storeOperations
):
m_expressionClasses(_expressionClasses)
{
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(
unsigned _initialSequenceNumber,
int _initialStackHeight,
map<int, Id> const& _initialStack,
map<int, Id> const& _targetStackContents
std::map<int, Id> const& _initialStack,
std::map<int, Id> const& _targetStackContents
)
{
m_stackHeight = _initialStackHeight;
@ -156,7 +155,7 @@ AssemblyItems CSECodeGenerator::generateCode(
}
// 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 id: {p.first, p.second})
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
// sequence number during dependency analysis.
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.
@ -230,7 +229,7 @@ void CSECodeGenerator::addDependencies(Id _c)
for (Id argument: expr.arguments)
{
addDependencies(argument);
m_neededBy.insert(make_pair(argument, _c));
m_neededBy.insert(std::make_pair(argument, _c));
}
if (expr.item && expr.item->type() == Operation && (
expr.item->instruction() == Instruction::SLOAD ||
@ -294,7 +293,7 @@ void CSECodeGenerator::addDependencies(Id _c)
if (it->sequenceNumber < expr.sequenceNumber)
latestStore = it->expression;
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,
"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)
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[_fromPosition]].erase(_fromPosition);
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 &&
SemanticInformation::isSwapInstruction(m_generatedItems.back()) &&

View File

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

View File

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

View File

@ -22,7 +22,6 @@
#include <libsolutil/CommonIO.h>
#include <functional>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::evmasm;
@ -31,7 +30,7 @@ using namespace solidity::evmasm;
void solidity::evmasm::eachInstruction(
bytes const& _mem,
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)
@ -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) {
if (!isValidInstruction(_instr))
ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter;

View File

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

View File

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

View File

@ -38,7 +38,6 @@
#include <optional>
#include <limits>
using namespace std;
using namespace solidity;
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::GasConsumption());
if (gasConsumption.isInfinite)
return numeric_limits<u256>::max();
return std::numeric_limits<u256>::max();
else
return gasConsumption.value;
}
@ -66,14 +65,14 @@ uint64_t codeSize(RangeType const& _itemRange)
[](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); }
), 0u);
}
/// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, nullopt otherwise.
optional<size_t> getLocalTag(AssemblyItem const& _item)
/// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, std::nullopt otherwise.
std::optional<size_t> getLocalTag(AssemblyItem const& _item)
{
if (_item.type() != PushTag && _item.type() != Tag)
return nullopt;
return std::nullopt;
auto [subId, tag] = _item.splitForeignPushTag();
if (subId != numeric_limits<size_t>::max())
return nullopt;
if (subId != std::numeric_limits<size_t>::max())
return std::nullopt;
return tag;
}
}
@ -99,7 +98,7 @@ bool Inliner::isInlineCandidate(size_t _tag, ranges::span<AssemblyItem const> _i
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, 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.
if (item.type() == PushTag)
if (optional<size_t> tag = getLocalTag(item))
if (std::optional<size_t> tag = getLocalTag(item))
++numPushTags[*tag];
// 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))
{
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))
inlinableBlockItems[*tag] = block;
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.
map<size_t, InlinableBlock> result;
std::map<size_t, InlinableBlock> result;
for (auto&& [tag, items]: inlinableBlockItems)
if (uint64_t const* numPushes = util::valueOrNullptr(numPushTags, tag))
result.emplace(tag, InlinableBlock{items, *numPushes});
@ -199,7 +198,7 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span<AssemblyIte
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, "");
AssemblyItem blockExit = _block.items.back();
@ -232,7 +231,7 @@ optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _j
return blockExit;
}
return nullopt;
return std::nullopt;
}
@ -252,7 +251,7 @@ void Inliner::optimise()
AssemblyItem const& nextItem = *next(it);
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 exitItem = shouldInline(*tag, nextItem, *inlinableBlock))
{
@ -264,7 +263,7 @@ void Inliner::optimise()
// We might increase the number of push tags to other blocks.
for (AssemblyItem const& inlinedItem: inlinableBlock->items)
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))
++block->pushTagCount;

View File

@ -22,7 +22,6 @@
#include <libevmasm/Instruction.h>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::evmasm;
@ -335,7 +334,7 @@ InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst, langutil::E
}
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>
using namespace std;
using namespace solidity;
using namespace solidity::util;
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());
size_t initialSize = m_items.size();
@ -46,7 +45,7 @@ bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
if (_item.type() != Tag)
return false;
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;
return !references.count(tag);
}
@ -55,9 +54,9 @@ bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
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)
if (item.type() == PushTag)
{

View File

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

View File

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

View File

@ -24,7 +24,6 @@
#include <libsolutil/CommonData.h>
#include <libsolutil/Keccak256.h>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::evmasm;
@ -36,24 +35,24 @@ void LinkerObject::append(LinkerObject const& _other)
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;
for (auto const& linkRef: linkReferences)
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
remainingRefs.insert(linkRef);
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)
{
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] = '_';
for (size_t i = 0; i < 36; ++i)
hex[pos + 2 + i] = hash.at(i);
@ -61,15 +60,15 @@ string LinkerObject::toHex() const
return hex;
}
string LinkerObject::libraryPlaceholder(string const& _libraryName)
std::string LinkerObject::libraryPlaceholder(std::string const& _libraryName)
{
return "$" + keccak256(_libraryName).hex().substr(0, 34) + "$";
}
h160 const*
LinkerObject::matchLibrary(
string const& _linkRefName,
map<string, h160> const& _libraryAddresses
std::string const& _linkRefName,
std::map<std::string, h160> const& _libraryAddresses
)
{
auto it = _libraryAddresses.find(_linkRefName);

View File

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

View File

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

View File

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

View File

@ -32,7 +32,6 @@
#include <utility>
#include <functional>
using namespace std;
using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::langutil;
@ -92,7 +91,7 @@ Rules::Rules()
Y.setMatchGroup(6, 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.");
}
@ -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_matchGroups = &_matchGroups;
@ -135,9 +134,9 @@ AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const
return AssemblyItem(m_type, data(), _location);
}
string Pattern::toString() const
std::string Pattern::toString() const
{
stringstream s;
std::stringstream s;
switch (m_type)
{
case Operation:
@ -146,7 +145,7 @@ string Pattern::toString() const
break;
case Push:
if (m_data)
s << "PUSH " << hex << data();
s << "PUSH " << std::hex << data();
else
s << "PUSH ";
break;
@ -155,15 +154,15 @@ string Pattern::toString() const
break;
default:
if (m_data)
s << "t=" << dec << m_type << " d=" << hex << data();
s << "t=" << std::dec << m_type << " d=" << std::hex << data();
else
s << "t=" << dec << m_type << " d: nullptr";
s << "t=" << std::dec << m_type << " d: nullptr";
break;
}
if (!m_requireDataMatch)
s << " ~";
if (m_matchGroup)
s << "[" << dec << m_matchGroup << "]";
s << "[" << std::dec << m_matchGroup << "]";
s << "(";
for (Pattern const& p: m_arguments)
s << p.toString() << ", ";
@ -216,9 +215,9 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation c
arguments.emplace_back(arg, _location);
}
string ExpressionTemplate::toString() const
std::string ExpressionTemplate::toString() const
{
stringstream s;
std::stringstream s;
if (hasId)
s << id;
else

View File

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

View File

@ -30,7 +30,6 @@
#include <vector>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::util;
@ -50,7 +49,7 @@ DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _me
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().
solAssert(componentMap().count("all") == 0, "");
@ -61,11 +60,11 @@ optional<DebugInfoSelection> DebugInfoSelection::fromString(string_view _input)
if (_input == "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(
vector<string> const& _componentNames,
std::optional<DebugInfoSelection> DebugInfoSelection::fromComponents(
std::vector<std::string> const& _componentNames,
bool _acceptWildcards
)
{
@ -75,16 +74,16 @@ optional<DebugInfoSelection> DebugInfoSelection::fromComponents(
for (auto const& component: _componentNames)
{
if (component == "*")
return (_acceptWildcards ? make_optional(DebugInfoSelection::All()) : nullopt);
return (_acceptWildcards ? std::make_optional(DebugInfoSelection::All()) : std::nullopt);
if (!selection.enable(component))
return nullopt;
return std::nullopt;
}
return selection;
}
bool DebugInfoSelection::enable(string _component)
bool DebugInfoSelection::enable(std::string _component)
{
auto memberIt = componentMap().find(boost::trim_copy(_component));
if (memberIt == componentMap().end())
@ -146,9 +145,9 @@ bool DebugInfoSelection::operator==(DebugInfoSelection const& _other) const noex
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())
if (_selection.*member)
selectedComponentNames.push_back(name);

View File

@ -25,7 +25,6 @@
#include <liblangutil/SourceLocation.h>
#include <memory>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
@ -37,7 +36,7 @@ ErrorReporter& ErrorReporter::operator=(ErrorReporter const& _errorReporter)
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);
}
@ -45,7 +44,7 @@ void ErrorReporter::warning(ErrorId _error, string const& _description)
void ErrorReporter::warning(
ErrorId _error,
SourceLocation const& _location,
string const& _description
std::string const& _description
)
{
error(_error, Error::Type::Warning, _location, _description);
@ -54,27 +53,27 @@ void ErrorReporter::warning(
void ErrorReporter::warning(
ErrorId _error,
SourceLocation const& _location,
string const& _description,
std::string const& _description,
SecondarySourceLocation const& _secondaryLocation
)
{
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))
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))
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
@ -89,7 +88,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
m_warningCount++;
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)
return true;
@ -99,7 +98,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
m_infoCount++;
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)
return true;
@ -110,7 +109,7 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
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());
}
}
@ -118,13 +117,13 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
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);
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);
BOOST_THROW_EXCEPTION(FatalError());
@ -140,7 +139,7 @@ void ErrorReporter::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,
@ -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,
@ -170,7 +169,7 @@ void ErrorReporter::fatalDeclarationError(ErrorId _error, SourceLocation const&
_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,
@ -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(
_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,
@ -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,
@ -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,
@ -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(
_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(
_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,
@ -256,13 +255,13 @@ void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const&
void ErrorReporter::info(
ErrorId _error,
SourceLocation const& _location,
string const& _description
std::string const& _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);
}

View File

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

View File

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

View File

@ -25,7 +25,6 @@
#include <liblangutil/Scanner.h>
#include <liblangutil/ErrorReporter.h>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
@ -44,7 +43,7 @@ Token ParserBase::peekNextToken() const
return m_scanner->peekNextToken();
}
string ParserBase::currentLiteral() const
std::string ParserBase::currentLiteral() const
{
return m_scanner->currentLiteral();
}
@ -54,7 +53,7 @@ Token ParserBase::advance()
return m_scanner->next();
}
string ParserBase::tokenName(Token _token)
std::string ParserBase::tokenName(Token _token)
{
if (_token == Token::Identifier)
return "identifier";
@ -75,56 +74,10 @@ void ParserBase::expectToken(Token _value, bool _advance)
{
Token tok = m_scanner->currentToken();
if (tok != _value)
{
string const expectedToken = ParserBase::tokenName(_value);
if (m_parserErrorRecovery)
parserError(6635_error, "Expected " + expectedToken + " but got " + tokenName(tok));
else
fatalParserError(2314_error, "Expected " + expectedToken + " but got " + tokenName(tok));
// Do not advance so that recovery can sync or make use of the current token.
// This is especially useful if the expected token
// is the only one that is missing and is at the end of a construct.
// "{ ... ; }" is such an example.
// ^
_advance = false;
}
if (_advance)
advance();
}
void ParserBase::expectTokenOrConsumeUntil(Token _value, 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;
}
fatalParserError(
2314_error,
"Expected " + ParserBase::tokenName(_value) + " but got " + tokenName(tok)
);
if (_advance)
advance();
}
@ -142,32 +95,32 @@ void ParserBase::decreaseRecursionDepth()
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);
}
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);
}
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);
}
void ParserBase::parserError(ErrorId _error, string const& _description)
void ParserBase::parserError(ErrorId _error, std::string const& _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);
}
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);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -25,14 +25,13 @@
using namespace solidity;
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"
enum SrcElem: size_t { Start, Length, Index };
vector<string> pos;
std::vector<std::string> pos;
boost::algorithm::split(pos, _input, boost::is_any_of(":"));

View File

@ -24,7 +24,6 @@
#include <cmath>
#include <variant>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
@ -36,7 +35,7 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
{
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 : "");
std::vector<SourceReference> secondary;
@ -45,7 +44,7 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
for (auto const& info: secondaryLocation->infos)
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(
@ -78,7 +77,7 @@ SourceReference SourceReferenceExtractor::extract(
LineColumn end = charStream.translatePositionToLineColumn(_location->end);
bool const isMultiline = start.line != end.line;
string line = charStream.lineAtPosition(_location->start);
std::string line = charStream.lineAtPosition(_location->start);
int locationLength =
isMultiline ?
@ -88,7 +87,7 @@ SourceReference SourceReferenceExtractor::extract(
if (locationLength > 150)
{
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);
end.column = start.column + 75;
locationLength = 75;
@ -98,9 +97,9 @@ SourceReference SourceReferenceExtractor::extract(
{
int const len = static_cast<int>(line.length());
line = line.substr(
static_cast<size_t>(max(0, start.column - 35)),
static_cast<size_t>(min(start.column, 35)) + static_cast<size_t>(
min(locationLength + 35, len - start.column)
static_cast<size_t>(std::max(0, start.column - 35)),
static_cast<size_t>(std::min(start.column, 35)) + static_cast<size_t>(
std::min(locationLength + 35, len - start.column)
)
);
if (start.column + locationLength + 35 < len)
@ -119,7 +118,7 @@ SourceReference SourceReferenceExtractor::extract(
interest,
isMultiline,
line,
min(start.column, static_cast<int>(line.length())),
min(end.column, static_cast<int>(line.length()))
std::min(start.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 <variant>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::util;
@ -114,15 +113,15 @@ void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref)
return; // No line available, nothing else to print
}
string line = std::to_string(_ref.position.line + 1); // one-based line number as string
string leftpad = string(line.size(), ' ');
std::string line = std::to_string(_ref.position.line + 1); // one-based line number as string
std::string leftpad = std::string(line.size(), ' ');
// line 0: source name
m_stream << leftpad;
frameColored() << "-->";
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())
return;

View File

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

View File

@ -46,8 +46,6 @@
#include <map>
using namespace std;
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)
{
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)
{
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)
{
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(
_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)
{
solAssert(
_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
@ -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
// and keywords to be put inside the keywords variable.
#define KEYWORD(name, string, precedence) {string, Token::name},
#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 TOKEN
auto it = keywords.find(_name);
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));
}
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`.
// 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.
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);
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);
int m = parseSize(positionM, positionX);
Token keyword = keywordByName(baseType);
if (keyword == Token::Bytes)
{
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)
{
if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end())
{
if (keyword == Token::UInt)
return make_tuple(Token::UIntM, m, 0);
return std::make_tuple(Token::UIntM, m, 0);
else
return make_tuple(Token::IntM, m, 0);
return std::make_tuple(Token::IntM, m, 0);
}
}
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
) {
if (keyword == Token::UFixed)
return make_tuple(Token::UFixedMxN, m, n);
return std::make_tuple(Token::UFixedMxN, m, n);
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. */ \
T(Leave, "leave", 0) \
\
T(NonExperimentalEnd, nullptr, 0) /* used as non-experimental enum end marker */ \
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
\
@ -323,6 +325,39 @@ namespace TokenTraits
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex;
}
constexpr bool isExperimentalSolidityKeyword(Token token)
{
return
token == Token::Assembly ||
token == Token::Contract ||
token == Token::External ||
token == Token::Fallback ||
token == Token::Pragma ||
token == Token::Import ||
token == Token::As ||
token == Token::Function ||
token == Token::Let ||
token == Token::Return ||
token == Token::Type ||
token == Token::If ||
token == Token::Else ||
token == Token::Do ||
token == Token::While ||
token == Token::For ||
token == Token::Continue ||
token == Token::Break;
// TODO: see isExperimentalSolidityKeyword below
// || (token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd);
}
constexpr bool isExperimentalSolidityOnlyKeyword(Token)
{
// TODO: use token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd
// as soon as other experimental tokens are added. For now the comparison generates
// a warning from clang because it is always false.
return false;
}
bool isYulKeyword(std::string const& _literal);
Token AssignmentToBinaryOp(Token op);

View File

@ -31,20 +31,19 @@
#include <memory>
#include <stdexcept>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
using namespace solidity::smtutil;
CHCSmtLib2Interface::CHCSmtLib2Interface(
map<h256, string> const& _queryResponses,
std::map<h256, std::string> const& _queryResponses,
ReadCallback::Callback _smtCallback,
SMTSolverChoice _enabledSolvers,
optional<unsigned> _queryTimeout
std::optional<unsigned> _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_smtCallback(_smtCallback),
m_enabledSolvers(_enabledSolvers)
@ -66,8 +65,8 @@ void CHCSmtLib2Interface::registerRelation(Expression const& _expr)
smtAssert(_expr.sort->kind == Kind::Function);
if (!m_variables.count(_expr.name))
{
auto fSort = dynamic_pointer_cast<FunctionSort>(_expr.sort);
string domain = toSmtLibSort(fSort->domain);
auto fSort = std::dynamic_pointer_cast<FunctionSort>(_expr.sort);
std::string domain = toSmtLibSort(fSort->domain);
// Relations are predicates which have implicit codomain Bool.
m_variables.insert(_expr.name);
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);
string response = querySolver(query);
std::string query = dumpQuery(_block);
std::string response = querySolver(query);
CheckResult result;
// TODO proper parsing
@ -108,7 +107,7 @@ tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> CHCSmtLib2Interface
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);
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))
m_sortNames[&_sort] = m_smtlib2->toSmtLibSort(_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)
ssort += toSmtLibSort(*sort) + " ";
ssort += ")";
return ssort;
}
string CHCSmtLib2Interface::forall()
std::string CHCSmtLib2Interface::forall()
{
string vars("(");
std::string vars("(");
for (auto const& [name, sort]: m_smtlib2->variables())
{
solAssert(sort, "");
@ -149,17 +148,17 @@ string CHCSmtLib2Interface::forall()
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->kind == Kind::Function);
// TODO Use domain and codomain as key as well
if (!m_variables.count(_name))
{
auto fSort = dynamic_pointer_cast<FunctionSort>(_sort);
auto fSort = std::dynamic_pointer_cast<FunctionSort>(_sort);
smtAssert(fSort->codomain);
string domain = toSmtLibSort(fSort->domain);
string codomain = toSmtLibSort(*fSort->codomain);
std::string domain = toSmtLibSort(fSort->domain);
std::string codomain = toSmtLibSort(*fSort->codomain);
m_variables.insert(_name);
write(
"(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";
}
string CHCSmtLib2Interface::querySolver(string const& _input)
std::string CHCSmtLib2Interface::querySolver(std::string const& _input)
{
util::h256 inputHash = util::keccak256(_input);
if (m_queryResponses.count(inputHash))
@ -212,7 +211,7 @@ std::string CHCSmtLib2Interface::dumpQuery(Expression const& _expr)
std::string CHCSmtLib2Interface::createHeaderAndDeclarations() {
std::stringstream s;
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;
for (auto const& decl: m_smtlib2->userSorts() | ranges::views::values)

View File

@ -23,12 +23,11 @@
#include <cvc4/util/bitvector.h>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::smtutil;
CVC4Interface::CVC4Interface(optional<unsigned> _queryTimeout):
CVC4Interface::CVC4Interface(std::optional<unsigned> _queryTimeout):
SolverInterface(_queryTimeout),
m_solver(&m_context)
{
@ -56,7 +55,7 @@ void CVC4Interface::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, "");
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;
vector<string> values;
std::vector<std::string> values;
try
{
switch (m_solver.checkSat().isSat())
@ -119,7 +118,7 @@ pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const&
values.clear();
}
return make_pair(result, values);
return std::make_pair(result, values);
}
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))
return m_variables.at(_expr.name);
vector<CVC4::Expr> arguments;
std::vector<CVC4::Expr> arguments;
for (auto const& arg: _expr.arguments)
arguments.push_back(toCVC4Expr(arg));
try
{
string const& n = _expr.name;
std::string const& n = _expr.name;
// Function application
if (!arguments.empty() && m_variables.count(_expr.name))
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);
else if (n == "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));
else
try
@ -224,7 +223,7 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
}
else if (n == "bv2int")
{
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort);
auto intSort = std::dynamic_pointer_cast<IntSort>(_expr.sort);
smtAssert(intSort, "");
auto nat = m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, arguments[0]);
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]);
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, "");
return m_context.mkConst(CVC4::ArrayStoreAll(cvc4Sort(*sortSort->inner), arguments[1]));
}
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, "");
CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components));
CVC4::Datatype const& dt = tt.getDatatype();
@ -270,7 +269,7 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
}
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, "");
CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components));
CVC4::Datatype const& dt = tt.getDatatype();
@ -328,9 +327,9 @@ CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort)
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)
cvc4Sorts.push_back(cvc4Sort(*_sort));
return cvc4Sorts;

View File

@ -33,16 +33,15 @@
#include <string>
#include <utility>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
using namespace solidity::smtutil;
SMTLib2Interface::SMTLib2Interface(
map<h256, string> _queryResponses,
std::map<h256, std::string> _queryResponses,
ReadCallback::Callback _smtCallback,
optional<unsigned> _queryTimeout
std::optional<unsigned> _queryTimeout
):
SolverInterface(_queryTimeout),
m_queryResponses(std::move(_queryResponses)),
@ -59,7 +58,7 @@ void SMTLib2Interface::reset()
m_userSorts.clear();
write("(set-option :produce-models true)");
if (m_queryTimeout)
write("(set-option :timeout " + to_string(*m_queryTimeout) + ")");
write("(set-option :timeout " + std::to_string(*m_queryTimeout) + ")");
write("(set-logic ALL)");
}
@ -74,7 +73,7 @@ void SMTLib2Interface::pop()
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, "");
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->kind == Kind::Function, "");
// TODO Use domain and codomain as key as well
if (!m_variables.count(_name))
{
auto const& fSort = dynamic_pointer_cast<FunctionSort>(_sort);
string domain = toSmtLibSort(fSort->domain);
string codomain = toSmtLibSort(*fSort->codomain);
auto const& fSort = std::dynamic_pointer_cast<FunctionSort>(_sort);
std::string domain = toSmtLibSort(fSort->domain);
std::string codomain = toSmtLibSort(*fSort->codomain);
m_variables.emplace(_name, _sort);
write(
"(declare-fun |" +
@ -114,9 +113,9 @@ void SMTLib2Interface::addAssertion(Expression const& _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") +
checkSatAndGetValuesCommand(_expressionsToEvaluate)
);
@ -132,13 +131,13 @@ pair<CheckResult, vector<string>> SMTLib2Interface::check(vector<Expression> con
else
result = CheckResult::ERROR;
vector<string> values;
std::vector<std::string> values;
if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty())
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())
return _expr.name;
@ -148,16 +147,16 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
{
size_t size = std::stoul(_expr.arguments[1].name);
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.
sexpr += string("ite ") +
sexpr += std::string("ite ") +
"(>= " + arg + " 0) " +
"(" + int2bv + " " + arg + ") " +
"(bvneg (" + int2bv + " (- " + arg + ")))";
}
else if (_expr.name == "bv2int")
{
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort);
auto intSort = std::dynamic_pointer_cast<IntSort>(_expr.sort);
smtAssert(intSort, "");
auto arg = toSExpr(_expr.arguments.front());
@ -166,13 +165,13 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
if (!intSort->isSigned)
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, "");
auto size = to_string(bvSort->size);
auto pos = to_string(bvSort->size - 1);
auto size = std::to_string(bvSort->size);
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.
sexpr += string("ite ") +
sexpr += std::string("ite ") +
"(= ((_ extract " + pos + " " + pos + ")" + arg + ") #b0) " +
nat + " " +
"(- (bv2nat (bvneg " + arg + ")))";
@ -182,7 +181,7 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
smtAssert(_expr.arguments.size() == 2, "");
auto sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments.at(0).sort);
smtAssert(sortSort, "");
auto arraySort = dynamic_pointer_cast<ArraySort>(sortSort->inner);
auto arraySort = std::dynamic_pointer_cast<ArraySort>(sortSort->inner);
smtAssert(arraySort, "");
sexpr += "(as const " + toSmtLibSort(*arraySort) + ") ";
sexpr += toSExpr(_expr.arguments.at(1));
@ -190,14 +189,14 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
else if (_expr.name == "tuple_get")
{
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);
smtAssert(index < tupleSort->members.size(), "");
sexpr += "|" + tupleSort->members.at(index) + "| " + toSExpr(_expr.arguments.at(0));
}
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, "");
sexpr += "|" + tupleSort->name + "|";
for (auto const& arg: _expr.arguments)
@ -213,7 +212,7 @@ string SMTLib2Interface::toSExpr(Expression const& _expr)
return sexpr;
}
string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
std::string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
{
switch (_sort.kind)
{
@ -222,7 +221,7 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
case Kind::Bool:
return "Bool";
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:
{
auto const& arraySort = dynamic_cast<ArraySort const&>(_sort);
@ -232,11 +231,11 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort)
case Kind::Tuple:
{
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; };
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(), "");
for (unsigned i = 0; i < tupleSort.members.size(); ++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)
ssort += toSmtLibSort(*sort) + " ";
ssort += ")";
return ssort;
}
void SMTLib2Interface::write(string _data)
void SMTLib2Interface::write(std::string _data)
{
smtAssert(!m_accumulatedOutput.empty(), "");
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())
command = "(check-sat)\n";
else
@ -279,22 +278,22 @@ string SMTLib2Interface::checkSatAndGetValuesCommand(vector<Expression> const& _
{
auto const& e = _expressionsToEvaluate.at(i);
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 += "(assert (= |EVALEXPR_" + to_string(i) + "| " + toSExpr(e) + "))\n";
command += "(declare-const |EVALEXPR_" + std::to_string(i) + "| " + (e.sort->kind == Kind::Int ? "Int" : "Bool") + ")\n";
command += "(assert (= |EVALEXPR_" + std::to_string(i) + "| " + toSExpr(e) + "))\n";
}
command += "(check-sat)\n";
command += "(get-value (";
for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
command += "|EVALEXPR_" + to_string(i) + "| ";
command += "|EVALEXPR_" + std::to_string(i) + "| ";
command += "))\n";
}
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)
{
auto valStart = find(_start, _end, ' ');
@ -308,7 +307,7 @@ vector<string> SMTLib2Interface::parseValues(string::const_iterator _start, stri
return values;
}
string SMTLib2Interface::querySolver(string const& _input)
std::string SMTLib2Interface::querySolver(std::string const& _input)
{
h256 inputHash = keccak256(_input);
if (m_queryResponses.count(inputHash))
@ -323,7 +322,7 @@ string SMTLib2Interface::querySolver(string const& _input)
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") +
checkSatAndGetValuesCommand(_expressionsToEvaluate);

View File

@ -26,31 +26,30 @@
#endif
#include <libsmtutil/SMTLib2Interface.h>
using namespace std;
using namespace solidity;
using namespace solidity::util;
using namespace solidity::frontend;
using namespace solidity::smtutil;
SMTPortfolio::SMTPortfolio(
map<h256, string> _smtlib2Responses,
std::map<h256, std::string> _smtlib2Responses,
frontend::ReadCallback::Callback _smtCallback,
[[maybe_unused]] SMTSolverChoice _enabledSolvers,
optional<unsigned> _queryTimeout,
std::optional<unsigned> _queryTimeout,
bool _printQuery
):
SolverInterface(_queryTimeout)
{
solAssert(!_printQuery || _enabledSolvers == smtutil::SMTSolverChoice::SMTLIB2(), "Only SMTLib2 solver can be enabled to print queries");
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
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
#ifdef HAVE_CVC4
if (_enabledSolvers.cvc4)
m_solvers.emplace_back(make_unique<CVC4Interface>(m_queryTimeout));
m_solvers.emplace_back(std::make_unique<CVC4Interface>(m_queryTimeout));
#endif
}
@ -72,7 +71,7 @@ void SMTPortfolio::pop()
s->pop();
}
void SMTPortfolio::declareVariable(string const& _name, SortPointer const& _sort)
void SMTPortfolio::declareVariable(std::string const& _name, SortPointer const& _sort)
{
smtAssert(_sort, "");
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.
*/
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;
vector<string> finalValues;
std::vector<std::string> finalValues;
for (auto const& s: m_solvers)
{
CheckResult result;
vector<string> values;
std::vector<std::string> values;
tie(result, values) = s->check(_expressionsToEvaluate);
if (solverAnswered(result))
{
@ -140,10 +139,10 @@ pair<CheckResult, vector<string>> SMTPortfolio::check(vector<Expression> const&
else if (result == CheckResult::UNKNOWN && lastResult == CheckResult::ERROR)
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
// SmtLib2Interface is in position 0, if enabled.
@ -158,7 +157,7 @@ bool SMTPortfolio::solverAnswered(CheckResult result)
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
// SmtLib2Interface is in position 0, if enabled.

View File

@ -19,22 +19,20 @@
#include <libsmtutil/Sorts.h>
using namespace std;
namespace solidity::smtutil
{
shared_ptr<Sort> const SortProvider::boolSort{make_shared<Sort>(Kind::Bool)};
shared_ptr<IntSort> const SortProvider::uintSort{make_shared<IntSort>(false)};
shared_ptr<IntSort> const SortProvider::sintSort{make_shared<IntSort>(true)};
std::shared_ptr<Sort> const SortProvider::boolSort{std::make_shared<Sort>(Kind::Bool)};
std::shared_ptr<IntSort> const SortProvider::uintSort{std::make_shared<IntSort>(false)};
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)
return sintSort;
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 <stack>
using namespace std;
using namespace solidity;
using namespace solidity::smtutil;
Z3CHCInterface::Z3CHCInterface(optional<unsigned> _queryTimeout):
Z3CHCInterface::Z3CHCInterface(std::optional<unsigned> _queryTimeout):
CHCSolverInterface(_queryTimeout),
m_z3Interface(make_unique<Z3Interface>(m_queryTimeout)),
m_z3Interface(std::make_unique<Z3Interface>(m_queryTimeout)),
m_context(m_z3Interface->context()),
m_solver(*m_context)
{
Z3_get_version(
&get<0>(m_version),
&get<1>(m_version),
&get<2>(m_version),
&get<3>(m_version)
&std::get<0>(m_version),
&std::get<1>(m_version),
&std::get<2>(m_version),
&std::get<3>(m_version)
);
// These need to be set globally.
@ -51,7 +50,7 @@ Z3CHCInterface::Z3CHCInterface(optional<unsigned> _queryTimeout):
setSpacerOptions();
}
void Z3CHCInterface::declareVariable(string const& _name, SortPointer const& _sort)
void Z3CHCInterface::declareVariable(std::string const& _name, SortPointer const& _sort)
{
smtAssert(_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));
}
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);
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;
try
@ -90,7 +89,7 @@ tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> Z3CHCInterface::que
result = CheckResult::SATISFIABLE;
// z3 version 4.8.8 modified Spacer to also return
// 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();
return {result, Expression(true), cexGraph(proof)};
@ -113,7 +112,7 @@ tuple<CheckResult, Expression, CHCSolverInterface::CexGraph> Z3CHCInterface::que
}
catch (z3::exception const& _err)
{
set<string> msgs{
std::set<std::string> msgs{
/// Resource limit (rlimit) exhausted.
"max. resource limit exceeded",
/// User given timeout exhausted.
@ -178,13 +177,13 @@ CHCSolverInterface::CexGraph Z3CHCInterface::cexGraph(z3::expr const& _proof)
CexGraph graph;
stack<z3::expr> proofStack;
std::stack<z3::expr> proofStack;
proofStack.push(_proof.arg(0));
auto const& root = proofStack.top();
graph.nodes.emplace(root.id(), m_z3Interface->fromZ3Expr(fact(root)));
set<unsigned> visited;
std::set<unsigned> visited;
visited.insert(root.id());
while (!proofStack.empty())
@ -227,16 +226,16 @@ z3::expr Z3CHCInterface::fact(z3::expr const& _node)
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(), "");
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(), "");
vector<string> args;
std::vector<std::string> args;
for (unsigned i = 0; i < _predicate.num_args(); ++i)
args.emplace_back(_predicate.arg(i).to_string());
return args;

View File

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

View File

@ -27,7 +27,6 @@
#endif
#include <dlfcn.h>
using namespace std;
using namespace solidity;
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.");
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;
}
@ -59,7 +58,7 @@ bool Z3Loader::available() const
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);
}

View File

@ -32,7 +32,6 @@
#include "license.h"
using namespace std;
using namespace solidity;
using namespace solidity::util;
@ -42,21 +41,21 @@ using solidity::frontend::StandardCompiler;
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().
static list<string> solidityAllocations;
static std::list<std::string> solidityAllocations;
/// Find the equivalent to @p _data in the list of allocations of solidity_alloc(),
/// removes it from the list and returns its value.
///
/// If any invalid argument is being passed, it is considered a programming error
/// 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)
if (iter->data() == _data)
{
string chunk = std::move(*iter);
std::string chunk = std::move(*iter);
solidityAllocations.erase(iter);
return chunk;
}
@ -64,11 +63,11 @@ string takeOverAllocation(char const* _data)
abort();
}
/// Resizes a std::string to the proper length based on the occurrence of a zero terminator.
void truncateCString(string& _data)
/// Resizes a std::std::string to the proper length based on the occurrence of a zero terminator.
void truncateCString(std::string& _data)
{
size_t pos = _data.find('\0');
if (pos != string::npos)
if (pos != std::string::npos)
_data.resize(pos);
}
@ -77,7 +76,7 @@ ReadCallback::Callback wrapReadCallback(CStyleReadFileCallback _readCallback, vo
ReadCallback::Callback readCallback;
if (_readCallback)
{
readCallback = [=](string const& _kind, string const& _data)
readCallback = [=](std::string const& _kind, std::string const& _data)
{
char* contents_c = nullptr;
char* error_c = nullptr;
@ -106,7 +105,7 @@ ReadCallback::Callback wrapReadCallback(CStyleReadFileCallback _readCallback, vo
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));
return compiler.compile(std::move(_input));
@ -118,7 +117,7 @@ extern "C"
{
extern char const* solidity_license() noexcept
{
static string fullLicenseText = otherLicenses + licenseText;
static std::string fullLicenseText = otherLicenses + licenseText;
return fullLicenseText.c_str();
}

View File

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

View File

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

View File

@ -32,7 +32,6 @@
#include <range/v3/view/reverse.hpp>
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend;
@ -49,10 +48,10 @@ bool hasEqualExternalCallableParameters(T const& _a, B const& _b)
}
template<typename T>
map<ASTString, vector<T const*>> filterDeclarations(
map<ASTString, vector<Declaration const*>> const& _declarations)
std::map<ASTString, std::vector<T const*>> filterDeclarations(
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* declaration: overloads)
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
/// 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* fallback = 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
/// 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 (EventDefinition const* event: contract->events())
events[event->name()].push_back(event);
@ -195,12 +194,12 @@ void ContractLevelChecker::checkReceiveFunction(ContractDefinition const& _contr
}
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)
{
vector<T> const& overloads = it.second;
set<size_t> reported;
std::vector<T> const& overloads = it.second;
std::set<size_t> reported;
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
{
SecondarySourceLocation ssl;
@ -228,15 +227,15 @@ void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const
if (ssl.infos.size() > 0)
{
ErrorId error;
string message;
if constexpr (is_same_v<T, FunctionDefinition const*>)
std::string message;
if constexpr (std::is_same_v<T, FunctionDefinition const*>)
{
error = 1686_error;
message = "Function with same name and parameter types defined twice.";
}
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;
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
// 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)
{
@ -323,7 +322,7 @@ void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _c
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.
for (ContractDefinition const* contract: bases)
@ -430,7 +429,7 @@ void ContractLevelChecker::annotateBaseConstructorArguments(
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 (FunctionDefinition const* f: contract->definedFunctions())
@ -467,7 +466,7 @@ void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _c
void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contract)
{
set<util::FixedHash<4>> hashes;
std::set<util::FixedHash<4>> hashes;
for (auto const& it: _contract.interfaceFunctionList())
{
util::FixedHash<4> const& hash = it.first;
@ -475,7 +474,7 @@ void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contra
m_errorReporter.fatalTypeError(
1860_error,
_contract.location(),
string("Function signature hash collision for ") + it.second->externalSignature()
std::string("Function signature hash collision for ") + it.second->externalSignature()
);
hashes.insert(hash);
}

View File

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

View File

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

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