Merge branch 'develop' into patch-2

This commit is contained in:
Markus Osterlund / robriks 2023-09-13 15:58:12 -04:00 committed by GitHub
commit c43c3c3a3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
587 changed files with 12601 additions and 11095 deletions

View File

@ -179,47 +179,199 @@ commands:
paths: paths:
- << parameters.install_path >> - << parameters.install_path >>
defaults:
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Build Templates # Build Commands
- setup_prerelease_commit_hash: &setup_prerelease_commit_hash setup_prerelease_commit_hash:
steps:
- run:
name: Store commit hash and prerelease name: Store commit hash and prerelease
command: | command: |
if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi 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 echo -n "$CIRCLE_SHA1" > commit_hash.txt
- run_build: &run_build run_build:
steps:
- run:
name: Build name: Build
command: scripts/ci/build.sh command: scripts/ci/build.sh
- run_build_ossfuzz: &run_build_ossfuzz run_build_ossfuzz:
steps:
- run:
name: Build_ossfuzz name: Build_ossfuzz
command: scripts/ci/build_ossfuzz.sh command: scripts/ci/build_ossfuzz.sh
- run_proofs: &run_proofs run_proofs:
steps:
- run:
name: Correctness proofs for optimization rules name: Correctness proofs for optimization rules
command: scripts/run_proofs.sh command: scripts/run_proofs.sh
- run_soltest: &run_soltest run_soltest:
steps:
- run:
name: soltest name: soltest
no_output_timeout: 30m no_output_timeout: 30m
command: ./.circleci/soltest.sh command: .circleci/soltest.sh
- run_soltest_all: &run_soltest_all run_soltest_all:
steps:
- run:
name: soltest_all name: soltest_all
no_output_timeout: 30m no_output_timeout: 30m
command: ./.circleci/soltest_all.sh command: .circleci/soltest_all.sh
- run_cmdline_tests: &run_cmdline_tests run_cmdline_tests:
steps:
- run:
name: command line tests name: command line tests
no_output_timeout: 30m no_output_timeout: 30m
command: .circleci/parallel_cli_tests.py command: .circleci/parallel_cli_tests.py
- run_docs_pragma_min_version: &run_docs_pragma_min_version run_docs_pragma_min_version:
steps:
- run:
name: docs pragma version check name: docs pragma version check
command: ./scripts/docs_version_pragma_check.sh command: scripts/docs_version_pragma_check.sh
# --------------------------------------------------------------------------
# Artifact Commands
store_artifacts_solc:
description: Store compiled solc executable as artifact
steps:
- store_artifacts:
path: build/solc/solc
destination: solc
store_artifacts_yul_phaser:
steps:
- store_artifacts:
path: build/tools/yul-phaser
destination: yul-phaser
persist_executables_to_workspace:
description: Persist compiled target executables to workspace
steps:
- persist_to_workspace:
root: build
paths:
- solc/solc
- test/soltest
- test/tools/solfuzzer
persist_executables_to_workspace_osx:
description: Persist compiled target executables to workspace on macOS
steps:
- persist_to_workspace:
root: .
paths:
- build/solc/solc
- build/test/soltest
- build/test/tools/solfuzzer
persist_ossfuzz_executables_to_workspace:
description: Persist compiled OSSFUZZ executables to workspace
steps:
- persist_to_workspace:
root: build
paths:
- test/tools/ossfuzz/abiv2_proto_ossfuzz
- test/tools/ossfuzz/abiv2_isabelle_ossfuzz
- test/tools/ossfuzz/const_opt_ossfuzz
- test/tools/ossfuzz/solc_mutator_ossfuzz
- test/tools/ossfuzz/solc_ossfuzz
- test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
- test/tools/ossfuzz/strictasm_diff_ossfuzz
- test/tools/ossfuzz/strictasm_opt_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
- test/tools/ossfuzz/yul_proto_ossfuzz
- test/tools/ossfuzz/sol_proto_ossfuzz
store_artifacts_test_results:
description: Store test output dir as artifact
steps:
- store_artifacts:
path: test_results/
destination: test_results/
# --------------------------------------------------------------------------
# Complex Build Commands
soltest:
steps:
- checkout
- attach_workspace:
at: build
# NOTE: Different build jobs produce different soltest executables (release/debug,
# clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the
# attached workspace and we only see the items added to the workspace by jobs we depend on.
- run_soltest
- store_test_results:
path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr
test_lsp:
steps:
- checkout
- attach_workspace:
at: build
- run:
name: Install dependencies
command: pip install --user deepdiff colorama
- run:
name: Executing solc LSP test suite
command: test/lsp.py build/solc/solc --non-interactive
- matrix_notify_failure_unless_pr
build:
steps:
- checkout
- run_build
- store_artifacts_solc
- store_artifacts_yul_phaser
- persist_executables_to_workspace
- matrix_notify_failure_unless_pr
soltest_all:
steps:
- checkout
- attach_workspace:
at: build
- run_soltest_all
- store_test_results:
path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr
cmdline_tests:
steps:
- checkout
- attach_workspace:
at: build
- run_cmdline_tests
- store_test_results:
path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr
install_dependencies_osx:
steps:
# FIXME: We used to cache dependencies on macOS but now it takes longer than just installing
# them each time. See https://github.com/ethereum/solidity/issues/12925.
- run:
name: Install build dependencies
command: .circleci/osx_install_dependencies.sh
defaults:
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Matrix templates # Matrix templates
@ -241,122 +393,6 @@ defaults:
- via-ir-no-optimize - via-ir-no-optimize
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Artifacts Templates
# compiled solc executable target
- artifacts_solc: &artifacts_solc
path: build/solc/solc
destination: solc
# windows artifacts
- artifact_solc_windows: &artifact_solc_windows
path: upload/
- artifact_yul_phaser: &artifact_yul_phaser
path: build/tools/yul-phaser
destination: yul-phaser
# compiled executable targets
- artifacts_executables: &artifacts_executables
root: build
paths:
- solc/solc
- test/soltest
- test/tools/solfuzzer
# compiled OSSFUZZ targets
- artifacts_executables_ossfuzz: &artifacts_executables_ossfuzz
root: build
paths:
- test/tools/ossfuzz/abiv2_proto_ossfuzz
- test/tools/ossfuzz/abiv2_isabelle_ossfuzz
- test/tools/ossfuzz/const_opt_ossfuzz
- test/tools/ossfuzz/solc_mutator_ossfuzz
- test/tools/ossfuzz/solc_ossfuzz
- test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
- test/tools/ossfuzz/strictasm_diff_ossfuzz
- test/tools/ossfuzz/strictasm_opt_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
- test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
- test/tools/ossfuzz/yul_proto_ossfuzz
- test/tools/ossfuzz/sol_proto_ossfuzz
# test result output directory
- artifacts_test_results: &artifacts_test_results
path: test_results/
destination: test_results/
# --------------------------------------------------------------------------
# Step Templates
# store_test_results helper
- store_test_results: &store_test_results
path: test_results/
- steps_soltest: &steps_soltest
steps:
- checkout
- attach_workspace:
at: build
# NOTE: Different build jobs produce different soltest executables (release/debug,
# clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the
# attached workspace and we only see the items added to the workspace by jobs we depend on.
- run: *run_soltest
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
- steps_test_lsp: &steps_test_lsp
steps:
- checkout
- attach_workspace:
at: build
- run:
name: Install dependencies
command: pip install --user deepdiff colorama
- run:
name: Executing solc LSP test suite
command: ./test/lsp.py ./build/solc/solc --non-interactive
- matrix_notify_failure_unless_pr
- steps_build: &steps_build
steps:
- checkout
- run: *run_build
- store_artifacts: *artifacts_solc
- store_artifacts: *artifact_yul_phaser
- persist_to_workspace: *artifacts_executables
- matrix_notify_failure_unless_pr
- steps_soltest_all: &steps_soltest_all
steps:
- checkout
- attach_workspace:
at: build
- run: *run_soltest_all
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
- steps_cmdline_tests: &steps_cmdline_tests
steps:
- checkout
- attach_workspace:
at: build
- run: *run_cmdline_tests
- store_test_results: *store_test_results
- store_artifacts: *artifacts_test_results
- matrix_notify_failure_unless_pr
- steps_install_dependencies_osx: &steps_install_dependencies_osx
steps:
# FIXME: We used to cache dependencies on macOS but now it takes longer than just installing
# them each time. See https://github.com/ethereum/solidity/issues/12925.
- run:
name: Install build dependencies
command: ./.circleci/osx_install_dependencies.sh
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Base Image Templates # Base Image Templates
@ -767,7 +803,11 @@ jobs:
pip install --user codespell pip install --user codespell
- run: - run:
name: Check spelling name: Check spelling
command: ~/.local/bin/codespell --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" --ignore-words ./scripts/codespell_whitelist.txt --exclude-file ./scripts/codespell_ignored_lines.txt command: |
~/.local/bin/codespell \
--skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" \
--ignore-words scripts/codespell_whitelist.txt \
--exclude-file scripts/codespell_ignored_lines.txt
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_docs_examples: chk_docs_examples:
@ -781,7 +821,7 @@ jobs:
command: sudo npm install -g solhint command: sudo npm install -g solhint
- run: - run:
name: Test Docs examples name: Test Docs examples
command: ./test/docsCodeStyle.sh command: test/docsCodeStyle.sh
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_coding_style: chk_coding_style:
@ -795,13 +835,13 @@ jobs:
sudo apt install -y shellcheck sudo apt install -y shellcheck
- run: - run:
name: Check for C++ coding style name: Check for C++ coding style
command: ./scripts/check_style.sh command: scripts/check_style.sh
- run: - run:
name: checking shell scripts name: checking shell scripts
command: ./scripts/chk_shellscripts/chk_shellscripts.sh command: scripts/chk_shellscripts/chk_shellscripts.sh
- run: - run:
name: Check for broken symlinks name: Check for broken symlinks
command: ./scripts/check_symlinks.sh command: scripts/check_symlinks.sh
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_errorcodes: chk_errorcodes:
@ -810,7 +850,7 @@ jobs:
- checkout - checkout
- run: - run:
name: Check for error codes name: Check for error codes
command: ./scripts/error_codes.py --check command: scripts/error_codes.py --check
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_pylint: chk_pylint:
@ -830,7 +870,7 @@ jobs:
- run: pylint --version - run: pylint --version
- run: - run:
name: Linting Python Scripts name: Linting Python Scripts
command: ./scripts/pylint_all.py command: scripts/pylint_all.py
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_antlr_grammar: chk_antlr_grammar:
@ -844,7 +884,7 @@ jobs:
sudo apt install -y openjdk-17-jdk sudo apt install -y openjdk-17-jdk
- run: - run:
name: Run tests name: Run tests
command: ./scripts/test_antlr_grammar.sh command: scripts/test_antlr_grammar.sh
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_buglist: chk_buglist:
@ -859,7 +899,7 @@ jobs:
npm install mktemp npm install mktemp
- run: - run:
name: Test buglist name: Test buglist
command: ./test/buglistTests.js command: test/buglistTests.js
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_proofs: chk_proofs:
@ -868,14 +908,14 @@ jobs:
- checkout - checkout
- install_python3: - install_python3:
packages: z3-solver packages: z3-solver
- run: *run_proofs - run_proofs
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
chk_docs_pragma_min_version: chk_docs_pragma_min_version:
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
steps: steps:
- checkout - checkout
- run: *run_docs_pragma_min_version - run_docs_pragma_min_version
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_ubu_pyscripts: t_ubu_pyscripts:
@ -901,7 +941,8 @@ jobs:
# this runs 2x faster on xlarge but takes 4x more resources (compared to medium). # this runs 2x faster on xlarge but takes 4x more resources (compared to medium).
# Enough other jobs depend on it that it's worth it though. # Enough other jobs depend on it that it's worth it though.
<<: *base_ubuntu2204_xlarge <<: *base_ubuntu2204_xlarge
<<: *steps_build steps:
- build
# x64 ASAN build, for testing for memory related bugs # x64 ASAN build, for testing for memory related bugs
b_ubu_asan: &b_ubu_asan b_ubu_asan: &b_ubu_asan
@ -911,14 +952,16 @@ jobs:
<<: *base_ubuntu2204_env <<: *base_ubuntu2204_env
CMAKE_OPTIONS: -DSANITIZE=address CMAKE_OPTIONS: -DSANITIZE=address
CMAKE_BUILD_TYPE: Release CMAKE_BUILD_TYPE: Release
<<: *steps_build steps:
- build
b_ubu_clang: &b_ubu_clang b_ubu_clang: &b_ubu_clang
<<: *base_ubuntu2204_clang_large <<: *base_ubuntu2204_clang_large
environment: environment:
<<: *base_ubuntu2204_clang_large_env <<: *base_ubuntu2204_clang_large_env
MAKEFLAGS: -j 10 MAKEFLAGS: -j 10
<<: *steps_build steps:
- build
b_ubu_san_clang: b_ubu_san_clang:
# This runs a bit faster on large and xlarge but on nightly efficiency matters more. # This runs a bit faster on large and xlarge but on nightly efficiency matters more.
@ -929,7 +972,8 @@ jobs:
environment: environment:
<<: *base_ubuntu2204_clang_env <<: *base_ubuntu2204_clang_env
CMAKE_OPTIONS: << parameters.cmake_options >> CMAKE_OPTIONS: << parameters.cmake_options >>
<<: *steps_build steps:
- build
b_ubu_force_release: &b_ubu_force_release b_ubu_force_release: &b_ubu_force_release
<<: *b_ubu <<: *b_ubu
@ -948,7 +992,7 @@ jobs:
CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON
steps: steps:
- checkout - checkout
- run: *run_build - run_build
- run: - run:
name: strip binary name: strip binary
command: strip build/solc/solc command: strip build/solc/solc
@ -971,8 +1015,8 @@ jobs:
CMAKE_BUILD_TYPE: Debug CMAKE_BUILD_TYPE: Debug
steps: steps:
- checkout - checkout
- run: *run_build - run_build
- persist_to_workspace: *artifacts_executables - persist_executables_to_workspace
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_ubu_codecov: t_ubu_codecov:
@ -991,11 +1035,11 @@ jobs:
- run: - run:
name: "Code Coverage: Syntax Tests" name: "Code Coverage: Syntax Tests"
command: codecov --flags syntax --gcov-root build command: codecov --flags syntax --gcov-root build
- run: *run_soltest - run_soltest
- run: - run:
name: "Coverage: All" name: "Coverage: All"
command: codecov --flags all --gcov-root build command: codecov --flags all --gcov-root build
- store_artifacts: *artifacts_test_results - store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
# Builds in C++20 mode and uses debug build in order to speed up. # Builds in C++20 mode and uses debug build in order to speed up.
@ -1009,16 +1053,16 @@ jobs:
MAKEFLAGS: -j 10 MAKEFLAGS: -j 10
steps: steps:
- checkout - checkout
- run: *run_build - run_build
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
b_ubu_ossfuzz: &b_ubu_ossfuzz b_ubu_ossfuzz: &b_ubu_ossfuzz
<<: *base_ubuntu_clang <<: *base_ubuntu_clang
steps: steps:
- checkout - checkout
- run: *setup_prerelease_commit_hash - setup_prerelease_commit_hash
- run: *run_build_ossfuzz - run_build_ossfuzz
- persist_to_workspace: *artifacts_executables_ossfuzz - persist_ossfuzz_executables_to_workspace
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_ubu_ossfuzz: &t_ubu_ossfuzz t_ubu_ossfuzz: &t_ubu_ossfuzz
@ -1033,8 +1077,9 @@ jobs:
git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus
mkdir -p test_results mkdir -p test_results
scripts/regressions.py -o test_results scripts/regressions.py -o test_results
- store_test_results: *store_test_results - store_test_results:
- store_artifacts: *artifacts_test_results path: test_results/
- store_artifacts_test_results
b_archlinux: b_archlinux:
<<: *base_archlinux_large <<: *base_archlinux_large
@ -1048,9 +1093,9 @@ jobs:
command: | command: |
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar
- checkout - checkout
- run: *run_build - run_build
- store_artifacts: *artifacts_solc - store_artifacts_solc
- persist_to_workspace: *artifacts_executables - persist_executables_to_workspace
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
b_osx: b_osx:
@ -1060,18 +1105,11 @@ jobs:
CMAKE_BUILD_TYPE: Release CMAKE_BUILD_TYPE: Release
steps: steps:
- checkout - checkout
- when: - install_dependencies_osx
condition: true - run_build
<<: *steps_install_dependencies_osx - store_artifacts_solc
- run: *run_build - store_artifacts_yul_phaser
- store_artifacts: *artifacts_solc - persist_executables_to_workspace_osx
- store_artifacts: *artifact_yul_phaser
- persist_to_workspace:
root: .
paths:
- build/solc/solc
- build/test/soltest
- build/test/tools/solfuzzer
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_osx_soltest: &t_osx_soltest t_osx_soltest: &t_osx_soltest
@ -1082,14 +1120,13 @@ jobs:
OPTIMIZE: 0 OPTIMIZE: 0
steps: steps:
- checkout - checkout
- when: - install_dependencies_osx
condition: true
<<: *steps_install_dependencies_osx
- attach_workspace: - attach_workspace:
at: . at: .
- run: *run_soltest - run_soltest
- store_test_results: *store_test_results - store_test_results:
- store_artifacts: *artifacts_test_results path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
t_osx_cli: t_osx_cli:
@ -1097,13 +1134,11 @@ jobs:
parallelism: 7 # Should match number of tests in .circleci/cli.sh parallelism: 7 # Should match number of tests in .circleci/cli.sh
steps: steps:
- checkout - checkout
- when: - install_dependencies_osx
condition: true
<<: *steps_install_dependencies_osx
- attach_workspace: - attach_workspace:
at: . at: .
- run: *run_cmdline_tests - run_cmdline_tests
- store_artifacts: *artifacts_test_results - store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
b_ems: b_ems:
@ -1134,10 +1169,10 @@ jobs:
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
steps: steps:
- checkout - checkout
- run: *setup_prerelease_commit_hash - setup_prerelease_commit_hash
- run: - run:
name: Build documentation name: Build documentation
command: ./docs/docs.sh command: docs/docs.sh
- store_artifacts: - store_artifacts:
path: docs/_build/html/ path: docs/_build/html/
destination: docs-html destination: docs-html
@ -1146,11 +1181,13 @@ jobs:
t_ubu_soltest_all: &t_ubu_soltest_all t_ubu_soltest_all: &t_ubu_soltest_all
<<: *base_ubuntu2204_large <<: *base_ubuntu2204_large
parallelism: 50 parallelism: 50
<<: *steps_soltest_all steps:
- soltest_all
t_ubu_lsp: &t_ubu_lsp t_ubu_lsp: &t_ubu_lsp
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
<<: *steps_test_lsp steps:
- test_lsp
t_archlinux_soltest: &t_archlinux_soltest t_archlinux_soltest: &t_archlinux_soltest
<<: *base_archlinux <<: *base_archlinux
@ -1167,9 +1204,7 @@ jobs:
name: Install runtime dependencies name: Install runtime dependencies
command: | command: |
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
- when: - soltest
condition: true
<<: *steps_soltest
t_ubu_clang_soltest: &t_ubu_clang_soltest t_ubu_clang_soltest: &t_ubu_clang_soltest
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -1181,7 +1216,8 @@ jobs:
# The high parallelism in this job is causing the SMT tests to run out of memory, # The high parallelism in this job is causing the SMT tests to run out of memory,
# so disabling for now. # so disabling for now.
SOLTEST_FLAGS: --no-smt SOLTEST_FLAGS: --no-smt
<<: *steps_soltest steps:
- soltest
t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all
# NOTE: This definition is identical to t_ubu_soltest_all but in the workflow we make it depend on # NOTE: This definition is identical to t_ubu_soltest_all but in the workflow we make it depend on
@ -1191,7 +1227,8 @@ jobs:
t_ubu_cli: &t_ubu_cli t_ubu_cli: &t_ubu_cli
<<: *base_ubuntu2204_small <<: *base_ubuntu2204_small
parallelism: 7 # Should match number of tests in .circleci/cli.sh parallelism: 7 # Should match number of tests in .circleci/cli.sh
<<: *steps_cmdline_tests steps:
- cmdline_tests
t_ubu_force_release_cli: &t_ubu_force_release_cli t_ubu_force_release_cli: &t_ubu_force_release_cli
<<: *t_ubu_cli <<: *t_ubu_cli
@ -1215,7 +1252,8 @@ jobs:
# Suppress CLN memory leak. # Suppress CLN memory leak.
# See: https://github.com/ethereum/solidity/issues/13891 for details. # See: https://github.com/ethereum/solidity/issues/13891 for details.
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0 LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0
<<: *steps_cmdline_tests steps:
- cmdline_tests
t_ubu_asan_soltest: t_ubu_asan_soltest:
<<: *base_ubuntu2204 <<: *base_ubuntu2204
@ -1229,7 +1267,8 @@ jobs:
# Suppress CLN memory leak. # Suppress CLN memory leak.
# See: https://github.com/ethereum/solidity/issues/13891 for details. # See: https://github.com/ethereum/solidity/issues/13891 for details.
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp
<<: *steps_soltest steps:
- soltest
t_ubu_asan_clang_soltest: t_ubu_asan_clang_soltest:
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -1240,7 +1279,8 @@ jobs:
OPTIMIZE: 0 OPTIMIZE: 0
SOLTEST_FLAGS: --no-smt SOLTEST_FLAGS: --no-smt
ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
<<: *steps_soltest steps:
- soltest
t_ubu_ubsan_clang_soltest: t_ubu_ubsan_clang_soltest:
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
@ -1249,12 +1289,14 @@ jobs:
<<: *base_ubuntu2204_clang_env <<: *base_ubuntu2204_clang_env
EVM: << pipeline.parameters.evm-version >> EVM: << pipeline.parameters.evm-version >>
SOLTEST_FLAGS: --no-smt SOLTEST_FLAGS: --no-smt
<<: *steps_soltest steps:
- soltest
t_ubu_ubsan_clang_cli: t_ubu_ubsan_clang_cli:
<<: *base_ubuntu2204_clang <<: *base_ubuntu2204_clang
parallelism: 7 # Should match number of tests in .circleci/cli.sh parallelism: 7 # Should match number of tests in .circleci/cli.sh
<<: *steps_cmdline_tests steps:
- cmdline_tests
t_ems_solcjs: t_ems_solcjs:
# Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small). # Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small).
@ -1478,7 +1520,8 @@ jobs:
name: "Run solc.exe to make sure build was successful." name: "Run solc.exe to make sure build was successful."
command: .\build\solc\Release\solc.exe --version command: .\build\solc\Release\solc.exe --version
shell: powershell.exe shell: powershell.exe
- store_artifacts: *artifact_solc_windows - store_artifacts:
path: upload/
- persist_to_workspace: - persist_to_workspace:
root: build root: build
paths: paths:
@ -1507,10 +1550,11 @@ jobs:
command: python -m pip install --user deepdiff colorama command: python -m pip install --user deepdiff colorama
- run: - run:
name: Executing solc LSP test suite name: Executing solc LSP test suite
command: python ./test/lsp.py .\build\solc\Release\solc.exe --non-interactive command: python test/lsp.py build\solc\Release\solc.exe --non-interactive
shell: powershell.exe shell: powershell.exe
- store_test_results: *store_test_results - store_test_results:
- store_artifacts: *artifacts_test_results path: test_results/
- store_artifacts_test_results
- matrix_notify_failure_unless_pr - matrix_notify_failure_unless_pr
# Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu # Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu

View File

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

View File

@ -4,7 +4,9 @@ Language Features:
Compiler Features: 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: 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: Bugfixes:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -32,14 +32,13 @@
#include <range/v3/view/map.hpp> #include <range/v3/view/map.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::frontend; using namespace solidity::frontend;
string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function) std::string IRGenerationContext::enqueueFunctionForCodeGeneration(FunctionDefinition const& _function)
{ {
string name = IRNames::function(_function); std::string name = IRNames::function(_function);
if (!m_functions.contains(name)) if (!m_functions.contains(name))
m_functionGenerationQueue.insert(&_function); m_functionGenerationQueue.insert(&_function);
@ -121,12 +120,12 @@ void IRGenerationContext::addStateVariable(
unsigned _byteOffset unsigned _byteOffset
) )
{ {
m_stateVariables[&_declaration] = make_pair(std::move(_storageOffset), _byteOffset); m_stateVariables[&_declaration] = std::make_pair(std::move(_storageOffset), _byteOffset);
} }
string IRGenerationContext::newYulVariable() std::string IRGenerationContext::newYulVariable()
{ {
return "_" + to_string(++m_varCounter); return "_" + std::to_string(++m_varCounter);
} }
void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _internalDispatch) void IRGenerationContext::initializeInternalDispatch(InternalDispatchMap _internalDispatch)

View File

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

View File

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

View File

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

View File

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

View File

@ -15,33 +15,35 @@
along with solidity. If not, see <http://www.gnu.org/licenses/>. along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/ */
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
/**
* Changes the topmost block to be a function with a specific name ("main") which has no
* inputs nor outputs.
*/
#pragma once #pragma once
#include <libyul/ASTForward.h> #include <vector>
#include <memory>
namespace solidity::yul namespace solidity::frontend
{
class SourceUnit;
}
namespace solidity::langutil
{
class ErrorReporter;
}
namespace solidity::frontend::experimental
{ {
struct OptimiserStepContext; class Analysis
/**
* Prerequisites: Function Grouper
*/
class MainFunction
{ {
public: public:
static constexpr char const* name{"MainFunction"}; Analysis(langutil::ErrorReporter& _errorReporter):
static void run(OptimiserStepContext&, Block& _ast) { MainFunction{}(_ast); } m_errorReporter(_errorReporter)
{}
void operator()(Block& _block); bool check(std::vector<std::shared_ptr<SourceUnit const>> const& _sourceUnits);
private: private:
MainFunction() = default; langutil::ErrorReporter& m_errorReporter;
}; };
} }

View File

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

View File

@ -31,7 +31,6 @@
#include <z3_version.h> #include <z3_version.h>
#endif #endif
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -41,13 +40,13 @@ BMC::BMC(
smt::EncodingContext& _context, smt::EncodingContext& _context,
UniqueErrorReporter& _errorReporter, UniqueErrorReporter& _errorReporter,
UniqueErrorReporter& _unsupportedErrorReporter, UniqueErrorReporter& _unsupportedErrorReporter,
map<h256, string> const& _smtlib2Responses, std::map<h256, std::string> const& _smtlib2Responses,
ReadCallback::Callback const& _smtCallback, ReadCallback::Callback const& _smtCallback,
ModelCheckerSettings _settings, ModelCheckerSettings _settings,
CharStreamProvider const& _charStreamProvider CharStreamProvider const& _charStreamProvider
): ):
SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider), SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider),
m_interface(make_unique<smtutil::SMTPortfolio>( m_interface(std::make_unique<smtutil::SMTPortfolio>(
_smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout, _settings.printQuery _smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout, _settings.printQuery
)) ))
{ {
@ -65,7 +64,7 @@ BMC::BMC(
#endif #endif
} }
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets) void BMC::analyze(SourceUnit const& _source, std::map<ASTNode const*, std::set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets)
{ {
// At this point every enabled solver is available. // At this point every enabled solver is available.
if (!m_settings.solvers.cvc4 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3) if (!m_settings.solvers.cvc4 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3)
@ -97,7 +96,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
2788_error, 2788_error,
{}, {},
"BMC: " + "BMC: " +
to_string(m_unprovedAmt) + std::to_string(m_unprovedAmt) +
" verification condition(s) could not be proved." + " verification condition(s) could not be proved." +
" Enable the model checker option \"show unproved\" to see all of them." + " Enable the model checker option \"show unproved\" to see all of them." +
" Consider choosing a specific contract to be verified in order to reduce the solving problems." + " Consider choosing a specific contract to be verified in order to reduce the solving problems." +
@ -108,7 +107,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
m_errorReporter.info( m_errorReporter.info(
6002_error, 6002_error,
"BMC: " + "BMC: " +
to_string(m_safeTargets.size()) + std::to_string(m_safeTargets.size()) +
" verification condition(s) proved safe!" + " verification condition(s) proved safe!" +
" Enable the model checker option \"show proved safe\" to see all of them." " Enable the model checker option \"show proved safe\" to see all of them."
); );
@ -138,7 +137,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
"BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available." "BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available."
" None of the installed solvers was enabled." " None of the installed solvers was enabled."
#ifdef HAVE_Z3_DLOPEN #ifdef HAVE_Z3_DLOPEN
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3." " Install libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION) + " to enable Z3."
#endif #endif
); );
} }
@ -504,11 +503,11 @@ bool BMC::visit(TryStatement const& _tryStatement)
if (_tryStatement.successClause()->parameters()) if (_tryStatement.successClause()->parameters())
expressionToTupleAssignment(_tryStatement.successClause()->parameters()->parameters(), *externalCall); expressionToTupleAssignment(_tryStatement.successClause()->parameters()->parameters(), *externalCall);
smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + to_string(m_context.newUniqueId()), smtutil::SortProvider::uintSort); smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + std::to_string(m_context.newUniqueId()), smtutil::SortProvider::uintSort);
auto const& clauses = _tryStatement.clauses(); auto const& clauses = _tryStatement.clauses();
m_context.addAssertion(clauseId >= 0 && clauseId < clauses.size()); m_context.addAssertion(clauseId >= 0 && clauseId < clauses.size());
solAssert(clauses[0].get() == _tryStatement.successClause(), "First clause of TryStatement should be the success clause"); solAssert(clauses[0].get() == _tryStatement.successClause(), "First clause of TryStatement should be the success clause");
vector<pair<VariableIndices, smtutil::Expression>> clausesVisitResults; std::vector<std::pair<VariableIndices, smtutil::Expression>> clausesVisitResults;
for (size_t i = 0; i < clauses.size(); ++i) for (size_t i = 0; i < clauses.size(); ++i)
clausesVisitResults.push_back(visitBranch(clauses[i].get())); clausesVisitResults.push_back(visitBranch(clauses[i].get()));
@ -736,7 +735,7 @@ void BMC::internalOrExternalFunctionCall(FunctionCall const& _funCall)
} }
} }
pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation( std::pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
Token _op, Token _op,
smtutil::Expression const& _left, smtutil::Expression const& _left,
smtutil::Expression const& _right, smtutil::Expression const& _right,
@ -800,10 +799,10 @@ void BMC::reset()
m_loopExecutionHappened = false; m_loopExecutionHappened = false;
} }
pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions() std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> BMC::modelExpressions()
{ {
vector<smtutil::Expression> expressionsToEvaluate; std::vector<smtutil::Expression> expressionsToEvaluate;
vector<string> expressionNames; std::vector<std::string> expressionNames;
for (auto const& var: m_context.variables()) for (auto const& var: m_context.variables())
if (var.first->type()->isValueType()) if (var.first->type()->isValueType())
{ {
@ -826,7 +825,7 @@ pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
if (uf->annotation().type->isValueType()) if (uf->annotation().type->isValueType())
{ {
expressionsToEvaluate.emplace_back(expr(*uf)); expressionsToEvaluate.emplace_back(expr(*uf));
string expressionName; std::string expressionName;
if (uf->location().hasText()) if (uf->location().hasText())
expressionName = m_charStreamProvider.charStream(*uf->location().sourceName).text( expressionName = m_charStreamProvider.charStream(*uf->location().sourceName).text(
uf->location() uf->location()
@ -839,7 +838,7 @@ pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
/// Verification targets. /// Verification targets.
string BMC::targetDescription(BMCVerificationTarget const& _target) std::string BMC::targetDescription(BMCVerificationTarget const& _target)
{ {
if ( if (
_target.type == VerificationTargetType::Underflow || _target.type == VerificationTargetType::Underflow ||
@ -1065,20 +1064,20 @@ void BMC::addVerificationTarget(
void BMC::checkCondition( void BMC::checkCondition(
BMCVerificationTarget const& _target, BMCVerificationTarget const& _target,
smtutil::Expression _condition, smtutil::Expression _condition,
vector<SMTEncoder::CallStackEntry> const& _callStack, std::vector<SMTEncoder::CallStackEntry> const& _callStack,
pair<vector<smtutil::Expression>, vector<string>> const& _modelExpressions, std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> const& _modelExpressions,
SourceLocation const& _location, SourceLocation const& _location,
ErrorId _errorHappens, ErrorId _errorHappens,
ErrorId _errorMightHappen, ErrorId _errorMightHappen,
string const& _additionalValueName, std::string const& _additionalValueName,
smtutil::Expression const* _additionalValue smtutil::Expression const* _additionalValue
) )
{ {
m_interface->push(); m_interface->push();
m_interface->addAssertion(_condition); m_interface->addAssertion(_condition);
vector<smtutil::Expression> expressionsToEvaluate; std::vector<smtutil::Expression> expressionsToEvaluate;
vector<string> expressionNames; std::vector<std::string> expressionNames;
tie(expressionsToEvaluate, expressionNames) = _modelExpressions; tie(expressionsToEvaluate, expressionNames) = _modelExpressions;
if (!_callStack.empty()) if (!_callStack.empty())
if (_additionalValue) if (_additionalValue)
@ -1087,10 +1086,10 @@ void BMC::checkCondition(
expressionNames.push_back(_additionalValueName); expressionNames.push_back(_additionalValueName);
} }
smtutil::CheckResult result; smtutil::CheckResult result;
vector<string> values; std::vector<std::string> values;
tie(result, values) = checkSatisfiableAndGenerateModel(expressionsToEvaluate); tie(result, values) = checkSatisfiableAndGenerateModel(expressionsToEvaluate);
string extraComment = SMTEncoder::extraComment(); std::string extraComment = SMTEncoder::extraComment();
if (m_loopExecutionHappened) if (m_loopExecutionHappened)
extraComment += extraComment +=
"False negatives are possible when unrolling loops.\n" "False negatives are possible when unrolling loops.\n"
@ -1119,7 +1118,7 @@ void BMC::checkCondition(
if (values.size() == expressionNames.size()) if (values.size() == expressionNames.size())
{ {
modelMessage << "Counterexample:\n"; modelMessage << "Counterexample:\n";
map<string, string> sortedModel; std::map<std::string, std::string> sortedModel;
for (size_t i = 0; i < values.size(); ++i) for (size_t i = 0; i < values.size(); ++i)
if (expressionsToEvaluate.at(i).name != values.at(i)) if (expressionsToEvaluate.at(i).name != values.at(i))
sortedModel[expressionNames.at(i)] = values.at(i); sortedModel[expressionNames.at(i)] = values.at(i);
@ -1165,7 +1164,7 @@ void BMC::checkBooleanNotConstant(
Expression const& _condition, Expression const& _condition,
smtutil::Expression const& _constraints, smtutil::Expression const& _constraints,
smtutil::Expression const& _value, smtutil::Expression const& _value,
vector<SMTEncoder::CallStackEntry> const& _callStack std::vector<SMTEncoder::CallStackEntry> const& _callStack
) )
{ {
// Do not check for const-ness if this is a constant. // Do not check for const-ness if this is a constant.
@ -1198,7 +1197,7 @@ void BMC::checkBooleanNotConstant(
m_errorReporter.warning(2512_error, _condition.location(), "BMC: Condition unreachable.", SMTEncoder::callStackMessage(_callStack)); m_errorReporter.warning(2512_error, _condition.location(), "BMC: Condition unreachable.", SMTEncoder::callStackMessage(_callStack));
else else
{ {
string description; std::string description;
if (positiveResult == smtutil::CheckResult::SATISFIABLE) if (positiveResult == smtutil::CheckResult::SATISFIABLE)
{ {
solAssert(negatedResult == smtutil::CheckResult::UNSATISFIABLE, ""); solAssert(negatedResult == smtutil::CheckResult::UNSATISFIABLE, "");
@ -1219,17 +1218,17 @@ void BMC::checkBooleanNotConstant(
} }
} }
pair<smtutil::CheckResult, vector<string>> std::pair<smtutil::CheckResult, std::vector<std::string>>
BMC::checkSatisfiableAndGenerateModel(vector<smtutil::Expression> const& _expressionsToEvaluate) BMC::checkSatisfiableAndGenerateModel(std::vector<smtutil::Expression> const& _expressionsToEvaluate)
{ {
smtutil::CheckResult result; smtutil::CheckResult result;
vector<string> values; std::vector<std::string> values;
try try
{ {
if (m_settings.printQuery) if (m_settings.printQuery)
{ {
auto portfolio = dynamic_cast<smtutil::SMTPortfolio*>(m_interface.get()); auto portfolio = dynamic_cast<smtutil::SMTPortfolio*>(m_interface.get());
string smtlibCode = portfolio->dumpQuery(_expressionsToEvaluate); std::string smtlibCode = portfolio->dumpQuery(_expressionsToEvaluate);
m_errorReporter.info( m_errorReporter.info(
6240_error, 6240_error,
"BMC: Requested query:\n" + smtlibCode "BMC: Requested query:\n" + smtlibCode
@ -1239,14 +1238,14 @@ BMC::checkSatisfiableAndGenerateModel(vector<smtutil::Expression> const& _expres
} }
catch (smtutil::SolverError const& _e) catch (smtutil::SolverError const& _e)
{ {
string description("BMC: Error querying SMT solver"); std::string description("BMC: Error querying SMT solver");
if (_e.comment()) if (_e.comment())
description += ": " + *_e.comment(); description += ": " + *_e.comment();
m_errorReporter.warning(8140_error, description); m_errorReporter.warning(8140_error, description);
result = smtutil::CheckResult::ERROR; result = smtutil::CheckResult::ERROR;
} }
for (string& value: values) for (std::string& value: values)
{ {
try try
{ {

View File

@ -51,7 +51,6 @@
#include <charconv> #include <charconv>
#include <queue> #include <queue>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -63,7 +62,7 @@ CHC::CHC(
EncodingContext& _context, EncodingContext& _context,
UniqueErrorReporter& _errorReporter, UniqueErrorReporter& _errorReporter,
UniqueErrorReporter& _unsupportedErrorReporter, UniqueErrorReporter& _unsupportedErrorReporter,
map<util::h256, string> const& _smtlib2Responses, std::map<util::h256, std::string> const& _smtlib2Responses,
ReadCallback::Callback const& _smtCallback, ReadCallback::Callback const& _smtCallback,
ModelCheckerSettings _settings, ModelCheckerSettings _settings,
CharStreamProvider const& _charStreamProvider CharStreamProvider const& _charStreamProvider
@ -130,7 +129,7 @@ void CHC::analyze(SourceUnit const& _source)
); );
} }
vector<string> CHC::unhandledQueries() const std::vector<std::string> CHC::unhandledQueries() const
{ {
if (auto smtlib2 = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get())) if (auto smtlib2 = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get()))
return smtlib2->unhandledQueries(); return smtlib2->unhandledQueries();
@ -213,7 +212,7 @@ void CHC::endVisit(ContractDefinition const& _contract)
auto baseConstructor = base->constructor(); auto baseConstructor = base->constructor();
if (baseConstructor && baseArgs.count(base)) if (baseConstructor && baseArgs.count(base))
{ {
vector<ASTPointer<Expression>> const& args = baseArgs.at(base); std::vector<ASTPointer<Expression>> const& args = baseArgs.at(base);
auto const& params = baseConstructor->parameters(); auto const& params = baseConstructor->parameters();
solAssert(params.size() == args.size(), ""); solAssert(params.size() == args.size(), "");
for (unsigned i = 0; i < params.size(); ++i) for (unsigned i = 0; i < params.size(); ++i)
@ -280,7 +279,7 @@ bool CHC::visit(FunctionDefinition const& _function)
conj = conj && currentEqualInitialVarsConstraints(stateVariablesIncludingInheritedAndPrivate(_function)); conj = conj && currentEqualInitialVarsConstraints(stateVariablesIncludingInheritedAndPrivate(_function));
conj = conj && errorFlag().currentValue() == 0; conj = conj && errorFlag().currentValue() == 0;
addRule(smtutil::Expression::implies(conj, summary(_function)), "summary_function_" + to_string(_function.id())); addRule(smtutil::Expression::implies(conj, summary(_function)), "summary_function_" + std::to_string(_function.id()));
return false; return false;
} }
@ -433,7 +432,7 @@ bool CHC::visit(WhileStatement const& _while)
solAssert(m_currentFunction, ""); solAssert(m_currentFunction, "");
auto const& functionBody = m_currentFunction->body(); auto const& functionBody = m_currentFunction->body();
auto namePrefix = string(_while.isDoWhile() ? "do_" : "") + "while"; auto namePrefix = std::string(_while.isDoWhile() ? "do_" : "") + "while";
auto loopHeaderBlock = createBlock(&_while, PredicateType::FunctionBlock, namePrefix + "_header_"); auto loopHeaderBlock = createBlock(&_while, PredicateType::FunctionBlock, namePrefix + "_header_");
auto loopBodyBlock = createBlock(&_while.body(), PredicateType::FunctionBlock, namePrefix + "_body_"); auto loopBodyBlock = createBlock(&_while.body(), PredicateType::FunctionBlock, namePrefix + "_body_");
auto afterLoopBlock = createBlock(&functionBody, PredicateType::FunctionBlock); auto afterLoopBlock = createBlock(&functionBody, PredicateType::FunctionBlock);
@ -622,8 +621,8 @@ void CHC::endVisit(IndexRangeAccess const& _range)
{ {
createExpr(_range); createExpr(_range);
auto baseArray = dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range.baseExpression())); auto baseArray = std::dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range.baseExpression()));
auto sliceArray = dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range)); auto sliceArray = std::dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range));
solAssert(baseArray && sliceArray, ""); solAssert(baseArray && sliceArray, "");
auto const& sliceData = ArraySlicePredicate::create(sliceArray->sort(), m_context); auto const& sliceData = ArraySlicePredicate::create(sliceArray->sort(), m_context);
@ -864,7 +863,7 @@ void CHC::nondetCall(ContractDefinition const& _contract, VariableDeclaration co
state().readStateVars(_contract, address); state().readStateVars(_contract, address);
m_context.addAssertion(state().state() == state().state(0)); m_context.addAssertion(state().state() == state().state(0));
auto preCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables(_contract); auto preCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables(_contract);
state().newState(); state().newState();
for (auto const* var: _contract.stateVariables()) for (auto const* var: _contract.stateVariables())
@ -879,8 +878,8 @@ void CHC::nondetCall(ContractDefinition const& _contract, VariableDeclaration co
&_var, &_var,
m_currentContract m_currentContract
); );
auto postCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables(_contract); auto postCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables(_contract);
vector<smtutil::Expression> stateExprs{error, address, state().abi(), state().crypto()}; std::vector<smtutil::Expression> stateExprs{error, address, state().abi(), state().crypto()};
auto nondet = (*m_nondetInterfaces.at(&_contract))(stateExprs + preCallState + postCallState); auto nondet = (*m_nondetInterfaces.at(&_contract))(stateExprs + preCallState + postCallState);
auto nondetCall = callPredicate(stateExprs + preCallState + postCallState); auto nondetCall = callPredicate(stateExprs + preCallState + postCallState);
@ -945,7 +944,7 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall)
if (Expression const* value = valueOption(callOptions)) if (Expression const* value = valueOption(callOptions))
decreaseBalanceFromOptionsValue(*value); decreaseBalanceFromOptionsValue(*value);
auto preCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables(); auto preCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables();
if (!usesStaticCall(_funCall)) if (!usesStaticCall(_funCall))
{ {
@ -962,8 +961,8 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall)
PredicateType::ExternalCallUntrusted, PredicateType::ExternalCallUntrusted,
&_funCall &_funCall
); );
auto postCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables(); auto postCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables();
vector<smtutil::Expression> stateExprs{error, state().thisAddress(), state().abi(), state().crypto()}; std::vector<smtutil::Expression> stateExprs{error, state().thisAddress(), state().abi(), state().crypto()};
auto nondet = (*m_nondetInterfaces.at(m_currentContract))(stateExprs + preCallState + postCallState); auto nondet = (*m_nondetInterfaces.at(m_currentContract))(stateExprs + preCallState + postCallState);
auto nondetCall = callPredicate(stateExprs + preCallState + postCallState); auto nondetCall = callPredicate(stateExprs + preCallState + postCallState);
@ -1076,7 +1075,7 @@ void CHC::makeArrayPopVerificationTarget(FunctionCall const& _arrayPop)
auto memberAccess = dynamic_cast<MemberAccess const*>(cleanExpression(_arrayPop.expression())); auto memberAccess = dynamic_cast<MemberAccess const*>(cleanExpression(_arrayPop.expression()));
solAssert(memberAccess, ""); solAssert(memberAccess, "");
auto symbArray = dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(memberAccess->expression())); auto symbArray = std::dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
solAssert(symbArray, ""); solAssert(symbArray, "");
verificationTargetEncountered(&_arrayPop, VerificationTargetType::PopEmptyArray, symbArray->length() <= 0); verificationTargetEncountered(&_arrayPop, VerificationTargetType::PopEmptyArray, symbArray->length() <= 0);
@ -1089,7 +1088,7 @@ void CHC::makeOutOfBoundsVerificationTarget(IndexAccess const& _indexAccess)
auto baseType = _indexAccess.baseExpression().annotation().type; auto baseType = _indexAccess.baseExpression().annotation().type;
optional<smtutil::Expression> length; std::optional<smtutil::Expression> length;
if (smt::isArray(*baseType)) if (smt::isArray(*baseType))
length = dynamic_cast<smt::SymbolicArrayVariable const&>( length = dynamic_cast<smt::SymbolicArrayVariable const&>(
*m_context.expression(_indexAccess.baseExpression()) *m_context.expression(_indexAccess.baseExpression())
@ -1097,7 +1096,7 @@ void CHC::makeOutOfBoundsVerificationTarget(IndexAccess const& _indexAccess)
else if (auto const* type = dynamic_cast<FixedBytesType const*>(baseType)) else if (auto const* type = dynamic_cast<FixedBytesType const*>(baseType))
length = smtutil::Expression(static_cast<size_t>(type->numBytes())); length = smtutil::Expression(static_cast<size_t>(type->numBytes()));
optional<smtutil::Expression> target; std::optional<smtutil::Expression> target;
if ( if (
auto index = _indexAccess.indexExpression(); auto index = _indexAccess.indexExpression();
index && length index && length
@ -1108,7 +1107,7 @@ void CHC::makeOutOfBoundsVerificationTarget(IndexAccess const& _indexAccess)
verificationTargetEncountered(&_indexAccess, VerificationTargetType::OutOfBounds, *target); verificationTargetEncountered(&_indexAccess, VerificationTargetType::OutOfBounds, *target);
} }
pair<smtutil::Expression, smtutil::Expression> CHC::arithmeticOperation( std::pair<smtutil::Expression, smtutil::Expression> CHC::arithmeticOperation(
Token _op, Token _op,
smtutil::Expression const& _left, smtutil::Expression const& _left,
smtutil::Expression const& _right, smtutil::Expression const& _right,
@ -1192,7 +1191,7 @@ void CHC::resetSourceAnalysis()
solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld); solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld);
if (!m_interface) if (!m_interface)
m_interface = make_unique<CHCSmtLib2Interface>(m_smtlib2Responses, m_smtCallback, m_settings.solvers, m_settings.timeout); m_interface = std::make_unique<CHCSmtLib2Interface>(m_smtlib2Responses, m_smtCallback, m_settings.solvers, m_settings.timeout);
auto smtlib2Interface = dynamic_cast<CHCSmtLib2Interface*>(m_interface.get()); auto smtlib2Interface = dynamic_cast<CHCSmtLib2Interface*>(m_interface.get());
solAssert(smtlib2Interface, ""); solAssert(smtlib2Interface, "");
@ -1249,9 +1248,9 @@ void CHC::setCurrentBlock(Predicate const& _block)
m_currentBlock = predicate(_block); m_currentBlock = predicate(_block);
} }
set<unsigned> CHC::transactionVerificationTargetsIds(ASTNode const* _txRoot) std::set<unsigned> CHC::transactionVerificationTargetsIds(ASTNode const* _txRoot)
{ {
set<unsigned> verificationTargetsIds; std::set<unsigned> verificationTargetsIds;
struct ASTNodeCompare: EncodingContext::IdCompare struct ASTNodeCompare: EncodingContext::IdCompare
{ {
bool operator<(ASTNodeCompare _other) const { return operator()(node, _other.node); } bool operator<(ASTNodeCompare _other) const { return operator()(node, _other.node); }
@ -1273,9 +1272,9 @@ bool CHC::usesStaticCall(FunctionCall const& _funCall)
return (function && (function->stateMutability() == StateMutability::Pure || function->stateMutability() == StateMutability::View)) || kind == FunctionType::Kind::BareStaticCall; return (function && (function->stateMutability() == StateMutability::Pure || function->stateMutability() == StateMutability::View)) || kind == FunctionType::Kind::BareStaticCall;
} }
optional<CHC::CHCNatspecOption> CHC::natspecOptionFromString(string const& _option) std::optional<CHC::CHCNatspecOption> CHC::natspecOptionFromString(std::string const& _option)
{ {
static map<string, CHCNatspecOption> options{ static std::map<std::string, CHCNatspecOption> options{
{"abstract-function-nondet", CHCNatspecOption::AbstractFunctionNondet} {"abstract-function-nondet", CHCNatspecOption::AbstractFunctionNondet}
}; };
if (options.count(_option)) if (options.count(_option))
@ -1283,15 +1282,15 @@ optional<CHC::CHCNatspecOption> CHC::natspecOptionFromString(string const& _opti
return {}; return {};
} }
set<CHC::CHCNatspecOption> CHC::smtNatspecTags(FunctionDefinition const& _function) std::set<CHC::CHCNatspecOption> CHC::smtNatspecTags(FunctionDefinition const& _function)
{ {
set<CHC::CHCNatspecOption> options; std::set<CHC::CHCNatspecOption> options;
string smtStr = "custom:smtchecker"; std::string smtStr = "custom:smtchecker";
bool errorSeen = false; bool errorSeen = false;
for (auto const& [tag, value]: _function.annotation().docTags) for (auto const& [tag, value]: _function.annotation().docTags)
if (tag == smtStr) if (tag == smtStr)
{ {
string const& content = value.content; std::string const& content = value.content;
if (auto option = natspecOptionFromString(content)) if (auto option = natspecOptionFromString(content))
options.insert(*option); options.insert(*option);
else if (!errorSeen) else if (!errorSeen)
@ -1327,7 +1326,7 @@ SortPointer CHC::sort(ASTNode const* _node)
return functionBodySort(*m_currentFunction, m_currentContract, state()); return functionBodySort(*m_currentFunction, m_currentContract, state());
} }
Predicate const* CHC::createSymbolicBlock(SortPointer _sort, string const& _name, PredicateType _predType, ASTNode const* _node, ContractDefinition const* _contractContext) Predicate const* CHC::createSymbolicBlock(SortPointer _sort, std::string const& _name, PredicateType _predType, ASTNode const* _node, ContractDefinition const* _contractContext)
{ {
auto const* block = Predicate::create(_sort, _name, _predType, m_context, _node, _contractContext, m_scopes); auto const* block = Predicate::create(_sort, _name, _predType, m_context, _node, _contractContext, m_scopes);
m_interface->registerRelation(block->functor()); m_interface->registerRelation(block->functor());
@ -1339,7 +1338,7 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
for (auto const& node: _source.nodes()) for (auto const& node: _source.nodes())
if (auto const* contract = dynamic_cast<ContractDefinition const*>(node.get())) if (auto const* contract = dynamic_cast<ContractDefinition const*>(node.get()))
{ {
string suffix = contract->name() + "_" + to_string(contract->id()); std::string suffix = contract->name() + "_" + std::to_string(contract->id());
m_interfaces[contract] = createSymbolicBlock(interfaceSort(*contract, state()), "interface_" + uniquePrefix() + "_" + suffix, PredicateType::Interface, contract, contract); m_interfaces[contract] = createSymbolicBlock(interfaceSort(*contract, state()), "interface_" + uniquePrefix() + "_" + suffix, PredicateType::Interface, contract, contract);
m_nondetInterfaces[contract] = createSymbolicBlock(nondetInterfaceSort(*contract, state()), "nondet_interface_" + uniquePrefix() + "_" + suffix, PredicateType::NondetInterface, contract, contract); m_nondetInterfaces[contract] = createSymbolicBlock(nondetInterfaceSort(*contract, state()), "nondet_interface_" + uniquePrefix() + "_" + suffix, PredicateType::NondetInterface, contract, contract);
m_constructorSummaries[contract] = createConstructorBlock(*contract, "summary_constructor"); m_constructorSummaries[contract] = createConstructorBlock(*contract, "summary_constructor");
@ -1385,10 +1384,10 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
auto errorPost = errorFlag().increaseIndex(); auto errorPost = errorFlag().increaseIndex();
auto nondetPost = smt::nondetInterface(iface, *contract, m_context, 0, 2); auto nondetPost = smt::nondetInterface(iface, *contract, m_context, 0, 2);
vector<smtutil::Expression> args{errorPost, state().thisAddress(), state().abi(), state().crypto(), state().tx(), state().state(1)}; std::vector<smtutil::Expression> args{errorPost, state().thisAddress(), state().abi(), state().crypto(), state().tx(), state().state(1)};
args += state1 + args += state1 +
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 0); }) + applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 0); }) +
vector<smtutil::Expression>{state().state(2)} + std::vector<smtutil::Expression>{state().state(2)} +
state2 + state2 +
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 1); }) + applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 1); }) +
applyMap(function->returnParameters(), [this](auto _var) { return valueAtIndex(*_var, 1); }); applyMap(function->returnParameters(), [this](auto _var) { return valueAtIndex(*_var, 1); });
@ -1416,7 +1415,7 @@ void CHC::defineExternalFunctionInterface(FunctionDefinition const& _function, C
// block.coinbase, which do not trigger calls into the contract. // block.coinbase, which do not trigger calls into the contract.
// So the only constraint we can add here is that the balance of // So the only constraint we can add here is that the balance of
// the contract grows by at least `msg.value`. // the contract grows by at least `msg.value`.
SymbolicIntVariable k{TypeProvider::uint256(), TypeProvider::uint256(), "funds_" + to_string(m_context.newUniqueId()), m_context}; SymbolicIntVariable k{TypeProvider::uint256(), TypeProvider::uint256(), "funds_" + std::to_string(m_context.newUniqueId()), m_context};
m_context.addAssertion(k.currentValue() >= state().txMember("msg.value")); m_context.addAssertion(k.currentValue() >= state().txMember("msg.value"));
// Assume that address(this).balance cannot overflow. // Assume that address(this).balance cannot overflow.
m_context.addAssertion(smt::symbolicUnknownConstraints(state().balance(state().thisAddress()) + k.currentValue(), TypeProvider::uint256())); m_context.addAssertion(smt::symbolicUnknownConstraints(state().balance(state().thisAddress()) + k.currentValue(), TypeProvider::uint256()));
@ -1582,7 +1581,7 @@ smtutil::Expression CHC::externalSummary(FunctionDefinition const& _function)
return externalSummary(_function, *m_currentContract); return externalSummary(_function, *m_currentContract);
} }
Predicate const* CHC::createBlock(ASTNode const* _node, PredicateType _predType, string const& _prefix) Predicate const* CHC::createBlock(ASTNode const* _node, PredicateType _predType, std::string const& _prefix)
{ {
auto block = createSymbolicBlock( auto block = createSymbolicBlock(
sort(_node), sort(_node),
@ -1607,7 +1606,7 @@ Predicate const* CHC::createSummaryBlock(FunctionDefinition const& _function, Co
); );
} }
Predicate const* CHC::createConstructorBlock(ContractDefinition const& _contract, string const& _prefix) Predicate const* CHC::createConstructorBlock(ContractDefinition const& _contract, std::string const& _prefix)
{ {
return createSymbolicBlock( return createSymbolicBlock(
constructorSort(_contract, state()), constructorSort(_contract, state()),
@ -1622,7 +1621,7 @@ void CHC::createErrorBlock()
{ {
m_errorPredicate = createSymbolicBlock( m_errorPredicate = createSymbolicBlock(
arity0FunctionSort(), arity0FunctionSort(),
"error_target_" + to_string(m_context.newUniqueId()), "error_target_" + std::to_string(m_context.newUniqueId()),
PredicateType::Error PredicateType::Error
); );
m_interface->registerRelation(m_errorPredicate->functor()); m_interface->registerRelation(m_errorPredicate->functor());
@ -1650,18 +1649,18 @@ smtutil::Expression CHC::initialConstraints(ContractDefinition const& _contract,
return conj; return conj;
} }
vector<smtutil::Expression> CHC::initialStateVariables() std::vector<smtutil::Expression> CHC::initialStateVariables()
{ {
return stateVariablesAtIndex(0); return stateVariablesAtIndex(0);
} }
vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index) std::vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index)
{ {
solAssert(m_currentContract, ""); solAssert(m_currentContract, "");
return stateVariablesAtIndex(_index, *m_currentContract); return stateVariablesAtIndex(_index, *m_currentContract);
} }
vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract) std::vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract)
{ {
return applyMap( return applyMap(
SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract),
@ -1669,27 +1668,27 @@ vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index, Contract
); );
} }
vector<smtutil::Expression> CHC::currentStateVariables() std::vector<smtutil::Expression> CHC::currentStateVariables()
{ {
solAssert(m_currentContract, ""); solAssert(m_currentContract, "");
return currentStateVariables(*m_currentContract); return currentStateVariables(*m_currentContract);
} }
vector<smtutil::Expression> CHC::currentStateVariables(ContractDefinition const& _contract) std::vector<smtutil::Expression> CHC::currentStateVariables(ContractDefinition const& _contract)
{ {
return applyMap(SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), [this](auto _var) { return currentValue(*_var); }); return applyMap(SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), [this](auto _var) { return currentValue(*_var); });
} }
smtutil::Expression CHC::currentEqualInitialVarsConstraints(vector<VariableDeclaration const*> const& _vars) const smtutil::Expression CHC::currentEqualInitialVarsConstraints(std::vector<VariableDeclaration const*> const& _vars) const
{ {
return fold(_vars, smtutil::Expression(true), [this](auto&& _conj, auto _var) { return fold(_vars, smtutil::Expression(true), [this](auto&& _conj, auto _var) {
return std::move(_conj) && currentValue(*_var) == m_context.variable(*_var)->valueAtIndex(0); return std::move(_conj) && currentValue(*_var) == m_context.variable(*_var)->valueAtIndex(0);
}); });
} }
string CHC::predicateName(ASTNode const* _node, ContractDefinition const* _contract) std::string CHC::predicateName(ASTNode const* _node, ContractDefinition const* _contract)
{ {
string prefix; std::string prefix;
if (auto funDef = dynamic_cast<FunctionDefinition const*>(_node)) if (auto funDef = dynamic_cast<FunctionDefinition const*>(_node))
{ {
prefix += TokenTraits::toString(funDef->kind()); prefix += TokenTraits::toString(funDef->kind());
@ -1701,7 +1700,7 @@ string CHC::predicateName(ASTNode const* _node, ContractDefinition const* _contr
auto contract = _contract ? _contract : m_currentContract; auto contract = _contract ? _contract : m_currentContract;
solAssert(contract, ""); solAssert(contract, "");
return prefix + "_" + to_string(_node->id()) + "_" + to_string(contract->id()); return prefix + "_" + std::to_string(_node->id()) + "_" + std::to_string(contract->id());
} }
smtutil::Expression CHC::predicate(Predicate const& _block) smtutil::Expression CHC::predicate(Predicate const& _block)
@ -1756,7 +1755,7 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
solAssert(false, "Unreachable!"); solAssert(false, "Unreachable!");
}; };
errorFlag().increaseIndex(); errorFlag().increaseIndex();
vector<smtutil::Expression> args{errorFlag().currentValue(), contractAddressValue(_funCall), state().abi(), state().crypto(), state().tx(), state().state()}; std::vector<smtutil::Expression> args{errorFlag().currentValue(), contractAddressValue(_funCall), state().abi(), state().crypto(), state().tx(), state().state()};
auto const* contract = function->annotation().contract; auto const* contract = function->annotation().contract;
auto const& hierarchy = m_currentContract->annotation().linearizedBaseContracts; auto const& hierarchy = m_currentContract->annotation().linearizedBaseContracts;
@ -1773,7 +1772,7 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
for (auto const& var: stateVariablesIncludingInheritedAndPrivate(*contract)) for (auto const& var: stateVariablesIncludingInheritedAndPrivate(*contract))
m_context.variable(*var)->increaseIndex(); m_context.variable(*var)->increaseIndex();
} }
args += vector<smtutil::Expression>{state().state()}; args += std::vector<smtutil::Expression>{state().state()};
args += currentStateVariables(*contract); args += currentStateVariables(*contract);
for (auto var: function->parameters() + function->returnParameters()) for (auto var: function->parameters() + function->returnParameters())
@ -1798,12 +1797,12 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
return callPredicate(args); return callPredicate(args);
} }
void CHC::addRule(smtutil::Expression const& _rule, string const& _ruleName) void CHC::addRule(smtutil::Expression const& _rule, std::string const& _ruleName)
{ {
m_interface->addRule(_rule, _ruleName); m_interface->addRule(_rule, _ruleName);
} }
tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query(smtutil::Expression const& _query, langutil::SourceLocation const& _location) std::tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query(smtutil::Expression const& _query, langutil::SourceLocation const& _location)
{ {
CheckResult result; CheckResult result;
smtutil::Expression invariant(true); smtutil::Expression invariant(true);
@ -1812,13 +1811,13 @@ tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query
{ {
auto smtLibInterface = dynamic_cast<CHCSmtLib2Interface*>(m_interface.get()); auto smtLibInterface = dynamic_cast<CHCSmtLib2Interface*>(m_interface.get());
solAssert(smtLibInterface, "Requested to print queries but CHCSmtLib2Interface not available"); solAssert(smtLibInterface, "Requested to print queries but CHCSmtLib2Interface not available");
string smtLibCode = smtLibInterface->dumpQuery(_query); std::string smtLibCode = smtLibInterface->dumpQuery(_query);
m_errorReporter.info( m_errorReporter.info(
2339_error, 2339_error,
"CHC: Requested query:\n" + smtLibCode "CHC: Requested query:\n" + smtLibCode
); );
} }
tie(result, invariant, cex) = m_interface->query(_query); std::tie(result, invariant, cex) = m_interface->query(_query);
switch (result) switch (result)
{ {
case CheckResult::SATISFIABLE: case CheckResult::SATISFIABLE:
@ -1836,7 +1835,7 @@ tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query
CheckResult resultNoOpt; CheckResult resultNoOpt;
smtutil::Expression invariantNoOpt(true); smtutil::Expression invariantNoOpt(true);
CHCSolverInterface::CexGraph cexNoOpt; CHCSolverInterface::CexGraph cexNoOpt;
tie(resultNoOpt, invariantNoOpt, cexNoOpt) = m_interface->query(_query); std::tie(resultNoOpt, invariantNoOpt, cexNoOpt) = m_interface->query(_query);
if (resultNoOpt == CheckResult::SATISFIABLE) if (resultNoOpt == CheckResult::SATISFIABLE)
cex = std::move(cexNoOpt); cex = std::move(cexNoOpt);
@ -1902,7 +1901,7 @@ void CHC::verificationTargetEncountered(
m_context.addAssertion(errorFlag().currentValue() == previousError); m_context.addAssertion(errorFlag().currentValue() == previousError);
} }
pair<string, ErrorId> CHC::targetDescription(CHCVerificationTarget const& _target) std::pair<std::string, ErrorId> CHC::targetDescription(CHCVerificationTarget const& _target)
{ {
if (_target.type == VerificationTargetType::PopEmptyArray) if (_target.type == VerificationTargetType::PopEmptyArray)
{ {
@ -1950,7 +1949,7 @@ void CHC::checkVerificationTargets()
// Also, all possible contexts in which an external function can be called has been recorded (m_queryPlaceholders). // Also, all possible contexts in which an external function can be called has been recorded (m_queryPlaceholders).
// Here we combine every context in which an external function can be called with all possible verification conditions // Here we combine every context in which an external function can be called with all possible verification conditions
// in its call graph. Each such combination forms a unique verification target. // in its call graph. Each such combination forms a unique verification target.
map<unsigned, vector<CHCQueryPlaceholder>> targetEntryPoints; std::map<unsigned, std::vector<CHCQueryPlaceholder>> targetEntryPoints;
for (auto const& [function, placeholders]: m_queryPlaceholders) for (auto const& [function, placeholders]: m_queryPlaceholders)
{ {
auto functionTargets = transactionVerificationTargetsIds(function); auto functionTargets = transactionVerificationTargetsIds(function);
@ -1959,7 +1958,7 @@ void CHC::checkVerificationTargets()
targetEntryPoints[id].push_back(placeholder); targetEntryPoints[id].push_back(placeholder);
} }
set<unsigned> checkedErrorIds; std::set<unsigned> checkedErrorIds;
for (auto const& [targetId, placeholders]: targetEntryPoints) for (auto const& [targetId, placeholders]: targetEntryPoints)
{ {
auto const& target = m_verificationTargets.at(targetId); auto const& target = m_verificationTargets.at(targetId);
@ -1988,7 +1987,7 @@ void CHC::checkVerificationTargets()
5840_error, 5840_error,
{}, {},
"CHC: " + "CHC: " +
to_string(m_unprovedTargets.size()) + std::to_string(m_unprovedTargets.size()) +
" verification condition(s) could not be proved." + " verification condition(s) could not be proved." +
" Enable the model checker option \"show unproved\" to see all of them." + " Enable the model checker option \"show unproved\" to see all of them." +
" Consider choosing a specific contract to be verified in order to reduce the solving problems." + " Consider choosing a specific contract to be verified in order to reduce the solving problems." +
@ -1999,7 +1998,7 @@ void CHC::checkVerificationTargets()
m_errorReporter.info( m_errorReporter.info(
1391_error, 1391_error,
"CHC: " + "CHC: " +
to_string(m_safeTargets.size()) + std::to_string(m_safeTargets.size()) +
" verification condition(s) proved safe!" + " verification condition(s) proved safe!" +
" Enable the model checker option \"show proved safe\" to see all of them." " Enable the model checker option \"show proved safe\" to see all of them."
); );
@ -2016,17 +2015,17 @@ void CHC::checkVerificationTargets()
if (!m_settings.invariants.invariants.empty()) if (!m_settings.invariants.invariants.empty())
{ {
string msg; std::string msg;
for (auto pred: m_invariants | ranges::views::keys) for (auto pred: m_invariants | ranges::views::keys)
{ {
ASTNode const* node = pred->programNode(); ASTNode const* node = pred->programNode();
string what; std::string what;
if (auto contract = dynamic_cast<ContractDefinition const*>(node)) if (auto contract = dynamic_cast<ContractDefinition const*>(node))
what = contract->fullyQualifiedName(); what = contract->fullyQualifiedName();
else else
solAssert(false, ""); solAssert(false, "");
string invType; std::string invType;
if (pred->type() == PredicateType::Interface) if (pred->type() == PredicateType::Interface)
invType = "Contract invariant(s)"; invType = "Contract invariant(s)";
else if (pred->type() == PredicateType::NondetInterface) else if (pred->type() == PredicateType::NondetInterface)
@ -2038,16 +2037,16 @@ void CHC::checkVerificationTargets()
for (auto const& inv: m_invariants.at(pred)) for (auto const& inv: m_invariants.at(pred))
msg += inv + "\n"; msg += inv + "\n";
} }
if (msg.find("<errorCode>") != string::npos) if (msg.find("<errorCode>") != std::string::npos)
{ {
set<unsigned> seenErrors; std::set<unsigned> seenErrors;
msg += "<errorCode> = 0 -> no errors\n"; msg += "<errorCode> = 0 -> no errors\n";
for (auto const& [id, target]: m_verificationTargets) for (auto const& [id, target]: m_verificationTargets)
if (!seenErrors.count(target.errorId)) if (!seenErrors.count(target.errorId))
{ {
seenErrors.insert(target.errorId); seenErrors.insert(target.errorId);
string loc = string(m_charStreamProvider.charStream(*target.errorNode->location().sourceName).text(target.errorNode->location())); std::string loc = std::string(m_charStreamProvider.charStream(*target.errorNode->location().sourceName).text(target.errorNode->location()));
msg += "<errorCode> = " + to_string(target.errorId) + " -> " + ModelCheckerTargets::targetTypeToString.at(target.type) + " at " + loc + "\n"; msg += "<errorCode> = " + std::to_string(target.errorId) + " -> " + ModelCheckerTargets::targetTypeToString.at(target.type) + " at " + loc + "\n";
} }
} }
@ -2058,12 +2057,12 @@ void CHC::checkVerificationTargets()
// There can be targets in internal functions that are not reachable from the external interface. // There can be targets in internal functions that are not reachable from the external interface.
// These are safe by definition and are not even checked by the CHC engine, but this information // These are safe by definition and are not even checked by the CHC engine, but this information
// must still be reported safe by the BMC engine. // must still be reported safe by the BMC engine.
set<unsigned> allErrorIds; std::set<unsigned> allErrorIds;
for (auto const& entry: m_functionTargetIds) for (auto const& entry: m_functionTargetIds)
for (unsigned id: entry.second) for (unsigned id: entry.second)
allErrorIds.insert(id); allErrorIds.insert(id);
set<unsigned> unreachableErrorIds; std::set<unsigned> unreachableErrorIds;
set_difference( set_difference(
allErrorIds.begin(), allErrorIds.begin(),
allErrorIds.end(), allErrorIds.end(),
@ -2077,10 +2076,10 @@ void CHC::checkVerificationTargets()
void CHC::checkAndReportTarget( void CHC::checkAndReportTarget(
CHCVerificationTarget const& _target, CHCVerificationTarget const& _target,
vector<CHCQueryPlaceholder> const& _placeholders, std::vector<CHCQueryPlaceholder> const& _placeholders,
ErrorId _errorReporterId, ErrorId _errorReporterId,
string _satMsg, std::string _satMsg,
string _unknownMsg std::string _unknownMsg
) )
{ {
if (m_unsafeTargets.count(_target.errorNode) && m_unsafeTargets.at(_target.errorNode).count(_target.type)) if (m_unsafeTargets.count(_target.errorNode) && m_unsafeTargets.at(_target.errorNode).count(_target.type))
@ -2098,12 +2097,12 @@ void CHC::checkAndReportTarget(
if (result == CheckResult::UNSATISFIABLE) if (result == CheckResult::UNSATISFIABLE)
{ {
m_safeTargets[_target.errorNode].insert(_target); m_safeTargets[_target.errorNode].insert(_target);
set<Predicate const*> predicates; std::set<Predicate const*> predicates;
for (auto const* pred: m_interfaces | ranges::views::values) for (auto const* pred: m_interfaces | ranges::views::values)
predicates.insert(pred); predicates.insert(pred);
for (auto const* pred: m_nondetInterfaces | ranges::views::values) for (auto const* pred: m_nondetInterfaces | ranges::views::values)
predicates.insert(pred); predicates.insert(pred);
map<Predicate const*, set<string>> invariants = collectInvariants(invariant, predicates, m_settings.invariants); std::map<Predicate const*, std::set<std::string>> invariants = collectInvariants(invariant, predicates, m_settings.invariants);
for (auto pred: invariants | ranges::views::keys) for (auto pred: invariants | ranges::views::keys)
m_invariants[pred] += std::move(invariants.at(pred)); m_invariants[pred] += std::move(invariants.at(pred));
} }
@ -2153,9 +2152,9 @@ the function summaries in the callgraph of the error node is the reverse transac
The first function summary seen contains the values for the state, input and output variables at the The first function summary seen contains the values for the state, input and output variables at the
error point. error point.
*/ */
optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const& _graph, string const& _root) std::optional<std::string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const& _graph, std::string const& _root)
{ {
optional<unsigned> rootId; std::optional<unsigned> rootId;
for (auto const& [id, node]: _graph.nodes) for (auto const& [id, node]: _graph.nodes)
if (node.name == _root) if (node.name == _root)
{ {
@ -2165,8 +2164,8 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
if (!rootId) if (!rootId)
return {}; return {};
vector<string> path; std::vector<std::string> path;
string localState; std::string localState;
auto callGraph = summaryCalls(_graph, *rootId); auto callGraph = summaryCalls(_graph, *rootId);
@ -2204,7 +2203,7 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
if (auto outStr = formatVariableModel(outParams, outValues, "\n"); !outStr.empty()) if (auto outStr = formatVariableModel(outParams, outValues, "\n"); !outStr.empty())
localState += outStr + "\n"; localState += outStr + "\n";
optional<unsigned> localErrorId; std::optional<unsigned> localErrorId;
solidity::util::BreadthFirstSearch<unsigned> bfs{{summaryId}}; solidity::util::BreadthFirstSearch<unsigned> bfs{{summaryId}};
bfs.run([&](auto _nodeId, auto&& _addChild) { bfs.run([&](auto _nodeId, auto&& _addChild) {
auto const& children = _graph.edges.at(_nodeId); auto const& children = _graph.edges.at(_nodeId);
@ -2239,9 +2238,9 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
} }
} }
string txCex = summaryPredicate->formatSummaryCall(summaryArgs, m_charStreamProvider); std::string txCex = summaryPredicate->formatSummaryCall(summaryArgs, m_charStreamProvider);
list<string> calls; std::list<std::string> calls;
auto dfs = [&](unsigned parent, unsigned node, unsigned depth, auto&& _dfs) -> void { auto dfs = [&](unsigned parent, unsigned node, unsigned depth, auto&& _dfs) -> void {
auto pred = nodePred(node); auto pred = nodePred(node);
auto parentPred = nodePred(parent); auto parentPred = nodePred(parent);
@ -2254,7 +2253,7 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
bool appendTxVars = pred->isConstructorSummary() || pred->isFunctionSummary() || pred->isExternalCallUntrusted(); bool appendTxVars = pred->isConstructorSummary() || pred->isFunctionSummary() || pred->isExternalCallUntrusted();
calls.push_front(string(depth * 4, ' ') + pred->formatSummaryCall(nodeArgs(node), m_charStreamProvider, appendTxVars)); calls.push_front(std::string(depth * 4, ' ') + pred->formatSummaryCall(nodeArgs(node), m_charStreamProvider, appendTxVars));
if (pred->isInternalCall()) if (pred->isInternalCall())
calls.front() += " -- internal call"; calls.front() += " -- internal call";
else if (pred->isExternalCallTrusted()) else if (pred->isExternalCallTrusted())
@ -2281,12 +2280,12 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
return localState + "\nTransaction trace:\n" + boost::algorithm::join(path | ranges::views::reverse, "\n"); return localState + "\nTransaction trace:\n" + boost::algorithm::join(path | ranges::views::reverse, "\n");
} }
map<unsigned, vector<unsigned>> CHC::summaryCalls(CHCSolverInterface::CexGraph const& _graph, unsigned _root) std::map<unsigned, std::vector<unsigned>> CHC::summaryCalls(CHCSolverInterface::CexGraph const& _graph, unsigned _root)
{ {
map<unsigned, vector<unsigned>> calls; std::map<unsigned, std::vector<unsigned>> calls;
auto compare = [&](unsigned _a, unsigned _b) { auto compare = [&](unsigned _a, unsigned _b) {
auto extract = [&](string const& _s) { auto extract = [&](std::string const& _s) {
// We want to sort sibling predicates in the counterexample graph by their unique predicate id. // We want to sort sibling predicates in the counterexample graph by their unique predicate id.
// For most predicates, this actually doesn't matter. // For most predicates, this actually doesn't matter.
// The cases where this matters are internal and external function calls which have the form: // The cases where this matters are internal and external function calls which have the form:
@ -2312,7 +2311,7 @@ map<unsigned, vector<unsigned>> CHC::summaryCalls(CHCSolverInterface::CexGraph c
return extract(_graph.nodes.at(_a).name) > extract(_graph.nodes.at(_b).name); return extract(_graph.nodes.at(_a).name) > extract(_graph.nodes.at(_b).name);
}; };
queue<pair<unsigned, unsigned>> q; std::queue<std::pair<unsigned, unsigned>> q;
q.push({_root, _root}); q.push({_root, _root});
while (!q.empty()) while (!q.empty())
{ {
@ -2334,19 +2333,19 @@ map<unsigned, vector<unsigned>> CHC::summaryCalls(CHCSolverInterface::CexGraph c
root = node; root = node;
} }
auto const& edges = _graph.edges.at(node); auto const& edges = _graph.edges.at(node);
for (unsigned v: set<unsigned, decltype(compare)>(begin(edges), end(edges), compare)) for (unsigned v: std::set<unsigned, decltype(compare)>(begin(edges), end(edges), compare))
q.push({v, root}); q.push({v, root});
} }
return calls; return calls;
} }
string CHC::cex2dot(CHCSolverInterface::CexGraph const& _cex) std::string CHC::cex2dot(CHCSolverInterface::CexGraph const& _cex)
{ {
string dot = "digraph {\n"; std::string dot = "digraph {\n";
auto pred = [&](CHCSolverInterface::CexNode const& _node) { auto pred = [&](CHCSolverInterface::CexNode const& _node) {
vector<string> args = applyMap( std::vector<std::string> args = applyMap(
_node.arguments, _node.arguments,
[&](auto const& arg) { return arg.name; } [&](auto const& arg) { return arg.name; }
); );
@ -2361,14 +2360,14 @@ string CHC::cex2dot(CHCSolverInterface::CexGraph const& _cex)
return dot; return dot;
} }
string CHC::uniquePrefix() std::string CHC::uniquePrefix()
{ {
return to_string(m_blockCounter++); return std::to_string(m_blockCounter++);
} }
string CHC::contractSuffix(ContractDefinition const& _contract) std::string CHC::contractSuffix(ContractDefinition const& _contract)
{ {
return _contract.name() + "_" + to_string(_contract.id()); return _contract.name() + "_" + std::to_string(_contract.id());
} }
unsigned CHC::newErrorId() unsigned CHC::newErrorId()

View File

@ -20,7 +20,6 @@
#include <libsolidity/formal/SymbolicTypes.h> #include <libsolidity/formal/SymbolicTypes.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::frontend::smt; using namespace solidity::frontend::smt;
@ -51,7 +50,7 @@ unsigned EncodingContext::newUniqueId()
/// Variables. /// Variables.
shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl) std::shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl)
{ {
solAssert(knownVariable(_varDecl), ""); solAssert(knownVariable(_varDecl), "");
return m_variables[&_varDecl]; return m_variables[&_varDecl];
@ -61,7 +60,7 @@ bool EncodingContext::createVariable(frontend::VariableDeclaration const& _varDe
{ {
solAssert(!knownVariable(_varDecl), ""); solAssert(!knownVariable(_varDecl), "");
auto const& type = _varDecl.type(); auto const& type = _varDecl.type();
auto result = newSymbolicVariable(*type, _varDecl.name() + "_" + to_string(_varDecl.id()), *this); auto result = newSymbolicVariable(*type, _varDecl.name() + "_" + std::to_string(_varDecl.id()), *this);
m_variables.emplace(&_varDecl, result.second); m_variables.emplace(&_varDecl, result.second);
return result.first; return result.first;
} }
@ -77,13 +76,13 @@ void EncodingContext::resetVariable(frontend::VariableDeclaration const& _variab
setUnknownValue(_variable); setUnknownValue(_variable);
} }
void EncodingContext::resetVariables(set<frontend::VariableDeclaration const*> const& _variables) void EncodingContext::resetVariables(std::set<frontend::VariableDeclaration const*> const& _variables)
{ {
for (auto const* decl: _variables) for (auto const* decl: _variables)
resetVariable(*decl); resetVariable(*decl);
} }
void EncodingContext::resetVariables(function<bool(frontend::VariableDeclaration const&)> const& _filter) void EncodingContext::resetVariables(std::function<bool(frontend::VariableDeclaration const&)> const& _filter)
{ {
for_each(begin(m_variables), end(m_variables), [&](auto _variable) for_each(begin(m_variables), end(m_variables), [&](auto _variable)
{ {
@ -127,14 +126,14 @@ void EncodingContext::setUnknownValue(SymbolicVariable& _variable)
/// Expressions /// Expressions
shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e) std::shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e)
{ {
if (!knownExpression(_e)) if (!knownExpression(_e))
createExpression(_e); createExpression(_e);
return m_expressions.at(&_e); return m_expressions.at(&_e);
} }
bool EncodingContext::createExpression(frontend::Expression const& _e, shared_ptr<SymbolicVariable> _symbVar) bool EncodingContext::createExpression(frontend::Expression const& _e, std::shared_ptr<SymbolicVariable> _symbVar)
{ {
solAssert(_e.annotation().type, ""); solAssert(_e.annotation().type, "");
if (knownExpression(_e)) if (knownExpression(_e))
@ -149,7 +148,7 @@ bool EncodingContext::createExpression(frontend::Expression const& _e, shared_pt
} }
else else
{ {
auto result = newSymbolicVariable(*_e.annotation().type, "expr_" + to_string(_e.id()), *this); auto result = newSymbolicVariable(*_e.annotation().type, "expr_" + std::to_string(_e.id()), *this);
m_expressions.emplace(&_e, result.second); m_expressions.emplace(&_e, result.second);
return result.first; return result.first;
} }
@ -162,13 +161,13 @@ bool EncodingContext::knownExpression(frontend::Expression const& _e) const
/// Global variables and functions. /// Global variables and functions.
shared_ptr<SymbolicVariable> EncodingContext::globalSymbol(string const& _name) std::shared_ptr<SymbolicVariable> EncodingContext::globalSymbol(std::string const& _name)
{ {
solAssert(knownGlobalSymbol(_name), ""); solAssert(knownGlobalSymbol(_name), "");
return m_globalContext.at(_name); return m_globalContext.at(_name);
} }
bool EncodingContext::createGlobalSymbol(string const& _name, frontend::Expression const& _expr) bool EncodingContext::createGlobalSymbol(std::string const& _name, frontend::Expression const& _expr)
{ {
solAssert(!knownGlobalSymbol(_name), ""); solAssert(!knownGlobalSymbol(_name), "");
auto result = newSymbolicVariable(*_expr.annotation().type, _name, *this); auto result = newSymbolicVariable(*_expr.annotation().type, _name, *this);
@ -177,7 +176,7 @@ bool EncodingContext::createGlobalSymbol(string const& _name, frontend::Expressi
return result.first; return result.first;
} }
bool EncodingContext::knownGlobalSymbol(string const& _var) const bool EncodingContext::knownGlobalSymbol(std::string const& _var) const
{ {
return m_globalContext.count(_var); return m_globalContext.count(_var);
} }

View File

@ -29,7 +29,6 @@
#include <vector> #include <vector>
#include <string> #include <string>
using namespace std;
using boost::algorithm::starts_with; using boost::algorithm::starts_with;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
@ -42,7 +41,7 @@ namespace solidity::frontend::smt
namespace namespace
{ {
string formatDatatypeAccessor(smtutil::Expression const& _expr, vector<string> const& _args) std::string formatDatatypeAccessor(smtutil::Expression const& _expr, std::vector<std::string> const& _args)
{ {
auto const& op = _expr.name; auto const& op = _expr.name;
@ -63,9 +62,9 @@ string formatDatatypeAccessor(smtutil::Expression const& _expr, vector<string> c
if (op == "dt_accessor_ecrecover") if (op == "dt_accessor_ecrecover")
return "ecrecover"; return "ecrecover";
string accessorStr = "accessor_"; std::string accessorStr = "accessor_";
// Struct members have suffix "accessor_<memberName>". // Struct members have suffix "accessor_<memberName>".
string type = op.substr(op.rfind(accessorStr) + accessorStr.size()); std::string type = op.substr(op.rfind(accessorStr) + accessorStr.size());
solAssert(_expr.arguments.size() == 1, ""); solAssert(_expr.arguments.size() == 1, "");
if (type == "length") if (type == "length")
@ -87,22 +86,22 @@ string formatDatatypeAccessor(smtutil::Expression const& _expr, vector<string> c
return _args.at(0) + "." + type; return _args.at(0) + "." + type;
} }
string formatGenericOp(smtutil::Expression const& _expr, vector<string> const& _args) std::string formatGenericOp(smtutil::Expression const& _expr, std::vector<std::string> const& _args)
{ {
return _expr.name + "(" + boost::algorithm::join(_args, ", ") + ")"; return _expr.name + "(" + boost::algorithm::join(_args, ", ") + ")";
} }
string formatInfixOp(string const& _op, vector<string> const& _args) std::string formatInfixOp(std::string const& _op, std::vector<std::string> const& _args)
{ {
return "(" + boost::algorithm::join(_args, " " + _op + " ") + ")"; return "(" + boost::algorithm::join(_args, " " + _op + " ") + ")";
} }
string formatArrayOp(smtutil::Expression const& _expr, vector<string> const& _args) std::string formatArrayOp(smtutil::Expression const& _expr, std::vector<std::string> const& _args)
{ {
if (_expr.name == "select") if (_expr.name == "select")
{ {
auto const& a0 = _args.at(0); auto const& a0 = _args.at(0);
static set<string> const ufs{"keccak256", "sha256", "ripemd160", "ecrecover"}; static std::set<std::string> const ufs{"keccak256", "sha256", "ripemd160", "ecrecover"};
if (ufs.count(a0) || starts_with(a0, "t_function_abi")) if (ufs.count(a0) || starts_with(a0, "t_function_abi"))
return _args.at(0) + "(" + _args.at(1) + ")"; return _args.at(0) + "(" + _args.at(1) + ")";
return _args.at(0) + "[" + _args.at(1) + "]"; return _args.at(0) + "[" + _args.at(1) + "]";
@ -112,7 +111,7 @@ string formatArrayOp(smtutil::Expression const& _expr, vector<string> const& _ar
return formatGenericOp(_expr, _args); return formatGenericOp(_expr, _args);
} }
string formatUnaryOp(smtutil::Expression const& _expr, vector<string> const& _args) std::string formatUnaryOp(smtutil::Expression const& _expr, std::vector<std::string> const& _args)
{ {
if (_expr.name == "not") if (_expr.name == "not")
return "!" + _args.at(0); return "!" + _args.at(0);
@ -122,7 +121,7 @@ string formatUnaryOp(smtutil::Expression const& _expr, vector<string> const& _ar
} }
smtutil::Expression substitute(smtutil::Expression _from, map<string, string> const& _subst) smtutil::Expression substitute(smtutil::Expression _from, std::map<std::string, std::string> const& _subst)
{ {
// TODO For now we ignore nested quantifier expressions, // TODO For now we ignore nested quantifier expressions,
// but we should support them in the future. // but we should support them in the future.
@ -135,7 +134,7 @@ smtutil::Expression substitute(smtutil::Expression _from, map<string, string> co
return _from; return _from;
} }
string toSolidityStr(smtutil::Expression const& _expr) std::string toSolidityStr(smtutil::Expression const& _expr)
{ {
auto const& op = _expr.name; auto const& op = _expr.name;
@ -150,7 +149,7 @@ string toSolidityStr(smtutil::Expression const& _expr)
return formatDatatypeAccessor(_expr, strArgs); return formatDatatypeAccessor(_expr, strArgs);
// Infix operators with format replacements. // Infix operators with format replacements.
static map<string, string> const infixOps{ static std::map<std::string, std::string> const infixOps{
{"and", "&&"}, {"and", "&&"},
{"or", "||"}, {"or", "||"},
{"implies", "=>"}, {"implies", "=>"},
@ -170,7 +169,7 @@ string toSolidityStr(smtutil::Expression const& _expr)
if (infixOps.count(op)) if (infixOps.count(op))
return formatInfixOp(infixOps.at(op), strArgs); return formatInfixOp(infixOps.at(op), strArgs);
static set<string> const arrayOps{"select", "store", "const_array"}; static std::set<std::string> const arrayOps{"select", "store", "const_array"};
if (arrayOps.count(op)) if (arrayOps.count(op))
return formatArrayOp(_expr, strArgs); return formatArrayOp(_expr, strArgs);

View File

@ -25,7 +25,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
using namespace std;
using boost::algorithm::starts_with; using boost::algorithm::starts_with;
using namespace solidity; using namespace solidity;
using namespace solidity::smtutil; using namespace solidity::smtutil;
@ -34,19 +33,19 @@ using namespace solidity::frontend::smt;
namespace solidity::frontend::smt namespace solidity::frontend::smt
{ {
map<Predicate const*, set<string>> collectInvariants( std::map<Predicate const*, std::set<std::string>> collectInvariants(
smtutil::Expression const& _proof, smtutil::Expression const& _proof,
set<Predicate const*> const& _predicates, std::set<Predicate const*> const& _predicates,
ModelCheckerInvariants const& _invariantsSetting ModelCheckerInvariants const& _invariantsSetting
) )
{ {
set<string> targets; std::set<std::string> targets;
if (_invariantsSetting.has(InvariantType::Contract)) if (_invariantsSetting.has(InvariantType::Contract))
targets.insert("interface_"); targets.insert("interface_");
if (_invariantsSetting.has(InvariantType::Reentrancy)) if (_invariantsSetting.has(InvariantType::Reentrancy))
targets.insert("nondet_interface_"); targets.insert("nondet_interface_");
map<string, pair<smtutil::Expression, smtutil::Expression>> equalities; std::map<std::string, std::pair<smtutil::Expression, smtutil::Expression>> equalities;
// Collect equalities where one of the sides is a predicate we're interested in. // Collect equalities where one of the sides is a predicate we're interested in.
util::BreadthFirstSearch<smtutil::Expression const*>{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) { util::BreadthFirstSearch<smtutil::Expression const*>{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) {
if (_expr->name == "=") if (_expr->name == "=")
@ -63,7 +62,7 @@ map<Predicate const*, set<string>> collectInvariants(
_addChild(&arg); _addChild(&arg);
}); });
map<Predicate const*, set<string>> invariants; std::map<Predicate const*, std::set<std::string>> invariants;
for (auto pred: _predicates) for (auto pred: _predicates)
{ {
auto predName = pred->functor().name; auto predName = pred->functor().name;
@ -74,7 +73,7 @@ map<Predicate const*, set<string>> collectInvariants(
auto const& [predExpr, invExpr] = equalities.at(predName); auto const& [predExpr, invExpr] = equalities.at(predName);
static set<string> const ignore{"true", "false"}; static std::set<std::string> const ignore{"true", "false"};
auto r = substitute(invExpr, pred->expressionSubstitution(predExpr)); auto r = substitute(invExpr, pred->expressionSubstitution(predExpr));
// No point in reporting true/false as invariants. // No point in reporting true/false as invariants.
if (!ignore.count(r.name)) if (!ignore.count(r.name))

View File

@ -31,7 +31,6 @@
#include <range/v3/algorithm/any_of.hpp> #include <range/v3/algorithm/any_of.hpp>
#include <range/v3/view.hpp> #include <range/v3/view.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
@ -41,7 +40,7 @@ using namespace solidity::smtutil;
ModelChecker::ModelChecker( ModelChecker::ModelChecker(
ErrorReporter& _errorReporter, ErrorReporter& _errorReporter,
langutil::CharStreamProvider const& _charStreamProvider, langutil::CharStreamProvider const& _charStreamProvider,
map<h256, string> const& _smtlib2Responses, std::map<h256, std::string> const& _smtlib2Responses,
ModelCheckerSettings _settings, ModelCheckerSettings _settings,
ReadCallback::Callback const& _smtCallback ReadCallback::Callback const& _smtCallback
): ):
@ -54,19 +53,19 @@ ModelChecker::ModelChecker(
} }
// TODO This should be removed for 0.9.0. // TODO This should be removed for 0.9.0.
bool ModelChecker::isPragmaPresent(vector<shared_ptr<SourceUnit>> const& _sources) bool ModelChecker::isPragmaPresent(std::vector<std::shared_ptr<SourceUnit>> const& _sources)
{ {
return ranges::any_of(_sources, [](auto _source) { return ranges::any_of(_sources, [](auto _source) {
return _source && _source->annotation().experimentalFeatures.count(ExperimentalFeature::SMTChecker); return _source && _source->annotation().experimentalFeatures.count(ExperimentalFeature::SMTChecker);
}); });
} }
void ModelChecker::checkRequestedSourcesAndContracts(vector<shared_ptr<SourceUnit>> const& _sources) void ModelChecker::checkRequestedSourcesAndContracts(std::vector<std::shared_ptr<SourceUnit>> const& _sources)
{ {
map<string, set<string>> exist; std::map<std::string, std::set<std::string>> exist;
for (auto const& source: _sources) for (auto const& source: _sources)
for (auto node: source->nodes()) for (auto node: source->nodes())
if (auto contract = dynamic_pointer_cast<ContractDefinition>(node)) if (auto contract = std::dynamic_pointer_cast<ContractDefinition>(node))
exist[contract->sourceUnitName()].insert(contract->name()); exist[contract->sourceUnitName()].insert(contract->name());
// Requested sources // Requested sources
@ -100,7 +99,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
{ {
PragmaDirective const* smtPragma = nullptr; PragmaDirective const* smtPragma = nullptr;
for (auto node: _source.nodes()) for (auto node: _source.nodes())
if (auto pragma = dynamic_pointer_cast<PragmaDirective>(node)) if (auto pragma = std::dynamic_pointer_cast<PragmaDirective>(node))
if ( if (
pragma->literals().size() >= 2 && pragma->literals().size() >= 2 &&
pragma->literals().at(1) == "SMTChecker" pragma->literals().at(1) == "SMTChecker"
@ -125,7 +124,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
if (m_settings.engine.chc) if (m_settings.engine.chc)
m_chc.analyze(_source); m_chc.analyze(_source);
map<ASTNode const*, set<VerificationTargetType>, smt::EncodingContext::IdCompare> solvedTargets; std::map<ASTNode const*, std::set<VerificationTargetType>, smt::EncodingContext::IdCompare> solvedTargets;
for (auto const& [node, targets]: m_chc.safeTargets()) for (auto const& [node, targets]: m_chc.safeTargets())
for (auto const& target: targets) for (auto const& target: targets)
@ -147,7 +146,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
5724_error, 5724_error,
{}, {},
"SMTChecker: " + "SMTChecker: " +
to_string(m_unsupportedErrorReporter.errors().size()) + std::to_string(m_unsupportedErrorReporter.errors().size()) +
" unsupported language feature(s)." " unsupported language feature(s)."
" Enable the model checker option \"show unsupported\" to see all of them." " Enable the model checker option \"show unsupported\" to see all of them."
); );
@ -156,7 +155,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
m_uniqueErrorReporter.clear(); m_uniqueErrorReporter.clear();
} }
vector<string> ModelChecker::unhandledQueries() std::vector<std::string> ModelChecker::unhandledQueries()
{ {
return m_bmc.unhandledQueries() + m_chc.unhandledQueries(); return m_bmc.unhandledQueries() + m_chc.unhandledQueries();
} }
@ -212,7 +211,7 @@ SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, Er
SourceLocation(), SourceLocation(),
"Solver z3 was selected for SMTChecker but it is not available." "Solver z3 was selected for SMTChecker but it is not available."
#ifdef HAVE_Z3_DLOPEN #ifdef HAVE_Z3_DLOPEN
" libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " was not found." " libz3.so." + std::to_string(Z3_MAJOR_VERSION) + "." + std::to_string(Z3_MINOR_VERSION) + " was not found."
#endif #endif
); );
} }

View File

@ -21,18 +21,17 @@
#include <optional> #include <optional>
#include <range/v3/view.hpp> #include <range/v3/view.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::frontend; using namespace solidity::frontend;
map<string, InvariantType> const ModelCheckerInvariants::validInvariants{ std::map<std::string, InvariantType> const ModelCheckerInvariants::validInvariants{
{"contract", InvariantType::Contract}, {"contract", InvariantType::Contract},
{"reentrancy", InvariantType::Reentrancy} {"reentrancy", InvariantType::Reentrancy}
}; };
std::optional<ModelCheckerInvariants> ModelCheckerInvariants::fromString(string const& _invs) std::optional<ModelCheckerInvariants> ModelCheckerInvariants::fromString(std::string const& _invs)
{ {
set<InvariantType> chosenInvs; std::set<InvariantType> chosenInvs;
if (_invs == "default") if (_invs == "default")
{ {
// The default is that no invariants are reported. // The default is that no invariants are reported.
@ -41,7 +40,7 @@ std::optional<ModelCheckerInvariants> ModelCheckerInvariants::fromString(string
for (auto&& v: validInvariants | ranges::views::values) for (auto&& v: validInvariants | ranges::views::values)
chosenInvs.insert(v); chosenInvs.insert(v);
else else
for (auto&& t: _invs | ranges::views::split(',') | ranges::to<vector<string>>()) for (auto&& t: _invs | ranges::views::split(',') | ranges::to<std::vector<std::string>>())
{ {
if (!validInvariants.count(t)) if (!validInvariants.count(t))
return {}; return {};
@ -51,7 +50,7 @@ std::optional<ModelCheckerInvariants> ModelCheckerInvariants::fromString(string
return ModelCheckerInvariants{chosenInvs}; return ModelCheckerInvariants{chosenInvs};
} }
bool ModelCheckerInvariants::setFromString(string const& _inv) bool ModelCheckerInvariants::setFromString(std::string const& _inv)
{ {
if (!validInvariants.count(_inv)) if (!validInvariants.count(_inv))
return false; return false;
@ -60,7 +59,7 @@ bool ModelCheckerInvariants::setFromString(string const& _inv)
} }
using TargetType = VerificationTargetType; using TargetType = VerificationTargetType;
map<string, TargetType> const ModelCheckerTargets::targetStrings{ std::map<std::string, TargetType> const ModelCheckerTargets::targetStrings{
{"constantCondition", TargetType::ConstantCondition}, {"constantCondition", TargetType::ConstantCondition},
{"underflow", TargetType::Underflow}, {"underflow", TargetType::Underflow},
{"overflow", TargetType::Overflow}, {"overflow", TargetType::Overflow},
@ -71,7 +70,7 @@ map<string, TargetType> const ModelCheckerTargets::targetStrings{
{"outOfBounds", TargetType::OutOfBounds} {"outOfBounds", TargetType::OutOfBounds}
}; };
map<TargetType, string> const ModelCheckerTargets::targetTypeToString{ std::map<TargetType, std::string> const ModelCheckerTargets::targetTypeToString{
{TargetType::ConstantCondition, "Constant condition"}, {TargetType::ConstantCondition, "Constant condition"},
{TargetType::Underflow, "Underflow"}, {TargetType::Underflow, "Underflow"},
{TargetType::Overflow, "Overflow"}, {TargetType::Overflow, "Overflow"},
@ -82,9 +81,9 @@ map<TargetType, string> const ModelCheckerTargets::targetTypeToString{
{TargetType::OutOfBounds, "Out of bounds access"} {TargetType::OutOfBounds, "Out of bounds access"}
}; };
std::optional<ModelCheckerTargets> ModelCheckerTargets::fromString(string const& _targets) std::optional<ModelCheckerTargets> ModelCheckerTargets::fromString(std::string const& _targets)
{ {
set<TargetType> chosenTargets; std::set<TargetType> chosenTargets;
if (_targets == "default" || _targets == "all") if (_targets == "default" || _targets == "all")
{ {
bool all = _targets == "all"; bool all = _targets == "all";
@ -96,7 +95,7 @@ std::optional<ModelCheckerTargets> ModelCheckerTargets::fromString(string const&
} }
} }
else else
for (auto&& t: _targets | ranges::views::split(',') | ranges::to<vector<string>>()) for (auto&& t: _targets | ranges::views::split(',') | ranges::to<std::vector<std::string>>())
{ {
if (!targetStrings.count(t)) if (!targetStrings.count(t))
return {}; return {};
@ -106,7 +105,7 @@ std::optional<ModelCheckerTargets> ModelCheckerTargets::fromString(string const&
return ModelCheckerTargets{chosenTargets}; return ModelCheckerTargets{chosenTargets};
} }
bool ModelCheckerTargets::setFromString(string const& _target) bool ModelCheckerTargets::setFromString(std::string const& _target)
{ {
if (!targetStrings.count(_target)) if (!targetStrings.count(_target))
return false; return false;
@ -114,15 +113,15 @@ bool ModelCheckerTargets::setFromString(string const& _target)
return true; return true;
} }
std::optional<ModelCheckerContracts> ModelCheckerContracts::fromString(string const& _contracts) std::optional<ModelCheckerContracts> ModelCheckerContracts::fromString(std::string const& _contracts)
{ {
map<string, set<string>> chosen; std::map<std::string, std::set<std::string>> chosen;
if (_contracts == "default") if (_contracts == "default")
return ModelCheckerContracts::Default(); return ModelCheckerContracts::Default();
for (auto&& sourceContract: _contracts | ranges::views::split(',') | ranges::to<vector<string>>()) for (auto&& sourceContract: _contracts | ranges::views::split(',') | ranges::to<std::vector<std::string>>())
{ {
auto&& names = sourceContract | ranges::views::split(':') | ranges::to<vector<string>>(); auto&& names = sourceContract | ranges::views::split(':') | ranges::to<std::vector<std::string>>();
if (names.size() != 2 || names.at(0).empty() || names.at(1).empty()) if (names.size() != 2 || names.at(0).empty() || names.at(1).empty())
return {}; return {};
chosen[names.at(0)].insert(names.at(1)); chosen[names.at(0)].insert(names.at(1));
@ -131,7 +130,7 @@ std::optional<ModelCheckerContracts> ModelCheckerContracts::fromString(string co
return ModelCheckerContracts{chosen}; return ModelCheckerContracts{chosen};
} }
std::optional<ModelCheckerExtCalls> ModelCheckerExtCalls::fromString(string const& _mode) std::optional<ModelCheckerExtCalls> ModelCheckerExtCalls::fromString(std::string const& _mode)
{ {
if (_mode == "untrusted") if (_mode == "untrusted")
return ModelCheckerExtCalls{Mode::UNTRUSTED}; return ModelCheckerExtCalls{Mode::UNTRUSTED};

View File

@ -31,27 +31,26 @@
#include <range/v3/view.hpp> #include <range/v3/view.hpp>
#include <utility> #include <utility>
using namespace std;
using boost::algorithm::starts_with; using boost::algorithm::starts_with;
using namespace solidity; using namespace solidity;
using namespace solidity::smtutil; using namespace solidity::smtutil;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::frontend::smt; using namespace solidity::frontend::smt;
map<string, Predicate> Predicate::m_predicates; std::map<std::string, Predicate> Predicate::m_predicates;
Predicate const* Predicate::create( Predicate const* Predicate::create(
SortPointer _sort, SortPointer _sort,
string _name, std::string _name,
PredicateType _type, PredicateType _type,
EncodingContext& _context, EncodingContext& _context,
ASTNode const* _node, ASTNode const* _node,
ContractDefinition const* _contractContext, ContractDefinition const* _contractContext,
vector<ScopeOpener const*> _scopeStack std::vector<ScopeOpener const*> _scopeStack
) )
{ {
smt::SymbolicFunctionVariable predicate{_sort, std::move(_name), _context}; smt::SymbolicFunctionVariable predicate{_sort, std::move(_name), _context};
string functorName = predicate.currentName(); std::string functorName = predicate.currentName();
solAssert(!m_predicates.count(functorName), ""); solAssert(!m_predicates.count(functorName), "");
return &m_predicates.emplace( return &m_predicates.emplace(
std::piecewise_construct, std::piecewise_construct,
@ -65,7 +64,7 @@ Predicate::Predicate(
PredicateType _type, PredicateType _type,
ASTNode const* _node, ASTNode const* _node,
ContractDefinition const* _contractContext, ContractDefinition const* _contractContext,
vector<ScopeOpener const*> _scopeStack std::vector<ScopeOpener const*> _scopeStack
): ):
m_predicate(std::move(_predicate)), m_predicate(std::move(_predicate)),
m_type(_type), m_type(_type),
@ -75,7 +74,7 @@ Predicate::Predicate(
{ {
} }
Predicate const* Predicate::predicate(string const& _name) Predicate const* Predicate::predicate(std::string const& _name)
{ {
return &m_predicates.at(_name); return &m_predicates.at(_name);
} }
@ -85,7 +84,7 @@ void Predicate::reset()
m_predicates.clear(); m_predicates.clear();
} }
smtutil::Expression Predicate::operator()(vector<smtutil::Expression> const& _args) const smtutil::Expression Predicate::operator()(std::vector<smtutil::Expression> const& _args) const
{ {
return m_predicate(_args); return m_predicate(_args);
} }
@ -149,12 +148,12 @@ VariableDeclaration const* Predicate::programVariable() const
return dynamic_cast<VariableDeclaration const*>(m_node); return dynamic_cast<VariableDeclaration const*>(m_node);
} }
optional<vector<VariableDeclaration const*>> Predicate::stateVariables() const std::optional<std::vector<VariableDeclaration const*>> Predicate::stateVariables() const
{ {
if (m_contractContext) if (m_contractContext)
return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*m_contractContext); return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*m_contractContext);
return nullopt; return std::nullopt;
} }
bool Predicate::isSummary() const bool Predicate::isSummary() const
@ -211,8 +210,8 @@ bool Predicate::isNondetInterface() const
return m_type == PredicateType::NondetInterface; return m_type == PredicateType::NondetInterface;
} }
string Predicate::formatSummaryCall( std::string Predicate::formatSummaryCall(
vector<smtutil::Expression> const& _args, std::vector<smtutil::Expression> const& _args,
langutil::CharStreamProvider const& _charStreamProvider, langutil::CharStreamProvider const& _charStreamProvider,
bool _appendTxVars bool _appendTxVars
) const ) const
@ -225,7 +224,7 @@ string Predicate::formatSummaryCall(
if (auto funCall = programFunctionCall()) if (auto funCall = programFunctionCall())
{ {
if (funCall->location().hasText()) if (funCall->location().hasText())
return string(_charStreamProvider.charStream(*funCall->location().sourceName).text(funCall->location())); return std::string(_charStreamProvider.charStream(*funCall->location().sourceName).text(funCall->location()));
else else
return {}; return {};
} }
@ -233,11 +232,11 @@ string Predicate::formatSummaryCall(
/// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockChainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars). /// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockChainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
/// Here we are interested in preInputVars to format the function call. /// Here we are interested in preInputVars to format the function call.
string txModel; std::string txModel;
if (_appendTxVars) if (_appendTxVars)
{ {
set<string> txVars; std::set<std::string> txVars;
if (isFunctionSummary()) if (isFunctionSummary())
{ {
solAssert(programFunction(), ""); solAssert(programFunction(), "");
@ -276,7 +275,7 @@ string Predicate::formatSummaryCall(
return true; return true;
} }
set<string> txVars; std::set<std::string> txVars;
} txVarsVisitor; } txVarsVisitor;
if (auto fun = programFunction()) if (auto fun = programFunction())
@ -287,7 +286,7 @@ string Predicate::formatSummaryCall(
// Here we are interested in txData from the summary predicate. // Here we are interested in txData from the summary predicate.
auto txValues = readTxVars(_args.at(4)); auto txValues = readTxVars(_args.at(4));
vector<string> values; std::vector<std::string> values;
for (auto const& _var: txVars) for (auto const& _var: txVars)
if (auto v = txValues.at(_var)) if (auto v = txValues.at(_var))
values.push_back(_var + ": " + *v); values.push_back(_var + ": " + *v);
@ -309,8 +308,8 @@ string Predicate::formatSummaryCall(
solAssert(first >= _args.begin() && first <= _args.end(), ""); solAssert(first >= _args.begin() && first <= _args.end(), "");
solAssert(last >= _args.begin() && last <= _args.end(), ""); solAssert(last >= _args.begin() && last <= _args.end(), "");
auto inTypes = SMTEncoder::replaceUserTypes(FunctionType(*fun).parameterTypes()); auto inTypes = SMTEncoder::replaceUserTypes(FunctionType(*fun).parameterTypes());
vector<optional<string>> functionArgsCex = formatExpressions(vector<smtutil::Expression>(first, last), inTypes); std::vector<std::optional<std::string>> functionArgsCex = formatExpressions(std::vector<smtutil::Expression>(first, last), inTypes);
vector<string> functionArgs; std::vector<std::string> functionArgs;
auto const& params = fun->parameters(); auto const& params = fun->parameters();
solAssert(params.size() == functionArgsCex.size(), ""); solAssert(params.size() == functionArgsCex.size(), "");
@ -320,12 +319,12 @@ string Predicate::formatSummaryCall(
else else
functionArgs.emplace_back(params[i]->name()); functionArgs.emplace_back(params[i]->name());
string fName = fun->isConstructor() ? "constructor" : std::string fName = fun->isConstructor() ? "constructor" :
fun->isFallback() ? "fallback" : fun->isFallback() ? "fallback" :
fun->isReceive() ? "receive" : fun->isReceive() ? "receive" :
fun->name(); fun->name();
string prefix; std::string prefix;
if (fun->isFree()) if (fun->isFree())
prefix = !fun->sourceUnitName().empty() ? (fun->sourceUnitName() + ":") : ""; prefix = !fun->sourceUnitName().empty() ? (fun->sourceUnitName() + ":") : "";
else else
@ -336,7 +335,7 @@ string Predicate::formatSummaryCall(
return prefix + fName + "(" + boost::algorithm::join(functionArgs, ", ") + ")" + txModel; return prefix + fName + "(" + boost::algorithm::join(functionArgs, ", ") + ")" + txModel;
} }
vector<optional<string>> Predicate::summaryStateValues(vector<smtutil::Expression> const& _args) const std::vector<std::optional<std::string>> Predicate::summaryStateValues(std::vector<smtutil::Expression> const& _args) const
{ {
/// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars). /// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
/// The signature of the summary predicate of a contract without constructor is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, postBlockchainState, preStateVars, postStateVars). /// The signature of the summary predicate of a contract without constructor is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, postBlockchainState, preStateVars, postStateVars).
@ -344,8 +343,8 @@ vector<optional<string>> Predicate::summaryStateValues(vector<smtutil::Expressio
auto stateVars = stateVariables(); auto stateVars = stateVariables();
solAssert(stateVars.has_value(), ""); solAssert(stateVars.has_value(), "");
vector<smtutil::Expression>::const_iterator stateFirst; std::vector<smtutil::Expression>::const_iterator stateFirst;
vector<smtutil::Expression>::const_iterator stateLast; std::vector<smtutil::Expression>::const_iterator stateLast;
if (auto const* function = programFunction()) if (auto const* function = programFunction())
{ {
stateFirst = _args.begin() + 6 + static_cast<int>(stateVars->size()) + static_cast<int>(function->parameters().size()) + 1; stateFirst = _args.begin() + 6 + static_cast<int>(stateVars->size()) + static_cast<int>(function->parameters().size()) + 1;
@ -364,13 +363,13 @@ vector<optional<string>> Predicate::summaryStateValues(vector<smtutil::Expressio
solAssert(stateFirst >= _args.begin() && stateFirst <= _args.end(), ""); solAssert(stateFirst >= _args.begin() && stateFirst <= _args.end(), "");
solAssert(stateLast >= _args.begin() && stateLast <= _args.end(), ""); solAssert(stateLast >= _args.begin() && stateLast <= _args.end(), "");
vector<smtutil::Expression> stateArgs(stateFirst, stateLast); std::vector<smtutil::Expression> stateArgs(stateFirst, stateLast);
solAssert(stateArgs.size() == stateVars->size(), ""); solAssert(stateArgs.size() == stateVars->size(), "");
auto stateTypes = util::applyMap(*stateVars, [&](auto const& _var) { return _var->type(); }); auto stateTypes = util::applyMap(*stateVars, [&](auto const& _var) { return _var->type(); });
return formatExpressions(stateArgs, stateTypes); return formatExpressions(stateArgs, stateTypes);
} }
vector<optional<string>> Predicate::summaryPostInputValues(vector<smtutil::Expression> const& _args) const std::vector<std::optional<std::string>> Predicate::summaryPostInputValues(std::vector<smtutil::Expression> const& _args) const
{ {
/// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars). /// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
/// Here we are interested in postInputVars. /// Here we are interested in postInputVars.
@ -388,13 +387,13 @@ vector<optional<string>> Predicate::summaryPostInputValues(vector<smtutil::Expre
solAssert(first >= _args.begin() && first <= _args.end(), ""); solAssert(first >= _args.begin() && first <= _args.end(), "");
solAssert(last >= _args.begin() && last <= _args.end(), ""); solAssert(last >= _args.begin() && last <= _args.end(), "");
vector<smtutil::Expression> inValues(first, last); std::vector<smtutil::Expression> inValues(first, last);
solAssert(inValues.size() == inParams.size(), ""); solAssert(inValues.size() == inParams.size(), "");
auto inTypes = SMTEncoder::replaceUserTypes(FunctionType(*function).parameterTypes()); auto inTypes = SMTEncoder::replaceUserTypes(FunctionType(*function).parameterTypes());
return formatExpressions(inValues, inTypes); return formatExpressions(inValues, inTypes);
} }
vector<optional<string>> Predicate::summaryPostOutputValues(vector<smtutil::Expression> const& _args) const std::vector<std::optional<std::string>> Predicate::summaryPostOutputValues(std::vector<smtutil::Expression> const& _args) const
{ {
/// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars). /// The signature of a function summary predicate is: summary(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars).
/// Here we are interested in outputVars. /// Here we are interested in outputVars.
@ -410,13 +409,13 @@ vector<optional<string>> Predicate::summaryPostOutputValues(vector<smtutil::Expr
solAssert(first >= _args.begin() && first <= _args.end(), ""); solAssert(first >= _args.begin() && first <= _args.end(), "");
vector<smtutil::Expression> outValues(first, _args.end()); std::vector<smtutil::Expression> outValues(first, _args.end());
solAssert(outValues.size() == function->returnParameters().size(), ""); solAssert(outValues.size() == function->returnParameters().size(), "");
auto outTypes = SMTEncoder::replaceUserTypes(FunctionType(*function).returnParameterTypes()); auto outTypes = SMTEncoder::replaceUserTypes(FunctionType(*function).returnParameterTypes());
return formatExpressions(outValues, outTypes); return formatExpressions(outValues, outTypes);
} }
pair<vector<optional<string>>, vector<VariableDeclaration const*>> Predicate::localVariableValues(vector<smtutil::Expression> const& _args) const std::pair<std::vector<std::optional<std::string>>, std::vector<VariableDeclaration const*>> Predicate::localVariableValues(std::vector<smtutil::Expression> const& _args) const
{ {
/// The signature of a local block predicate is: /// The signature of a local block predicate is:
/// block(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars, localVars). /// block(error, this, abiFunctions, cryptoFunctions, txData, preBlockchainState, preStateVars, preInputVars, postBlockchainState, postStateVars, postInputVars, outputVars, localVars).
@ -426,7 +425,7 @@ pair<vector<optional<string>>, vector<VariableDeclaration const*>> Predicate::lo
auto const& localVars = SMTEncoder::localVariablesIncludingModifiers(*function, m_contractContext); auto const& localVars = SMTEncoder::localVariablesIncludingModifiers(*function, m_contractContext);
auto first = _args.end() - static_cast<int>(localVars.size()); auto first = _args.end() - static_cast<int>(localVars.size());
vector<smtutil::Expression> outValues(first, _args.end()); std::vector<smtutil::Expression> outValues(first, _args.end());
auto mask = util::applyMap( auto mask = util::applyMap(
localVars, localVars,
@ -442,10 +441,10 @@ pair<vector<optional<string>>, vector<VariableDeclaration const*>> Predicate::lo
return {formatExpressions(outValuesInScope, outTypes), localVarsInScope}; return {formatExpressions(outValuesInScope, outTypes), localVarsInScope};
} }
map<string, string> Predicate::expressionSubstitution(smtutil::Expression const& _predExpr) const std::map<std::string, std::string> Predicate::expressionSubstitution(smtutil::Expression const& _predExpr) const
{ {
map<string, string> subst; std::map<std::string, std::string> subst;
string predName = functor().name; std::string predName = functor().name;
solAssert(contextContract(), ""); solAssert(contextContract(), "");
auto const& stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*contextContract()); auto const& stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*contextContract());
@ -486,16 +485,16 @@ map<string, string> Predicate::expressionSubstitution(smtutil::Expression const&
return subst; return subst;
} }
vector<optional<string>> Predicate::formatExpressions(vector<smtutil::Expression> const& _exprs, vector<Type const*> const& _types) const std::vector<std::optional<std::string>> Predicate::formatExpressions(std::vector<smtutil::Expression> const& _exprs, std::vector<Type const*> const& _types) const
{ {
solAssert(_exprs.size() == _types.size(), ""); solAssert(_exprs.size() == _types.size(), "");
vector<optional<string>> strExprs; std::vector<std::optional<std::string>> strExprs;
for (unsigned i = 0; i < _exprs.size(); ++i) for (unsigned i = 0; i < _exprs.size(); ++i)
strExprs.push_back(expressionToString(_exprs.at(i), _types.at(i))); strExprs.push_back(expressionToString(_exprs.at(i), _types.at(i)));
return strExprs; return strExprs;
} }
optional<string> Predicate::expressionToString(smtutil::Expression const& _expr, Type const* _type) const std::optional<std::string> Predicate::expressionToString(smtutil::Expression const& _expr, Type const* _type) const
{ {
if (smt::isNumber(*_type)) if (smt::isNumber(*_type))
{ {
@ -514,10 +513,10 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
// For some reason the code below returns "0x" for "0". // For some reason the code below returns "0x" for "0".
return util::toHex(toCompactBigEndian(bigint(_expr.name)), util::HexPrefix::Add, util::HexCase::Lower); return util::toHex(toCompactBigEndian(bigint(_expr.name)), util::HexPrefix::Add, util::HexCase::Lower);
} }
catch (out_of_range const&) catch (std::out_of_range const&)
{ {
} }
catch (invalid_argument const&) catch (std::invalid_argument const&)
{ {
} }
} }
@ -550,11 +549,11 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
{ {
length = stoul(_expr.arguments.at(1).name); length = stoul(_expr.arguments.at(1).name);
} }
catch(out_of_range const&) catch(std::out_of_range const&)
{ {
return {}; return {};
} }
catch(invalid_argument const&) catch(std::invalid_argument const&)
{ {
return {}; return {};
} }
@ -567,12 +566,12 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
return {}; return {};
try try
{ {
vector<string> array(length); std::vector<std::string> array(length);
if (!fillArray(_expr.arguments.at(0), array, arrayType)) if (!fillArray(_expr.arguments.at(0), array, arrayType))
return {}; return {};
return "[" + boost::algorithm::join(array, ", ") + "]"; return "[" + boost::algorithm::join(array, ", ") + "]";
} }
catch (bad_alloc const&) catch (std::bad_alloc const&)
{ {
// Solver gave a concrete array but length is too large. // Solver gave a concrete array but length is too large.
} }
@ -585,10 +584,10 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
auto members = structType.structDefinition().members(); auto members = structType.structDefinition().members();
solAssert(tupleSort.components.size() == members.size(), ""); solAssert(tupleSort.components.size() == members.size(), "");
solAssert(_expr.arguments.size() == members.size(), ""); solAssert(_expr.arguments.size() == members.size(), "");
vector<string> elements; std::vector<std::string> elements;
for (unsigned i = 0; i < members.size(); ++i) for (unsigned i = 0; i < members.size(); ++i)
{ {
optional<string> elementStr = expressionToString(_expr.arguments.at(i), members[i]->type()); std::optional<std::string> elementStr = expressionToString(_expr.arguments.at(i), members[i]->type());
elements.push_back(members[i]->name() + (elementStr.has_value() ? ": " + elementStr.value() : "")); elements.push_back(members[i]->name() + (elementStr.has_value() ? ": " + elementStr.value() : ""));
} }
return "{" + boost::algorithm::join(elements, ", ") + "}"; return "{" + boost::algorithm::join(elements, ", ") + "}";
@ -597,13 +596,13 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
return {}; return {};
} }
bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _array, ArrayType const& _type) const bool Predicate::fillArray(smtutil::Expression const& _expr, std::vector<std::string>& _array, ArrayType const& _type) const
{ {
// Base case // Base case
if (_expr.name == "const_array") if (_expr.name == "const_array")
{ {
auto length = _array.size(); auto length = _array.size();
optional<string> elemStr = expressionToString(_expr.arguments.at(1), _type.baseType()); std::optional<std::string> elemStr = expressionToString(_expr.arguments.at(1), _type.baseType());
if (!elemStr) if (!elemStr)
return false; return false;
_array.clear(); _array.clear();
@ -616,7 +615,7 @@ bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _arr
{ {
if (!fillArray(_expr.arguments.at(0), _array, _type)) if (!fillArray(_expr.arguments.at(0), _array, _type))
return false; return false;
optional<string> indexStr = expressionToString(_expr.arguments.at(1), TypeProvider::uint256()); std::optional<std::string> indexStr = expressionToString(_expr.arguments.at(1), TypeProvider::uint256());
if (!indexStr) if (!indexStr)
return false; return false;
// Sometimes the solver assigns huge lengths that are not related, // Sometimes the solver assigns huge lengths that are not related,
@ -626,15 +625,15 @@ bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _arr
{ {
index = stoul(*indexStr); index = stoul(*indexStr);
} }
catch (out_of_range const&) catch (std::out_of_range const&)
{ {
return true; return true;
} }
catch (invalid_argument const&) catch (std::invalid_argument const&)
{ {
return true; return true;
} }
optional<string> elemStr = expressionToString(_expr.arguments.at(2), _type.baseType()); std::optional<std::string> elemStr = expressionToString(_expr.arguments.at(2), _type.baseType());
if (!elemStr) if (!elemStr)
return false; return false;
if (index < _array.size()) if (index < _array.size())
@ -652,9 +651,9 @@ bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _arr
solAssert(false, ""); solAssert(false, "");
} }
map<string, optional<string>> Predicate::readTxVars(smtutil::Expression const& _tx) const std::map<std::string, std::optional<std::string>> Predicate::readTxVars(smtutil::Expression const& _tx) const
{ {
map<string, Type const*> const txVars{ std::map<std::string, Type const*> const txVars{
{"block.basefee", TypeProvider::uint256()}, {"block.basefee", TypeProvider::uint256()},
{"block.chainid", TypeProvider::uint256()}, {"block.chainid", TypeProvider::uint256()},
{"block.coinbase", TypeProvider::address()}, {"block.coinbase", TypeProvider::address()},
@ -670,7 +669,7 @@ map<string, optional<string>> Predicate::readTxVars(smtutil::Expression const& _
{"tx.gasprice", TypeProvider::uint256()}, {"tx.gasprice", TypeProvider::uint256()},
{"tx.origin", TypeProvider::address()} {"tx.origin", TypeProvider::address()}
}; };
map<string, optional<string>> vars; std::map<std::string, std::optional<std::string>> vars;
for (auto&& [i, v]: txVars | ranges::views::enumerate) for (auto&& [i, v]: txVars | ranges::views::enumerate)
vars.emplace(v.first, expressionToString(_tx.arguments.at(i), v.second)); vars.emplace(v.first, expressionToString(_tx.arguments.at(i), v.second));
return vars; return vars;

View File

@ -21,7 +21,6 @@
#include <libsolidity/formal/EncodingContext.h> #include <libsolidity/formal/EncodingContext.h>
#include <libsolidity/formal/SMTEncoder.h> #include <libsolidity/formal/SMTEncoder.h>
using namespace std;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::smtutil; using namespace solidity::smtutil;
@ -30,14 +29,14 @@ namespace solidity::frontend::smt
smtutil::Expression interfacePre(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context) smtutil::Expression interfacePre(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
{ {
auto& state = _context.state(); auto& state = _context.state();
vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.abi(0), state.crypto(0), state.state(0)}; std::vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.abi(0), state.crypto(0), state.state(0)};
return _pred(stateExprs + initialStateVariables(_contract, _context)); return _pred(stateExprs + initialStateVariables(_contract, _context));
} }
smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context) smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
{ {
auto const& state = _context.state(); auto const& state = _context.state();
vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.abi(0), state.crypto(0), state.state()}; std::vector<smtutil::Expression> stateExprs{state.thisAddress(0), state.abi(0), state.crypto(0), state.state()};
return _pred(stateExprs + currentStateVariables(_contract, _context)); return _pred(stateExprs + currentStateVariables(_contract, _context));
} }
@ -49,12 +48,12 @@ smtutil::Expression nondetInterface(
unsigned _postIdx) unsigned _postIdx)
{ {
auto const& state = _context.state(); auto const& state = _context.state();
vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(), state.abi(), state.crypto()}; std::vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(), state.abi(), state.crypto()};
return _pred( return _pred(
stateExprs + stateExprs +
vector<smtutil::Expression>{_context.state().state(_preIdx)} + std::vector<smtutil::Expression>{_context.state().state(_preIdx)} +
stateVariablesAtIndex(_preIdx, _contract, _context) + stateVariablesAtIndex(_preIdx, _contract, _context) +
vector<smtutil::Expression>{_context.state().state(_postIdx)} + std::vector<smtutil::Expression>{_context.state().state(_postIdx)} +
stateVariablesAtIndex(_postIdx, _contract, _context) stateVariablesAtIndex(_postIdx, _contract, _context)
); );
} }
@ -66,7 +65,7 @@ smtutil::Expression constructor(Predicate const& _pred, EncodingContext& _contex
return _pred(currentFunctionVariablesForDefinition(*constructor, &contract, _context)); return _pred(currentFunctionVariablesForDefinition(*constructor, &contract, _context));
auto& state = _context.state(); auto& state = _context.state();
vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state(0), state.state()}; std::vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state(0), state.state()};
return _pred(stateExprs + initialStateVariables(contract, _context) + currentStateVariables(contract, _context)); return _pred(stateExprs + initialStateVariables(contract, _context) + currentStateVariables(contract, _context));
} }
@ -77,9 +76,9 @@ smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _co
return _pred(currentFunctionVariablesForCall(*constructor, &contract, _context, _internal)); return _pred(currentFunctionVariablesForCall(*constructor, &contract, _context, _internal));
auto& state = _context.state(); auto& state = _context.state();
vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), _internal ? state.thisAddress(0) : state.thisAddress(), state.abi(0), state.crypto(0), _internal ? state.tx(0) : state.tx(), state.state()}; std::vector<smtutil::Expression> stateExprs{state.errorFlag().currentValue(), _internal ? state.thisAddress(0) : state.thisAddress(), state.abi(0), state.crypto(0), _internal ? state.tx(0) : state.tx(), state.state()};
state.newState(); state.newState();
stateExprs += vector<smtutil::Expression>{state.state()}; stateExprs += std::vector<smtutil::Expression>{state.state()};
stateExprs += currentStateVariables(contract, _context); stateExprs += currentStateVariables(contract, _context);
stateExprs += newStateVariables(contract, _context); stateExprs += newStateVariables(contract, _context);
return _pred(stateExprs); return _pred(stateExprs);
@ -117,12 +116,12 @@ smtutil::Expression functionBlock(
/// Helpers /// Helpers
vector<smtutil::Expression> initialStateVariables(ContractDefinition const& _contract, EncodingContext& _context) std::vector<smtutil::Expression> initialStateVariables(ContractDefinition const& _contract, EncodingContext& _context)
{ {
return stateVariablesAtIndex(0, _contract, _context); return stateVariablesAtIndex(0, _contract, _context);
} }
vector<smtutil::Expression> stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract, EncodingContext& _context) std::vector<smtutil::Expression> stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract, EncodingContext& _context)
{ {
return applyMap( return applyMap(
SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract),
@ -130,7 +129,7 @@ vector<smtutil::Expression> stateVariablesAtIndex(unsigned _index, ContractDefin
); );
} }
vector<smtutil::Expression> currentStateVariables(ContractDefinition const& _contract, EncodingContext& _context) std::vector<smtutil::Expression> currentStateVariables(ContractDefinition const& _contract, EncodingContext& _context)
{ {
return applyMap( return applyMap(
SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract),
@ -138,7 +137,7 @@ vector<smtutil::Expression> currentStateVariables(ContractDefinition const& _con
); );
} }
vector<smtutil::Expression> newStateVariables(ContractDefinition const& _contract, EncodingContext& _context) std::vector<smtutil::Expression> newStateVariables(ContractDefinition const& _contract, EncodingContext& _context)
{ {
return applyMap( return applyMap(
SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract),
@ -146,24 +145,24 @@ vector<smtutil::Expression> newStateVariables(ContractDefinition const& _contrac
); );
} }
vector<smtutil::Expression> currentFunctionVariablesForDefinition( std::vector<smtutil::Expression> currentFunctionVariablesForDefinition(
FunctionDefinition const& _function, FunctionDefinition const& _function,
ContractDefinition const* _contract, ContractDefinition const* _contract,
EncodingContext& _context EncodingContext& _context
) )
{ {
auto& state = _context.state(); auto& state = _context.state();
vector<smtutil::Expression> exprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state(0)}; std::vector<smtutil::Expression> exprs{state.errorFlag().currentValue(), state.thisAddress(0), state.abi(0), state.crypto(0), state.tx(0), state.state(0)};
exprs += _contract ? initialStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; exprs += _contract ? initialStateVariables(*_contract, _context) : std::vector<smtutil::Expression>{};
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->valueAtIndex(0); }); exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->valueAtIndex(0); });
exprs += vector<smtutil::Expression>{state.state()}; exprs += std::vector<smtutil::Expression>{state.state()};
exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; exprs += _contract ? currentStateVariables(*_contract, _context) : std::vector<smtutil::Expression>{};
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
return exprs; return exprs;
} }
vector<smtutil::Expression> currentFunctionVariablesForCall( std::vector<smtutil::Expression> currentFunctionVariablesForCall(
FunctionDefinition const& _function, FunctionDefinition const& _function,
ContractDefinition const* _contract, ContractDefinition const* _contract,
EncodingContext& _context, EncodingContext& _context,
@ -171,20 +170,20 @@ vector<smtutil::Expression> currentFunctionVariablesForCall(
) )
{ {
auto& state = _context.state(); auto& state = _context.state();
vector<smtutil::Expression> exprs{state.errorFlag().currentValue(), _internal ? state.thisAddress(0) : state.thisAddress(), state.abi(0), state.crypto(0), _internal ? state.tx(0) : state.tx(), state.state()}; std::vector<smtutil::Expression> exprs{state.errorFlag().currentValue(), _internal ? state.thisAddress(0) : state.thisAddress(), state.abi(0), state.crypto(0), _internal ? state.tx(0) : state.tx(), state.state()};
exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; exprs += _contract ? currentStateVariables(*_contract, _context) : std::vector<smtutil::Expression>{};
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
state.newState(); state.newState();
exprs += vector<smtutil::Expression>{state.state()}; exprs += std::vector<smtutil::Expression>{state.state()};
exprs += _contract ? newStateVariables(*_contract, _context) : vector<smtutil::Expression>{}; exprs += _contract ? newStateVariables(*_contract, _context) : std::vector<smtutil::Expression>{};
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->increaseIndex(); }); exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->increaseIndex(); });
exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); }); exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
return exprs; return exprs;
} }
vector<smtutil::Expression> currentBlockVariables(FunctionDefinition const& _function, ContractDefinition const* _contract, EncodingContext& _context) std::vector<smtutil::Expression> currentBlockVariables(FunctionDefinition const& _function, ContractDefinition const* _contract, EncodingContext& _context)
{ {
return currentFunctionVariablesForDefinition(_function, _contract, _context) + return currentFunctionVariablesForDefinition(_function, _contract, _context) +
applyMap( applyMap(

View File

@ -21,7 +21,6 @@
#include <libsolidity/formal/SMTEncoder.h> #include <libsolidity/formal/SMTEncoder.h>
#include <libsolidity/formal/SymbolicTypes.h> #include <libsolidity/formal/SymbolicTypes.h>
using namespace std;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::smtutil; using namespace solidity::smtutil;
@ -30,8 +29,8 @@ namespace solidity::frontend::smt
SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _state) SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _state)
{ {
return make_shared<FunctionSort>( return std::make_shared<FunctionSort>(
vector<SortPointer>{_state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.stateSort()} + stateSorts(_contract), std::vector<SortPointer>{_state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.stateSort()} + stateSorts(_contract),
SortProvider::boolSort SortProvider::boolSort
); );
} }
@ -39,9 +38,9 @@ SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _s
SortPointer nondetInterfaceSort(ContractDefinition const& _contract, SymbolicState& _state) SortPointer nondetInterfaceSort(ContractDefinition const& _contract, SymbolicState& _state)
{ {
auto varSorts = stateSorts(_contract); auto varSorts = stateSorts(_contract);
vector<SortPointer> stateSort{_state.stateSort()}; std::vector<SortPointer> stateSort{_state.stateSort()};
return make_shared<FunctionSort>( return std::make_shared<FunctionSort>(
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort()} + std::vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort()} +
stateSort + stateSort +
varSorts + varSorts +
stateSort + stateSort +
@ -56,9 +55,9 @@ SortPointer constructorSort(ContractDefinition const& _contract, SymbolicState&
return functionSort(*constructor, &_contract, _state); return functionSort(*constructor, &_contract, _state);
auto varSorts = stateSorts(_contract); auto varSorts = stateSorts(_contract);
vector<SortPointer> stateSort{_state.stateSort()}; std::vector<SortPointer> stateSort{_state.stateSort()};
return make_shared<FunctionSort>( return std::make_shared<FunctionSort>(
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort(), _state.stateSort()} + varSorts + varSorts, std::vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort(), _state.stateSort()} + varSorts + varSorts,
SortProvider::boolSort SortProvider::boolSort
); );
} }
@ -66,14 +65,14 @@ SortPointer constructorSort(ContractDefinition const& _contract, SymbolicState&
SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state) SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state)
{ {
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); }; auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
auto varSorts = _contract ? stateSorts(*_contract) : vector<SortPointer>{}; auto varSorts = _contract ? stateSorts(*_contract) : std::vector<SortPointer>{};
auto inputSorts = applyMap(_function.parameters(), smtSort); auto inputSorts = applyMap(_function.parameters(), smtSort);
auto outputSorts = applyMap(_function.returnParameters(), smtSort); auto outputSorts = applyMap(_function.returnParameters(), smtSort);
return make_shared<FunctionSort>( return std::make_shared<FunctionSort>(
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort()} + std::vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort()} +
varSorts + varSorts +
inputSorts + inputSorts +
vector<SortPointer>{_state.stateSort()} + std::vector<SortPointer>{_state.stateSort()} +
varSorts + varSorts +
inputSorts + inputSorts +
outputSorts, outputSorts,
@ -83,11 +82,11 @@ SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition
SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state) SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state)
{ {
auto fSort = dynamic_pointer_cast<FunctionSort>(functionSort(_function, _contract, _state)); auto fSort = std::dynamic_pointer_cast<FunctionSort>(functionSort(_function, _contract, _state));
solAssert(fSort, ""); solAssert(fSort, "");
auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); }; auto smtSort = [](auto _var) { return smt::smtSortAbstractFunction(*_var->type()); };
return make_shared<FunctionSort>( return std::make_shared<FunctionSort>(
fSort->domain + applyMap(SMTEncoder::localVariablesIncludingModifiers(_function, _contract), smtSort), fSort->domain + applyMap(SMTEncoder::localVariablesIncludingModifiers(_function, _contract), smtSort),
SortProvider::boolSort SortProvider::boolSort
); );
@ -95,15 +94,15 @@ SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefini
SortPointer arity0FunctionSort() SortPointer arity0FunctionSort()
{ {
return make_shared<FunctionSort>( return std::make_shared<FunctionSort>(
vector<SortPointer>(), std::vector<SortPointer>(),
SortProvider::boolSort SortProvider::boolSort
); );
} }
/// Helpers /// Helpers
vector<SortPointer> stateSorts(ContractDefinition const& _contract) std::vector<SortPointer> stateSorts(ContractDefinition const& _contract)
{ {
return applyMap( return applyMap(
SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract),

View File

@ -40,11 +40,11 @@
#include <limits> #include <limits>
#include <deque> #include <deque>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace std::string_literals;
SMTEncoder::SMTEncoder( SMTEncoder::SMTEncoder(
smt::EncodingContext& _context, smt::EncodingContext& _context,
@ -72,8 +72,8 @@ bool SMTEncoder::visit(ContractDefinition const& _contract)
for (auto const& node: _contract.subNodes()) for (auto const& node: _contract.subNodes())
if ( if (
!dynamic_pointer_cast<FunctionDefinition>(node) && !std::dynamic_pointer_cast<FunctionDefinition>(node) &&
!dynamic_pointer_cast<VariableDeclaration>(node) !std::dynamic_pointer_cast<VariableDeclaration>(node)
) )
node->accept(*this); node->accept(*this);
@ -198,7 +198,7 @@ void SMTEncoder::inlineModifierInvocation(ModifierInvocation const* _invocation,
solAssert(_invocation, ""); solAssert(_invocation, "");
_invocation->accept(*this); _invocation->accept(*this);
vector<smtutil::Expression> args; std::vector<smtutil::Expression> args;
if (auto const* arguments = _invocation->arguments()) if (auto const* arguments = _invocation->arguments())
{ {
auto const& modifierParams = _definition->parameters(); auto const& modifierParams = _definition->parameters();
@ -314,8 +314,8 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm)
this->operator()(_inlineAsm.operations()); this->operator()(_inlineAsm.operations());
} }
map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> const& externalReferences; std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> const& externalReferences;
set<VariableDeclaration const*> assignedVars; std::set<VariableDeclaration const*> assignedVars;
using yul::ASTWalker::operator(); using yul::ASTWalker::operator();
void operator()(yul::Assignment const& _assignment) void operator()(yul::Assignment const& _assignment)
@ -425,14 +425,14 @@ void SMTEncoder::endVisit(TupleExpression const& _tuple)
if (_tuple.isInlineArray()) if (_tuple.isInlineArray())
{ {
// Add constraints for the length and values as it is known. // Add constraints for the length and values as it is known.
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_tuple)); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_tuple));
solAssert(symbArray, ""); solAssert(symbArray, "");
addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c); })); addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c); }));
} }
else else
{ {
auto values = applyMap(_tuple.components(), [this](auto const& component) -> optional<smtutil::Expression> { auto values = applyMap(_tuple.components(), [this](auto const& component) -> std::optional<smtutil::Expression> {
if (component) if (component)
{ {
if (!m_context.knownExpression(*component)) if (!m_context.knownExpression(*component))
@ -816,19 +816,19 @@ void SMTEncoder::visitABIFunction(FunctionCall const& _funCall)
defineExpr(_funCall, smt::zeroValue(TypeProvider::bytesMemory())); defineExpr(_funCall, smt::zeroValue(TypeProvider::bytesMemory()));
return; return;
} }
vector<smtutil::Expression> symbArgs; std::vector<smtutil::Expression> symbArgs;
for (unsigned i = 0; i < argsActualLength; ++i) for (unsigned i = 0; i < argsActualLength; ++i)
if (args.at(i)) if (args.at(i))
symbArgs.emplace_back(expr(*args.at(i), inTypes.at(i))); symbArgs.emplace_back(expr(*args.at(i), inTypes.at(i)));
optional<smtutil::Expression> arg; std::optional<smtutil::Expression> arg;
if (inTypes.size() == 1) if (inTypes.size() == 1)
arg = expr(*args.at(0), inTypes.at(0)); arg = expr(*args.at(0), inTypes.at(0));
else else
{ {
auto inputSort = dynamic_cast<smtutil::ArraySort&>(*symbFunction.sort).domain; auto inputSort = dynamic_cast<smtutil::ArraySort&>(*symbFunction.sort).domain;
arg = smtutil::Expression::tuple_constructor( arg = smtutil::Expression::tuple_constructor(
smtutil::Expression(make_shared<smtutil::SortSort>(inputSort), ""), smtutil::Expression(std::make_shared<smtutil::SortSort>(inputSort), ""),
symbArgs symbArgs
); );
} }
@ -838,7 +838,7 @@ void SMTEncoder::visitABIFunction(FunctionCall const& _funCall)
defineExpr(_funCall, out); defineExpr(_funCall, out);
else else
{ {
auto symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_funCall)); auto symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_funCall));
solAssert(symbTuple, ""); solAssert(symbTuple, "");
solAssert(symbTuple->components().size() == outTypes.size(), ""); solAssert(symbTuple->components().size() == outTypes.size(), "");
solAssert(out.sort->kind == smtutil::Kind::Tuple, ""); solAssert(out.sort->kind == smtutil::Kind::Tuple, "");
@ -854,7 +854,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type); auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
auto kind = funType.kind(); auto kind = funType.kind();
auto arg0 = expr(*_funCall.arguments().at(0)); auto arg0 = expr(*_funCall.arguments().at(0));
optional<smtutil::Expression> result; std::optional<smtutil::Expression> result;
if (kind == FunctionType::Kind::KECCAK256) if (kind == FunctionType::Kind::KECCAK256)
result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0); result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0);
else if (kind == FunctionType::Kind::SHA256) else if (kind == FunctionType::Kind::SHA256)
@ -870,7 +870,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
auto arg3 = expr(*_funCall.arguments().at(3)); auto arg3 = expr(*_funCall.arguments().at(3));
auto inputSort = dynamic_cast<smtutil::ArraySort&>(*e.sort).domain; auto inputSort = dynamic_cast<smtutil::ArraySort&>(*e.sort).domain;
auto ecrecoverInput = smtutil::Expression::tuple_constructor( auto ecrecoverInput = smtutil::Expression::tuple_constructor(
smtutil::Expression(make_shared<smtutil::SortSort>(inputSort), ""), smtutil::Expression(std::make_shared<smtutil::SortSort>(inputSort), ""),
{arg0, arg1, arg2, arg3} {arg0, arg1, arg2, arg3}
); );
result = smtutil::Expression::select(e, ecrecoverInput); result = smtutil::Expression::select(e, ecrecoverInput);
@ -883,7 +883,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
void SMTEncoder::visitGasLeft(FunctionCall const& _funCall) void SMTEncoder::visitGasLeft(FunctionCall const& _funCall)
{ {
string gasLeft = "gasleft"; std::string gasLeft = "gasleft";
// We increase the variable index since gasleft changes // We increase the variable index since gasleft changes
// inside a tx. // inside a tx.
defineGlobalVariable(gasLeft, _funCall, true); defineGlobalVariable(gasLeft, _funCall, true);
@ -930,7 +930,7 @@ void SMTEncoder::visitObjectCreation(FunctionCall const& _funCall)
smtutil::Expression arraySize = expr(*args.front()); smtutil::Expression arraySize = expr(*args.front());
setSymbolicUnknownValue(arraySize, TypeProvider::uint256(), m_context); setSymbolicUnknownValue(arraySize, TypeProvider::uint256(), m_context);
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_funCall)); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_funCall));
solAssert(symbArray, ""); solAssert(symbArray, "");
smt::setSymbolicZeroValue(*symbArray, m_context); smt::setSymbolicZeroValue(*symbArray, m_context);
auto zeroElements = symbArray->elements(); auto zeroElements = symbArray->elements();
@ -1004,9 +1004,9 @@ bool isReturnedFromStructGetter(Type const* _type)
return true; return true;
} }
vector<string> structGetterReturnedMembers(StructType const& _structType) std::vector<std::string> structGetterReturnedMembers(StructType const& _structType)
{ {
vector<string> returnedMembers; std::vector<std::string> returnedMembers;
for (auto const& member: _structType.nativeMembers(nullptr)) for (auto const& member: _structType.nativeMembers(nullptr))
if (isReturnedFromStructGetter(member.type)) if (isReturnedFromStructGetter(member.type))
returnedMembers.push_back(member.name); returnedMembers.push_back(member.name);
@ -1023,7 +1023,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
auto paramExpectedTypes = replaceUserTypes(FunctionType(*var).parameterTypes()); auto paramExpectedTypes = replaceUserTypes(FunctionType(*var).parameterTypes());
auto actualArguments = _funCall.arguments(); auto actualArguments = _funCall.arguments();
solAssert(actualArguments.size() == paramExpectedTypes.size(), ""); solAssert(actualArguments.size() == paramExpectedTypes.size(), "");
deque<smtutil::Expression> symbArguments; std::deque<smtutil::Expression> symbArguments;
for (unsigned i = 0; i < paramExpectedTypes.size(); ++i) for (unsigned i = 0; i < paramExpectedTypes.size(); ++i)
symbArguments.push_back(expr(*actualArguments[i], paramExpectedTypes[i])); symbArguments.push_back(expr(*actualArguments[i], paramExpectedTypes[i]));
@ -1063,11 +1063,11 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
case Type::Category::Struct: case Type::Category::Struct:
{ {
solAssert(symbArguments.empty(), ""); solAssert(symbArguments.empty(), "");
smt::SymbolicStructVariable structVar(dynamic_cast<StructType const*>(type), "struct_temp_" + to_string(_funCall.id()), m_context); smt::SymbolicStructVariable structVar(dynamic_cast<StructType const*>(type), "struct_temp_" + std::to_string(_funCall.id()), m_context);
m_context.addAssertion(structVar.currentValue() == currentExpr); m_context.addAssertion(structVar.currentValue() == currentExpr);
auto returnedMembers = structGetterReturnedMembers(dynamic_cast<StructType const&>(*structVar.type())); auto returnedMembers = structGetterReturnedMembers(dynamic_cast<StructType const&>(*structVar.type()));
solAssert(!returnedMembers.empty(), ""); solAssert(!returnedMembers.empty(), "");
auto returnedValues = applyMap(returnedMembers, [&](string const& memberName) -> optional<smtutil::Expression> { return structVar.member(memberName); }); auto returnedValues = applyMap(returnedMembers, [&](std::string const& memberName) -> std::optional<smtutil::Expression> { return structVar.member(memberName); });
defineExpr(_funCall, returnedValues); defineExpr(_funCall, returnedValues);
return; return;
} }
@ -1118,7 +1118,7 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
if (arrayType && arrayType->isByteArrayOrString() && smt::isFixedBytes(*funCallType)) if (arrayType && arrayType->isByteArrayOrString() && smt::isFixedBytes(*funCallType))
{ {
auto array = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*argument)); auto array = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*argument));
bytesToFixedBytesAssertions(*array, _funCall); bytesToFixedBytesAssertions(*array, _funCall);
return; return;
} }
@ -1129,8 +1129,8 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
unsigned castSize = funCallType->storageBytes(); unsigned castSize = funCallType->storageBytes();
bool castIsSigned = smt::isNumber(*funCallType) && smt::isSigned(funCallType); bool castIsSigned = smt::isNumber(*funCallType) && smt::isSigned(funCallType);
bool argIsSigned = smt::isNumber(*argType) && smt::isSigned(argType); bool argIsSigned = smt::isNumber(*argType) && smt::isSigned(argType);
optional<smtutil::Expression> symbMin; std::optional<smtutil::Expression> symbMin;
optional<smtutil::Expression> symbMax; std::optional<smtutil::Expression> symbMax;
if (smt::isNumber(*funCallType)) if (smt::isNumber(*funCallType))
{ {
symbMin = smt::minValue(funCallType); symbMin = smt::minValue(funCallType);
@ -1285,7 +1285,7 @@ void SMTEncoder::endVisit(Literal const& _literal)
createExpr(_literal); createExpr(_literal);
// Add constraints for the length and values as it is known. // Add constraints for the length and values as it is known.
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_literal)); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_literal));
solAssert(symbArray, ""); solAssert(symbArray, "");
addArrayLiteralAssertions( addArrayLiteralAssertions(
@ -1299,7 +1299,7 @@ void SMTEncoder::endVisit(Literal const& _literal)
void SMTEncoder::addArrayLiteralAssertions( void SMTEncoder::addArrayLiteralAssertions(
smt::SymbolicArrayVariable& _symArray, smt::SymbolicArrayVariable& _symArray,
vector<smtutil::Expression> const& _elementValues std::vector<smtutil::Expression> const& _elementValues
) )
{ {
m_context.addAssertion(_symArray.length() == _elementValues.size()); m_context.addAssertion(_symArray.length() == _elementValues.size());
@ -1314,7 +1314,7 @@ void SMTEncoder::bytesToFixedBytesAssertions(
{ {
auto const& fixed = dynamic_cast<FixedBytesType const&>(*_fixedBytes.annotation().type); auto const& fixed = dynamic_cast<FixedBytesType const&>(*_fixedBytes.annotation().type);
auto intType = TypeProvider::uint256(); auto intType = TypeProvider::uint256();
string suffix = to_string(_fixedBytes.id()) + "_" + to_string(m_context.newUniqueId()); std::string suffix = std::to_string(_fixedBytes.id()) + "_" + std::to_string(m_context.newUniqueId());
smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context); smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context);
m_context.addAssertion(k.currentValue() == 0); m_context.addAssertion(k.currentValue() == 0);
size_t n = fixed.numBytes(); size_t n = fixed.numBytes();
@ -1333,7 +1333,7 @@ void SMTEncoder::endVisit(Return const& _return)
auto returnParams = m_callStack.back().first->returnParameters(); auto returnParams = m_callStack.back().first->returnParameters();
if (returnParams.size() > 1) if (returnParams.size() > 1)
{ {
auto const& symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(*_return.expression())); auto const& symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(*_return.expression()));
solAssert(symbTuple, ""); solAssert(symbTuple, "");
solAssert(symbTuple->components().size() == returnParams.size(), ""); solAssert(symbTuple->components().size() == returnParams.size(), "");
@ -1428,7 +1428,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
else if (smt::isNonRecursiveStruct(*exprType)) else if (smt::isNonRecursiveStruct(*exprType))
{ {
memberExpr->accept(*this); memberExpr->accept(*this);
auto const& symbStruct = dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(*memberExpr)); auto const& symbStruct = std::dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(*memberExpr));
defineExpr(_memberAccess, symbStruct->member(_memberAccess.memberName())); defineExpr(_memberAccess, symbStruct->member(_memberAccess.memberName()));
return false; return false;
} }
@ -1471,7 +1471,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
memberExpr->accept(*this); memberExpr->accept(*this);
if (_memberAccess.memberName() == "length") if (_memberAccess.memberName() == "length")
{ {
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*memberExpr)); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(*memberExpr));
solAssert(symbArray, ""); solAssert(symbArray, "");
defineExpr(_memberAccess, symbArray->length()); defineExpr(_memberAccess, symbArray->length());
m_uninterpretedTerms.insert(&_memberAccess); m_uninterpretedTerms.insert(&_memberAccess);
@ -1554,7 +1554,7 @@ void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
return; return;
} }
shared_ptr<smt::SymbolicVariable> array; std::shared_ptr<smt::SymbolicVariable> array;
if (auto const* id = dynamic_cast<Identifier const*>(&_indexAccess.baseExpression())) if (auto const* id = dynamic_cast<Identifier const*>(&_indexAccess.baseExpression()))
{ {
auto varDecl = identifierToVariable(*id); auto varDecl = identifierToVariable(*id);
@ -1570,7 +1570,7 @@ void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
array = m_context.expression(_indexAccess.baseExpression()); array = m_context.expression(_indexAccess.baseExpression());
} }
auto arrayVar = dynamic_pointer_cast<smt::SymbolicArrayVariable>(array); auto arrayVar = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(array);
solAssert(arrayVar, ""); solAssert(arrayVar, "");
Type const* baseType = _indexAccess.baseExpression().annotation().type; Type const* baseType = _indexAccess.baseExpression().annotation().type;
@ -1611,10 +1611,10 @@ void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expre
Type const* baseType = base.annotation().type; Type const* baseType = base.annotation().type;
auto indexExpr = expr(*indexAccess->indexExpression(), keyType(baseType)); auto indexExpr = expr(*indexAccess->indexExpression(), keyType(baseType));
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(base)); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(base));
solAssert(symbArray, ""); solAssert(symbArray, "");
toStore = smtutil::Expression::tuple_constructor( toStore = smtutil::Expression::tuple_constructor(
smtutil::Expression(make_shared<smtutil::SortSort>(smt::smtSort(*baseType)), baseType->toString(true)), smtutil::Expression(std::make_shared<smtutil::SortSort>(smt::smtSort(*baseType)), baseType->toString(true)),
{smtutil::Expression::store(symbArray->elements(), indexExpr, toStore), symbArray->length()} {smtutil::Expression::store(symbArray->elements(), indexExpr, toStore), symbArray->length()}
); );
defineExpr(*indexAccess, smtutil::Expression::select( defineExpr(*indexAccess, smtutil::Expression::select(
@ -1650,7 +1650,7 @@ void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expre
break; break;
} }
auto symbStruct = dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(base)); auto symbStruct = std::dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(base));
solAssert(symbStruct, ""); solAssert(symbStruct, "");
symbStruct->assignMember(memberAccess->memberName(), toStore); symbStruct->assignMember(memberAccess->memberName(), toStore);
toStore = symbStruct->currentValue(); toStore = symbStruct->currentValue();
@ -1688,7 +1688,7 @@ void SMTEncoder::arrayPush(FunctionCall const& _funCall)
{ {
auto memberAccess = dynamic_cast<MemberAccess const*>(&_funCall.expression()); auto memberAccess = dynamic_cast<MemberAccess const*>(&_funCall.expression());
solAssert(memberAccess, ""); solAssert(memberAccess, "");
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression())); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
solAssert(symbArray, ""); solAssert(symbArray, "");
auto oldLength = symbArray->length(); auto oldLength = symbArray->length();
m_context.addAssertion(oldLength >= 0); m_context.addAssertion(oldLength >= 0);
@ -1722,7 +1722,7 @@ void SMTEncoder::arrayPop(FunctionCall const& _funCall)
{ {
auto memberAccess = dynamic_cast<MemberAccess const*>(cleanExpression(_funCall.expression())); auto memberAccess = dynamic_cast<MemberAccess const*>(cleanExpression(_funCall.expression()));
solAssert(memberAccess, ""); solAssert(memberAccess, "");
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression())); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
solAssert(symbArray, ""); solAssert(symbArray, "");
makeArrayPopVerificationTarget(_funCall); makeArrayPopVerificationTarget(_funCall);
@ -1742,7 +1742,7 @@ void SMTEncoder::arrayPop(FunctionCall const& _funCall)
assignment(memberAccess->expression(), symbArray->currentValue()); assignment(memberAccess->expression(), symbArray->currentValue());
} }
void SMTEncoder::defineGlobalVariable(string const& _name, Expression const& _expr, bool _increaseIndex) void SMTEncoder::defineGlobalVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex)
{ {
if (!m_context.knownGlobalSymbol(_name)) if (!m_context.knownGlobalSymbol(_name))
{ {
@ -1807,7 +1807,7 @@ void SMTEncoder::arithmeticOperation(BinaryOperation const& _op)
} }
} }
pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation( std::pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
Token _op, Token _op,
smtutil::Expression const& _left, smtutil::Expression const& _left,
smtutil::Expression const& _right, smtutil::Expression const& _right,
@ -1815,7 +1815,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
Expression const& _operation Expression const& _operation
) )
{ {
static set<Token> validOperators{ static std::set<Token> validOperators{
Token::Add, Token::Add,
Token::Sub, Token::Sub,
Token::Mul, Token::Mul,
@ -1862,7 +1862,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
// - RHS is -1 // - RHS is -1
// the result is then -(type.min), which wraps back to type.min // the result is then -(type.min), which wraps back to type.min
smtutil::Expression maxLeft = _left == smt::minValue(*intType); smtutil::Expression maxLeft = _left == smt::minValue(*intType);
smtutil::Expression minusOneRight = _right == numeric_limits<size_t >::max(); smtutil::Expression minusOneRight = _right == std::numeric_limits<size_t >::max();
smtutil::Expression wrap = smtutil::Expression::ite(maxLeft && minusOneRight, smt::minValue(*intType), valueUnbounded); smtutil::Expression wrap = smtutil::Expression::ite(maxLeft && minusOneRight, smt::minValue(*intType), valueUnbounded);
return {wrap, valueUnbounded}; return {wrap, valueUnbounded};
} }
@ -1871,7 +1871,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
auto symbMax = smt::maxValue(*intType); auto symbMax = smt::maxValue(*intType);
smtutil::Expression intValueRange = (0 - symbMin) + symbMax + 1; smtutil::Expression intValueRange = (0 - symbMin) + symbMax + 1;
string suffix = to_string(_operation.id()) + "_" + to_string(m_context.newUniqueId()); std::string suffix = std::to_string(_operation.id()) + "_" + std::to_string(m_context.newUniqueId());
smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context); smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context);
smt::SymbolicIntVariable m(intType, intType, "m_" + suffix, m_context); smt::SymbolicIntVariable m(intType, intType, "m_" + suffix, m_context);
@ -1905,7 +1905,7 @@ smtutil::Expression SMTEncoder::bitwiseOperation(
Type const* _commonType Type const* _commonType
) )
{ {
static set<Token> validOperators{ static std::set<Token> validOperators{
Token::BitAnd, Token::BitAnd,
Token::BitOr, Token::BitOr,
Token::BitXor, Token::BitXor,
@ -1921,7 +1921,7 @@ smtutil::Expression SMTEncoder::bitwiseOperation(
auto bvLeft = smtutil::Expression::int2bv(_left, bvSize); auto bvLeft = smtutil::Expression::int2bv(_left, bvSize);
auto bvRight = smtutil::Expression::int2bv(_right, bvSize); auto bvRight = smtutil::Expression::int2bv(_right, bvSize);
optional<smtutil::Expression> result; std::optional<smtutil::Expression> result;
switch (_op) switch (_op)
{ {
case Token::BitAnd: case Token::BitAnd:
@ -1962,10 +1962,10 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op)
smtutil::Expression left(expr(_op.leftExpression(), commonType)); smtutil::Expression left(expr(_op.leftExpression(), commonType));
smtutil::Expression right(expr(_op.rightExpression(), commonType)); smtutil::Expression right(expr(_op.rightExpression(), commonType));
Token op = _op.getOperator(); Token op = _op.getOperator();
shared_ptr<smtutil::Expression> value; std::shared_ptr<smtutil::Expression> value;
if (smt::isNumber(*commonType)) if (smt::isNumber(*commonType))
{ {
value = make_shared<smtutil::Expression>( value = std::make_shared<smtutil::Expression>(
op == Token::Equal ? (left == right) : op == Token::Equal ? (left == right) :
op == Token::NotEqual ? (left != right) : op == Token::NotEqual ? (left != right) :
op == Token::LessThan ? (left < right) : op == Token::LessThan ? (left < right) :
@ -1977,7 +1977,7 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op)
else // Bool else // Bool
{ {
solUnimplementedAssert(smt::isBool(*commonType), "Operation not yet supported"); solUnimplementedAssert(smt::isBool(*commonType), "Operation not yet supported");
value = make_shared<smtutil::Expression>( value = std::make_shared<smtutil::Expression>(
op == Token::Equal ? (left == right) : op == Token::Equal ? (left == right) :
/*op == Token::NotEqual*/ (left != right) /*op == Token::NotEqual*/ (left != right)
); );
@ -2039,7 +2039,7 @@ void SMTEncoder::bitwiseNotOperation(UnaryOperation const& _op)
defineExpr(_op, smtutil::Expression::bv2int(~bvOperand, isSigned)); defineExpr(_op, smtutil::Expression::bv2int(~bvOperand, isSigned));
} }
pair<smtutil::Expression, smtutil::Expression> SMTEncoder::divModWithSlacks( std::pair<smtutil::Expression, smtutil::Expression> SMTEncoder::divModWithSlacks(
smtutil::Expression _left, smtutil::Expression _left,
smtutil::Expression _right, smtutil::Expression _right,
IntegerType const& _type IntegerType const& _type
@ -2049,7 +2049,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::divModWithSlacks(
return {_left / _right, _left % _right}; return {_left / _right, _left % _right};
IntegerType const* intType = &_type; IntegerType const* intType = &_type;
string suffix = "div_mod_" + to_string(m_context.newUniqueId()); std::string suffix = "div_mod_" + std::to_string(m_context.newUniqueId());
smt::SymbolicIntVariable dSymb(intType, intType, "d_" + suffix, m_context); smt::SymbolicIntVariable dSymb(intType, intType, "d_" + suffix, m_context);
smt::SymbolicIntVariable rSymb(intType, intType, "r_" + suffix, m_context); smt::SymbolicIntVariable rSymb(intType, intType, "r_" + suffix, m_context);
auto d = dSymb.currentValue(); auto d = dSymb.currentValue();
@ -2115,7 +2115,7 @@ void SMTEncoder::assignment(
{ {
auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression()); auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
solAssert(memberAccess, ""); solAssert(memberAccess, "");
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression())); auto symbArray = std::dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
solAssert(symbArray, ""); solAssert(symbArray, "");
auto oldLength = symbArray->length(); auto oldLength = symbArray->length();
@ -2190,14 +2190,14 @@ void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _rig
smtutil::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment) smtutil::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment)
{ {
static map<Token, Token> const compoundToArithmetic{ static std::map<Token, Token> const compoundToArithmetic{
{Token::AssignAdd, Token::Add}, {Token::AssignAdd, Token::Add},
{Token::AssignSub, Token::Sub}, {Token::AssignSub, Token::Sub},
{Token::AssignMul, Token::Mul}, {Token::AssignMul, Token::Mul},
{Token::AssignDiv, Token::Div}, {Token::AssignDiv, Token::Div},
{Token::AssignMod, Token::Mod} {Token::AssignMod, Token::Mod}
}; };
static map<Token, Token> const compoundToBitwise{ static std::map<Token, Token> const compoundToBitwise{
{Token::AssignBitAnd, Token::BitAnd}, {Token::AssignBitAnd, Token::BitAnd},
{Token::AssignBitOr, Token::BitOr}, {Token::AssignBitOr, Token::BitOr},
{Token::AssignBitXor, Token::BitXor}, {Token::AssignBitXor, Token::BitXor},
@ -2228,12 +2228,12 @@ smtutil::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment
return values.first; return values.first;
} }
void SMTEncoder::expressionToTupleAssignment(vector<shared_ptr<VariableDeclaration>> const& _variables, Expression const& _rhs) void SMTEncoder::expressionToTupleAssignment(std::vector<std::shared_ptr<VariableDeclaration>> const& _variables, Expression const& _rhs)
{ {
auto symbolicVar = m_context.expression(_rhs); auto symbolicVar = m_context.expression(_rhs);
if (_variables.size() > 1) if (_variables.size() > 1)
{ {
auto symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(symbolicVar); auto symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(symbolicVar);
solAssert(symbTuple, ""); solAssert(symbTuple, "");
auto const& symbComponents = symbTuple->components(); auto const& symbComponents = symbTuple->components();
solAssert(symbComponents.size() == _variables.size(), ""); solAssert(symbComponents.size() == _variables.size(), "");
@ -2282,7 +2282,7 @@ void SMTEncoder::assignment(smt::SymbolicVariable& _symVar, smtutil::Expression
m_context.addAssertion(_symVar.increaseIndex() == _value); m_context.addAssertion(_symVar.increaseIndex() == _value);
} }
pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch( std::pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
ASTNode const* _statement, ASTNode const* _statement,
smtutil::Expression _condition smtutil::Expression _condition
) )
@ -2290,7 +2290,7 @@ pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
return visitBranch(_statement, &_condition); return visitBranch(_statement, &_condition);
} }
pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch( std::pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
ASTNode const* _statement, ASTNode const* _statement,
smtutil::Expression const* _condition smtutil::Expression const* _condition
) )
@ -2307,7 +2307,7 @@ pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
return {indicesAfterBranch, pathConditionOnExit}; return {indicesAfterBranch, pathConditionOnExit};
} }
void SMTEncoder::initializeFunctionCallParameters(CallableDeclaration const& _function, vector<smtutil::Expression> const& _callArgs) void SMTEncoder::initializeFunctionCallParameters(CallableDeclaration const& _function, std::vector<smtutil::Expression> const& _callArgs)
{ {
auto const& funParams = _function.parameters(); auto const& funParams = _function.parameters();
solAssert(funParams.size() == _callArgs.size(), ""); solAssert(funParams.size() == _callArgs.size(), "");
@ -2319,7 +2319,7 @@ void SMTEncoder::initializeFunctionCallParameters(CallableDeclaration const& _fu
m_arrayAssignmentHappened = true; m_arrayAssignmentHappened = true;
} }
vector<VariableDeclaration const*> localVars; std::vector<VariableDeclaration const*> localVars;
if (auto const* fun = dynamic_cast<FunctionDefinition const*>(&_function)) if (auto const* fun = dynamic_cast<FunctionDefinition const*>(&_function))
localVars = localVariablesIncludingModifiers(*fun, m_currentContract); localVars = localVariablesIncludingModifiers(*fun, m_currentContract);
else else
@ -2560,14 +2560,14 @@ void SMTEncoder::defineExpr(Expression const& _e, smtutil::Expression _value)
)); ));
} }
void SMTEncoder::defineExpr(Expression const& _e, vector<optional<smtutil::Expression>> const& _values) void SMTEncoder::defineExpr(Expression const& _e, std::vector<std::optional<smtutil::Expression>> const& _values)
{ {
if (_values.size() == 1 && _values.front()) if (_values.size() == 1 && _values.front())
{ {
defineExpr(_e, *_values.front()); defineExpr(_e, *_values.front());
return; return;
} }
auto const& symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_e)); auto const& symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_e));
solAssert(symbTuple, ""); solAssert(symbTuple, "");
symbTuple->increaseIndex(); symbTuple->increaseIndex();
auto const& symbComponents = symbTuple->components(); auto const& symbComponents = symbTuple->components();
@ -2606,7 +2606,7 @@ smtutil::Expression SMTEncoder::currentPathConditions()
return m_pathConditions.back(); return m_pathConditions.back();
} }
SecondarySourceLocation SMTEncoder::callStackMessage(vector<CallStackEntry> const& _callStack) SecondarySourceLocation SMTEncoder::callStackMessage(std::vector<CallStackEntry> const& _callStack)
{ {
SecondarySourceLocation callStackLocation; SecondarySourceLocation callStackLocation;
solAssert(!_callStack.empty(), ""); solAssert(!_callStack.empty(), "");
@ -2617,7 +2617,7 @@ SecondarySourceLocation SMTEncoder::callStackMessage(vector<CallStackEntry> cons
return callStackLocation; return callStackLocation;
} }
pair<CallableDeclaration const*, ASTNode const*> SMTEncoder::popCallStack() std::pair<CallableDeclaration const*, ASTNode const*> SMTEncoder::popCallStack()
{ {
solAssert(!m_callStack.empty(), ""); solAssert(!m_callStack.empty(), "");
auto lastCalled = m_callStack.back(); auto lastCalled = m_callStack.back();
@ -2738,7 +2738,7 @@ TypePointers SMTEncoder::replaceUserTypes(TypePointers const& _types)
}); });
} }
pair<Expression const*, FunctionCallOptions const*> SMTEncoder::functionCallExpression(FunctionCall const& _funCall) std::pair<Expression const*, FunctionCallOptions const*> SMTEncoder::functionCallExpression(FunctionCall const& _funCall)
{ {
Expression const* callExpr = &_funCall.expression(); Expression const* callExpr = &_funCall.expression();
auto const* callOptions = dynamic_cast<FunctionCallOptions const*>(callExpr); auto const* callOptions = dynamic_cast<FunctionCallOptions const*>(callExpr);
@ -2775,9 +2775,9 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _expr)
return expr; return expr;
} }
set<VariableDeclaration const*> SMTEncoder::touchedVariables(ASTNode const& _node) std::set<VariableDeclaration const*> SMTEncoder::touchedVariables(ASTNode const& _node)
{ {
vector<CallableDeclaration const*> callStack; std::vector<CallableDeclaration const*> callStack;
for (auto const& call: m_callStack) for (auto const& call: m_callStack)
callStack.push_back(call.first); callStack.push_back(call.first);
return m_variableUsage.touchedVariables(_node, callStack); return m_variableUsage.touchedVariables(_node, callStack);
@ -2861,9 +2861,9 @@ bool SMTEncoder::isExternalCallToThis(Expression const* _expr) {
; ;
} }
string SMTEncoder::extraComment() std::string SMTEncoder::extraComment()
{ {
string extra; std::string extra;
if (m_arrayAssignmentHappened) if (m_arrayAssignmentHappened)
extra += extra +=
"\nNote that array aliasing is not supported," "\nNote that array aliasing is not supported,"
@ -2921,28 +2921,28 @@ FunctionDefinition const* SMTEncoder::functionCallToDefinition(
return {}; return {};
} }
vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract) std::vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract)
{ {
return fold( return fold(
_contract.annotation().linearizedBaseContracts, _contract.annotation().linearizedBaseContracts,
vector<VariableDeclaration const*>{}, std::vector<VariableDeclaration const*>{},
[](auto&& _acc, auto _contract) { return _acc + _contract->stateVariables(); } [](auto&& _acc, auto _contract) { return _acc + _contract->stateVariables(); }
); );
} }
vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(FunctionDefinition const& _function) std::vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(FunctionDefinition const& _function)
{ {
if (auto contract = dynamic_cast<ContractDefinition const*>(_function.scope())) if (auto contract = dynamic_cast<ContractDefinition const*>(_function.scope()))
return stateVariablesIncludingInheritedAndPrivate(*contract); return stateVariablesIncludingInheritedAndPrivate(*contract);
return {}; return {};
} }
vector<VariableDeclaration const*> SMTEncoder::localVariablesIncludingModifiers(FunctionDefinition const& _function, ContractDefinition const* _contract) std::vector<VariableDeclaration const*> SMTEncoder::localVariablesIncludingModifiers(FunctionDefinition const& _function, ContractDefinition const* _contract)
{ {
return _function.localVariables() + tryCatchVariables(_function) + modifiersVariables(_function, _contract); return _function.localVariables() + tryCatchVariables(_function) + modifiersVariables(_function, _contract);
} }
vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinition const& _function) std::vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinition const& _function)
{ {
struct TryCatchVarsVisitor : public ASTConstVisitor struct TryCatchVarsVisitor : public ASTConstVisitor
{ {
@ -2958,23 +2958,23 @@ vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinit
return true; return true;
} }
vector<VariableDeclaration const*> vars; std::vector<VariableDeclaration const*> vars;
} tryCatchVarsVisitor; } tryCatchVarsVisitor;
_function.accept(tryCatchVarsVisitor); _function.accept(tryCatchVarsVisitor);
return tryCatchVarsVisitor.vars; return tryCatchVarsVisitor.vars;
} }
vector<VariableDeclaration const*> SMTEncoder::modifiersVariables(FunctionDefinition const& _function, ContractDefinition const* _contract) std::vector<VariableDeclaration const*> SMTEncoder::modifiersVariables(FunctionDefinition const& _function, ContractDefinition const* _contract)
{ {
struct BlockVars: ASTConstVisitor struct BlockVars: ASTConstVisitor
{ {
BlockVars(Block const& _block) { _block.accept(*this); } BlockVars(Block const& _block) { _block.accept(*this); }
void endVisit(VariableDeclaration const& _var) { vars.push_back(&_var); } void endVisit(VariableDeclaration const& _var) { vars.push_back(&_var); }
vector<VariableDeclaration const*> vars; std::vector<VariableDeclaration const*> vars;
}; };
vector<VariableDeclaration const*> vars; std::vector<VariableDeclaration const*> vars;
set<ModifierDefinition const*> visited; std::set<ModifierDefinition const*> visited;
for (auto invok: _function.modifiers()) for (auto invok: _function.modifiers())
{ {
if (!invok) if (!invok)
@ -3007,12 +3007,12 @@ ModifierDefinition const* SMTEncoder::resolveModifierInvocation(ModifierInvocati
return modifier; return modifier;
} }
set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctions(ContractDefinition const& _contract) std::set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctions(ContractDefinition const& _contract)
{ {
if (!m_contractFunctions.count(&_contract)) if (!m_contractFunctions.count(&_contract))
{ {
auto const& functions = _contract.definedFunctions(); auto const& functions = _contract.definedFunctions();
set<FunctionDefinition const*, ASTNode::CompareByID> resolvedFunctions(begin(functions), end(functions)); std::set<FunctionDefinition const*, ASTNode::CompareByID> resolvedFunctions(begin(functions), end(functions));
for (auto const* base: _contract.annotation().linearizedBaseContracts) for (auto const* base: _contract.annotation().linearizedBaseContracts)
{ {
if (base == &_contract) if (base == &_contract)
@ -3042,7 +3042,7 @@ set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contract
return m_contractFunctions.at(&_contract); return m_contractFunctions.at(&_contract);
} }
set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctionsWithoutVirtual(ContractDefinition const& _contract) std::set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctionsWithoutVirtual(ContractDefinition const& _contract)
{ {
if (!m_contractFunctionsWithoutVirtual.count(&_contract)) if (!m_contractFunctionsWithoutVirtual.count(&_contract))
{ {
@ -3057,9 +3057,9 @@ set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contract
return m_contractFunctionsWithoutVirtual.at(&_contract); return m_contractFunctionsWithoutVirtual.at(&_contract);
} }
map<ContractDefinition const*, vector<ASTPointer<frontend::Expression>>> SMTEncoder::baseArguments(ContractDefinition const& _contract) std::map<ContractDefinition const*, std::vector<ASTPointer<frontend::Expression>>> SMTEncoder::baseArguments(ContractDefinition const& _contract)
{ {
map<ContractDefinition const*, vector<ASTPointer<Expression>>> baseArgs; std::map<ContractDefinition const*, std::vector<ASTPointer<Expression>>> baseArgs;
for (auto contract: _contract.annotation().linearizedBaseContracts) for (auto contract: _contract.annotation().linearizedBaseContracts)
{ {
@ -3104,7 +3104,7 @@ RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr)
return nullptr; return nullptr;
} }
set<FunctionCall const*, ASTCompareByID<FunctionCall>> SMTEncoder::collectABICalls(ASTNode const* _node) std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> SMTEncoder::collectABICalls(ASTNode const* _node)
{ {
struct ABIFunctions: public ASTConstVisitor struct ABIFunctions: public ASTConstVisitor
{ {
@ -3126,15 +3126,15 @@ set<FunctionCall const*, ASTCompareByID<FunctionCall>> SMTEncoder::collectABICal
} }
} }
set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls; std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls;
}; };
return ABIFunctions(_node).abiCalls; return ABIFunctions(_node).abiCalls;
} }
set<SourceUnit const*, ASTNode::CompareByID> SMTEncoder::sourceDependencies(SourceUnit const& _source) std::set<SourceUnit const*, ASTNode::CompareByID> SMTEncoder::sourceDependencies(SourceUnit const& _source)
{ {
set<SourceUnit const*, ASTNode::CompareByID> sources; std::set<SourceUnit const*, ASTNode::CompareByID> sources;
sources.insert(&_source); sources.insert(&_source);
for (auto const& source: _source.referencedSourceUnits(true)) for (auto const& source: _source.referencedSourceUnits(true))
sources.insert(source); sources.insert(source);
@ -3150,24 +3150,24 @@ void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall, Contrac
auto const& returnParams = funDef->returnParameters(); auto const& returnParams = funDef->returnParameters();
for (auto param: returnParams) for (auto param: returnParams)
createVariable(*param); createVariable(*param);
auto returnValues = applyMap(returnParams, [this](auto const& param) -> optional<smtutil::Expression> { auto returnValues = applyMap(returnParams, [this](auto const& param) -> std::optional<smtutil::Expression> {
solAssert(param && m_context.knownVariable(*param), ""); solAssert(param && m_context.knownVariable(*param), "");
return currentValue(*param); return currentValue(*param);
}); });
defineExpr(_funCall, returnValues); defineExpr(_funCall, returnValues);
} }
vector<smtutil::Expression> SMTEncoder::symbolicArguments(FunctionCall const& _funCall, ContractDefinition const* _contextContract) std::vector<smtutil::Expression> SMTEncoder::symbolicArguments(FunctionCall const& _funCall, ContractDefinition const* _contextContract)
{ {
auto funDef = functionCallToDefinition(_funCall, currentScopeContract(), _contextContract); auto funDef = functionCallToDefinition(_funCall, currentScopeContract(), _contextContract);
solAssert(funDef, ""); solAssert(funDef, "");
vector<smtutil::Expression> args; std::vector<smtutil::Expression> args;
Expression const* calledExpr = &_funCall.expression(); Expression const* calledExpr = &_funCall.expression();
auto funType = dynamic_cast<FunctionType const*>(calledExpr->annotation().type); auto funType = dynamic_cast<FunctionType const*>(calledExpr->annotation().type);
solAssert(funType, ""); solAssert(funType, "");
vector<ASTPointer<Expression const>> arguments = _funCall.sortedArguments(); std::vector<ASTPointer<Expression const>> arguments = _funCall.sortedArguments();
auto functionParams = funDef->parameters(); auto functionParams = funDef->parameters();
unsigned firstParam = 0; unsigned firstParam = 0;
if (funType->hasBoundFirstArgument()) if (funType->hasBoundFirstArgument())
@ -3204,7 +3204,7 @@ smtutil::Expression SMTEncoder::constantExpr(Expression const& _expr, VariableDe
solAssert(false, ""); solAssert(false, "");
} }
void SMTEncoder::collectFreeFunctions(set<SourceUnit const*, ASTNode::CompareByID> const& _sources) void SMTEncoder::collectFreeFunctions(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources)
{ {
for (auto source: _sources) for (auto source: _sources)
for (auto node: source->nodes()) for (auto node: source->nodes())
@ -3220,7 +3220,7 @@ void SMTEncoder::collectFreeFunctions(set<SourceUnit const*, ASTNode::CompareByI
m_freeFunctions.insert(function); m_freeFunctions.insert(function);
} }
void SMTEncoder::createFreeConstants(set<SourceUnit const*, ASTNode::CompareByID> const& _sources) void SMTEncoder::createFreeConstants(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources)
{ {
for (auto source: _sources) for (auto source: _sources)
for (auto node: source->nodes()) for (auto node: source->nodes())

View File

@ -18,7 +18,6 @@
#include <libsolidity/formal/SSAVariable.h> #include <libsolidity/formal/SSAVariable.h>
using namespace std;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::frontend::smt; using namespace solidity::frontend::smt;

View File

@ -26,42 +26,41 @@
#include <range/v3/view.hpp> #include <range/v3/view.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::smtutil; using namespace solidity::smtutil;
using namespace solidity::frontend::smt; using namespace solidity::frontend::smt;
BlockchainVariable::BlockchainVariable( BlockchainVariable::BlockchainVariable(
string _name, std::string _name,
map<string, smtutil::SortPointer> _members, std::map<std::string, smtutil::SortPointer> _members,
EncodingContext& _context EncodingContext& _context
): ):
m_name(std::move(_name)), m_name(std::move(_name)),
m_members(std::move(_members)), m_members(std::move(_members)),
m_context(_context) m_context(_context)
{ {
vector<string> members; std::vector<std::string> members;
vector<SortPointer> sorts; std::vector<SortPointer> sorts;
for (auto const& [component, sort]: m_members) for (auto const& [component, sort]: m_members)
{ {
members.emplace_back(component); members.emplace_back(component);
sorts.emplace_back(sort); sorts.emplace_back(sort);
m_componentIndices[component] = static_cast<unsigned>(members.size() - 1); m_componentIndices[component] = static_cast<unsigned>(members.size() - 1);
} }
m_tuple = make_unique<SymbolicTupleVariable>( m_tuple = std::make_unique<SymbolicTupleVariable>(
make_shared<smtutil::TupleSort>(m_name + "_type", members, sorts), std::make_shared<smtutil::TupleSort>(m_name + "_type", members, sorts),
m_name, m_name,
m_context m_context
); );
} }
smtutil::Expression BlockchainVariable::member(string const& _member) const smtutil::Expression BlockchainVariable::member(std::string const& _member) const
{ {
return m_tuple->component(m_componentIndices.at(_member)); return m_tuple->component(m_componentIndices.at(_member));
} }
smtutil::Expression BlockchainVariable::assignMember(string const& _member, smtutil::Expression const& _value) smtutil::Expression BlockchainVariable::assignMember(std::string const& _member, smtutil::Expression const& _value)
{ {
smtutil::Expression newTuple = smt::assignMember(m_tuple->currentValue(), {{_member, _value}}); smtutil::Expression newTuple = smt::assignMember(m_tuple->currentValue(), {{_member, _value}});
m_context.addAssertion(m_tuple->increaseIndex() == newTuple); m_context.addAssertion(m_tuple->increaseIndex() == newTuple);
@ -104,9 +103,9 @@ smtutil::Expression SymbolicState::blockhash(smtutil::Expression _blockNumber) c
void SymbolicState::newBalances() void SymbolicState::newBalances()
{ {
auto tupleSort = dynamic_pointer_cast<TupleSort>(stateSort()); auto tupleSort = std::dynamic_pointer_cast<TupleSort>(stateSort());
auto balanceSort = tupleSort->components.at(tupleSort->memberToIndex.at("balances")); auto balanceSort = tupleSort->components.at(tupleSort->memberToIndex.at("balances"));
SymbolicVariable newBalances(balanceSort, "fresh_balances_" + to_string(m_context.newUniqueId()), m_context); SymbolicVariable newBalances(balanceSort, "fresh_balances_" + std::to_string(m_context.newUniqueId()), m_context);
m_state->assignMember("balances", newBalances.currentValue()); m_state->assignMember("balances", newBalances.currentValue());
} }
@ -158,7 +157,7 @@ void SymbolicState::newStorage()
{ {
auto newStorageVar = SymbolicTupleVariable( auto newStorageVar = SymbolicTupleVariable(
m_state->member("storage").sort, m_state->member("storage").sort,
"havoc_storage_" + to_string(m_context.newUniqueId()), "havoc_storage_" + std::to_string(m_context.newUniqueId()),
m_context m_context
); );
m_state->assignMember("storage", newStorageVar.currentValue()); m_state->assignMember("storage", newStorageVar.currentValue());
@ -170,7 +169,7 @@ void SymbolicState::writeStateVars(ContractDefinition const& _contract, smtutil:
if (stateVars.empty()) if (stateVars.empty())
return; return;
map<string, smtutil::Expression> values; std::map<std::string, smtutil::Expression> values;
for (auto var: stateVars) for (auto var: stateVars)
values.emplace(stateVarStorageKey(*var, _contract), m_context.variable(*var)->currentValue()); values.emplace(stateVarStorageKey(*var, _contract), m_context.variable(*var)->currentValue());
@ -207,7 +206,7 @@ void SymbolicState::addBalance(smtutil::Expression _address, smtutil::Expression
m_state->assignMember("balances", newBalances); m_state->assignMember("balances", newBalances);
} }
smtutil::Expression SymbolicState::txMember(string const& _member) const smtutil::Expression SymbolicState::txMember(std::string const& _member) const
{ {
return m_tx.member(_member); return m_tx.member(_member);
} }
@ -268,8 +267,8 @@ void SymbolicState::prepareForSourceUnit(SourceUnit const& _source, bool _storag
{ {
auto allSources = _source.referencedSourceUnits(true); auto allSources = _source.referencedSourceUnits(true);
allSources.insert(&_source); allSources.insert(&_source);
set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls; std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls;
set<ContractDefinition const*, ASTCompareByID<ContractDefinition>> contracts; std::set<ContractDefinition const*, ASTCompareByID<ContractDefinition>> contracts;
for (auto const& source: allSources) for (auto const& source: allSources)
{ {
abiCalls += SMTEncoder::collectABICalls(source); abiCalls += SMTEncoder::collectABICalls(source);
@ -283,34 +282,34 @@ void SymbolicState::prepareForSourceUnit(SourceUnit const& _source, bool _storag
/// Private helpers. /// Private helpers.
string SymbolicState::contractSuffix(ContractDefinition const& _contract) const std::string SymbolicState::contractSuffix(ContractDefinition const& _contract) const
{ {
return "_" + _contract.name() + "_" + to_string(_contract.id()); return "_" + _contract.name() + "_" + std::to_string(_contract.id());
} }
string SymbolicState::contractStorageKey(ContractDefinition const& _contract) const std::string SymbolicState::contractStorageKey(ContractDefinition const& _contract) const
{ {
return "storage" + contractSuffix(_contract); return "storage" + contractSuffix(_contract);
} }
string SymbolicState::stateVarStorageKey(VariableDeclaration const& _var, ContractDefinition const& _contract) const std::string SymbolicState::stateVarStorageKey(VariableDeclaration const& _var, ContractDefinition const& _contract) const
{ {
return _var.name() + "_" + to_string(_var.id()) + contractSuffix(_contract); return _var.name() + "_" + std::to_string(_var.id()) + contractSuffix(_contract);
} }
void SymbolicState::buildState(set<ContractDefinition const*, ASTCompareByID<ContractDefinition>> const& _contracts, bool _allStorages) void SymbolicState::buildState(std::set<ContractDefinition const*, ASTCompareByID<ContractDefinition>> const& _contracts, bool _allStorages)
{ {
map<string, SortPointer> stateMembers{ std::map<std::string, SortPointer> stateMembers{
{"balances", make_shared<smtutil::ArraySort>(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)} {"balances", std::make_shared<smtutil::ArraySort>(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)}
}; };
if (_allStorages) if (_allStorages)
{ {
vector<string> memberNames; std::vector<std::string> memberNames;
vector<SortPointer> memberSorts; std::vector<SortPointer> memberSorts;
for (auto contract: _contracts) for (auto contract: _contracts)
{ {
string suffix = contractSuffix(*contract); std::string suffix = contractSuffix(*contract);
// z3 doesn't like empty tuples, so if the contract has 0 // z3 doesn't like empty tuples, so if the contract has 0
// state vars we can't put it there. // state vars we can't put it there.
@ -319,16 +318,16 @@ void SymbolicState::buildState(set<ContractDefinition const*, ASTCompareByID<Con
continue; continue;
auto names = applyMap(stateVars, [&](auto var) { auto names = applyMap(stateVars, [&](auto var) {
return var->name() + "_" + to_string(var->id()) + suffix; return var->name() + "_" + std::to_string(var->id()) + suffix;
}); });
auto sorts = applyMap(stateVars, [](auto var) { return smtSortAbstractFunction(*var->type()); }); auto sorts = applyMap(stateVars, [](auto var) { return smtSortAbstractFunction(*var->type()); });
string name = "storage" + suffix; std::string name = "storage" + suffix;
auto storageTuple = make_shared<smtutil::TupleSort>( auto storageTuple = std::make_shared<smtutil::TupleSort>(
name + "_type", names, sorts name + "_type", names, sorts
); );
auto storageSort = make_shared<smtutil::ArraySort>( auto storageSort = std::make_shared<smtutil::ArraySort>(
smtSort(*TypeProvider::address()), smtSort(*TypeProvider::address()),
storageTuple storageTuple
); );
@ -339,26 +338,26 @@ void SymbolicState::buildState(set<ContractDefinition const*, ASTCompareByID<Con
stateMembers.emplace( stateMembers.emplace(
"isActive", "isActive",
make_shared<smtutil::ArraySort>(smtSort(*TypeProvider::address()), smtutil::SortProvider::boolSort) std::make_shared<smtutil::ArraySort>(smtSort(*TypeProvider::address()), smtutil::SortProvider::boolSort)
); );
stateMembers.emplace( stateMembers.emplace(
"storage", "storage",
make_shared<smtutil::TupleSort>( std::make_shared<smtutil::TupleSort>(
"storage_type", memberNames, memberSorts "storage_type", memberNames, memberSorts
) )
); );
} }
m_state = make_unique<BlockchainVariable>( m_state = std::make_unique<BlockchainVariable>(
"state", "state",
std::move(stateMembers), std::move(stateMembers),
m_context m_context
); );
} }
void SymbolicState::buildABIFunctions(set<FunctionCall const*, ASTCompareByID<FunctionCall>> const& _abiFunctions) void SymbolicState::buildABIFunctions(std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> const& _abiFunctions)
{ {
map<string, SortPointer> functions; std::map<std::string, SortPointer> functions;
for (auto const* funCall: _abiFunctions) for (auto const* funCall: _abiFunctions)
{ {
@ -375,8 +374,8 @@ void SymbolicState::buildABIFunctions(set<FunctionCall const*, ASTCompareByID<Fu
/// Since each abi.* function may have a different number of input/output parameters, /// Since each abi.* function may have a different number of input/output parameters,
/// we generically compute those types. /// we generically compute those types.
vector<frontend::Type const*> inTypes; std::vector<frontend::Type const*> inTypes;
vector<frontend::Type const*> outTypes; std::vector<frontend::Type const*> outTypes;
if (t->kind() == FunctionType::Kind::ABIDecode) if (t->kind() == FunctionType::Kind::ABIDecode)
{ {
/// abi.decode : (bytes, tuple_of_types(return_types)) -> (return_types) /// abi.decode : (bytes, tuple_of_types(return_types)) -> (return_types)
@ -415,7 +414,7 @@ void SymbolicState::buildABIFunctions(set<FunctionCall const*, ASTCompareByID<Fu
/// abi.encodeWithSelector : (bytes4, one_or_more_types) -> bytes /// abi.encodeWithSelector : (bytes4, one_or_more_types) -> bytes
/// abi.encodeWithSignature : (string, one_or_more_types) -> bytes /// abi.encodeWithSignature : (string, one_or_more_types) -> bytes
inTypes.emplace_back(paramTypes.front()); inTypes.emplace_back(paramTypes.front());
inTypes += argTypes(vector<ASTPointer<Expression const>>(args.begin() + 1, args.end())); inTypes += argTypes(std::vector<ASTPointer<Expression const>>(args.begin() + 1, args.end()));
} }
else else
{ {
@ -455,25 +454,25 @@ void SymbolicState::buildABIFunctions(set<FunctionCall const*, ASTCompareByID<Fu
/// If there is only one input or output parameter, we use that type directly. /// If there is only one input or output parameter, we use that type directly.
/// Otherwise we create a tuple wrapping the necessary input or output types. /// Otherwise we create a tuple wrapping the necessary input or output types.
auto typesToSort = [](auto const& _types, string const& _name) -> shared_ptr<Sort> { auto typesToSort = [](auto const& _types, std::string const& _name) -> std::shared_ptr<Sort> {
if (_types.size() == 1) if (_types.size() == 1)
return smtSortAbstractFunction(*_types.front()); return smtSortAbstractFunction(*_types.front());
vector<string> inNames; std::vector<std::string> inNames;
vector<SortPointer> sorts; std::vector<SortPointer> sorts;
for (unsigned i = 0; i < _types.size(); ++i) for (unsigned i = 0; i < _types.size(); ++i)
{ {
inNames.emplace_back(_name + "_input_" + to_string(i)); inNames.emplace_back(_name + "_input_" + std::to_string(i));
sorts.emplace_back(smtSortAbstractFunction(*_types.at(i))); sorts.emplace_back(smtSortAbstractFunction(*_types.at(i)));
} }
return make_shared<smtutil::TupleSort>( return std::make_shared<smtutil::TupleSort>(
_name + "_input", _name + "_input",
inNames, inNames,
sorts sorts
); );
}; };
auto functionSort = make_shared<smtutil::ArraySort>( auto functionSort = std::make_shared<smtutil::ArraySort>(
typesToSort(inTypes, name), typesToSort(inTypes, name),
typesToSort(outTypes, name) typesToSort(outTypes, name)
); );
@ -481,13 +480,13 @@ void SymbolicState::buildABIFunctions(set<FunctionCall const*, ASTCompareByID<Fu
functions[name] = functionSort; functions[name] = functionSort;
} }
m_abi = make_unique<BlockchainVariable>("abi", std::move(functions), m_context); m_abi = std::make_unique<BlockchainVariable>("abi", std::move(functions), m_context);
} }
smtutil::Expression SymbolicState::abiFunction(frontend::FunctionCall const* _funCall) smtutil::Expression SymbolicState::abiFunction(frontend::FunctionCall const* _funCall)
{ {
solAssert(m_abi, ""); solAssert(m_abi, "");
return m_abi->member(get<0>(m_abiMembers.at(_funCall))); return m_abi->member(std::get<0>(m_abiMembers.at(_funCall)));
} }
SymbolicState::SymbolicABIFunction const& SymbolicState::abiFunctionTypes(FunctionCall const* _funCall) const SymbolicState::SymbolicABIFunction const& SymbolicState::abiFunctionTypes(FunctionCall const* _funCall) const

View File

@ -26,7 +26,6 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
using namespace std;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::smtutil; using namespace solidity::smtutil;
@ -52,7 +51,7 @@ SortPointer smtSort(frontend::Type const& _type)
{ {
auto fType = dynamic_cast<frontend::FunctionType const*>(&_type); auto fType = dynamic_cast<frontend::FunctionType const*>(&_type);
solAssert(fType, ""); solAssert(fType, "");
vector<SortPointer> parameterSorts = smtSort(fType->parameterTypes()); std::vector<SortPointer> parameterSorts = smtSort(fType->parameterTypes());
auto returnTypes = fType->returnParameterTypes(); auto returnTypes = fType->returnParameterTypes();
SortPointer returnSort; SortPointer returnSort;
// TODO change this when we support tuples. // TODO change this when we support tuples.
@ -64,22 +63,22 @@ SortPointer smtSort(frontend::Type const& _type)
returnSort = SortProvider::uintSort; returnSort = SortProvider::uintSort;
else else
returnSort = smtSort(*returnTypes.front()); returnSort = smtSort(*returnTypes.front());
return make_shared<FunctionSort>(parameterSorts, returnSort); return std::make_shared<FunctionSort>(parameterSorts, returnSort);
} }
case Kind::Array: case Kind::Array:
{ {
shared_ptr<ArraySort> array; std::shared_ptr<ArraySort> array;
if (isMapping(_type)) if (isMapping(_type))
{ {
auto mapType = dynamic_cast<frontend::MappingType const*>(&_type); auto mapType = dynamic_cast<frontend::MappingType const*>(&_type);
solAssert(mapType, ""); solAssert(mapType, "");
array = make_shared<ArraySort>(smtSortAbstractFunction(*mapType->keyType()), smtSortAbstractFunction(*mapType->valueType())); array = std::make_shared<ArraySort>(smtSortAbstractFunction(*mapType->keyType()), smtSortAbstractFunction(*mapType->valueType()));
} }
else if (isStringLiteral(_type)) else if (isStringLiteral(_type))
{ {
auto stringLitType = dynamic_cast<frontend::StringLiteralType const*>(&_type); auto stringLitType = dynamic_cast<frontend::StringLiteralType const*>(&_type);
solAssert(stringLitType, ""); solAssert(stringLitType, "");
array = make_shared<ArraySort>(SortProvider::uintSort, SortProvider::uintSort); array = std::make_shared<ArraySort>(SortProvider::uintSort, SortProvider::uintSort);
} }
else else
{ {
@ -92,10 +91,10 @@ SortPointer smtSort(frontend::Type const& _type)
solAssert(false, ""); solAssert(false, "");
solAssert(arrayType, ""); solAssert(arrayType, "");
array = make_shared<ArraySort>(SortProvider::uintSort, smtSortAbstractFunction(*arrayType->baseType())); array = std::make_shared<ArraySort>(SortProvider::uintSort, smtSortAbstractFunction(*arrayType->baseType()));
} }
string tupleName; std::string tupleName;
auto sliceArrayType = dynamic_cast<ArraySliceType const*>(&_type); auto sliceArrayType = dynamic_cast<ArraySliceType const*>(&_type);
ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type); ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type);
if ( if (
@ -109,7 +108,7 @@ SortPointer smtSort(frontend::Type const& _type)
// Solidity allows implicit conversion also when assigning arrays. // Solidity allows implicit conversion also when assigning arrays.
// So if the base type potentially has a size, that size cannot go // So if the base type potentially has a size, that size cannot go
// in the tuple's name. // in the tuple's name.
if (auto tupleSort = dynamic_pointer_cast<TupleSort>(array->range)) if (auto tupleSort = std::dynamic_pointer_cast<TupleSort>(array->range))
tupleName = tupleSort->name; tupleName = tupleSort->name;
else if ( else if (
baseType->category() == frontend::Type::Category::Integer || baseType->category() == frontend::Type::Category::Integer ||
@ -128,23 +127,23 @@ SortPointer smtSort(frontend::Type const& _type)
tupleName += "_tuple"; tupleName += "_tuple";
return make_shared<TupleSort>( return std::make_shared<TupleSort>(
tupleName, tupleName,
vector<string>{tupleName + "_accessor_array", tupleName + "_accessor_length"}, std::vector<std::string>{tupleName + "_accessor_array", tupleName + "_accessor_length"},
vector<SortPointer>{array, SortProvider::uintSort} std::vector<SortPointer>{array, SortProvider::uintSort}
); );
} }
case Kind::Tuple: case Kind::Tuple:
{ {
vector<string> members; std::vector<std::string> members;
auto const& tupleName = _type.toString(true); auto const& tupleName = _type.toString(true);
vector<SortPointer> sorts; std::vector<SortPointer> sorts;
if (auto const* tupleType = dynamic_cast<frontend::TupleType const*>(&_type)) if (auto const* tupleType = dynamic_cast<frontend::TupleType const*>(&_type))
{ {
auto const& components = tupleType->components(); auto const& components = tupleType->components();
for (unsigned i = 0; i < components.size(); ++i) for (unsigned i = 0; i < components.size(); ++i)
members.emplace_back(tupleName + "_accessor_" + to_string(i)); members.emplace_back(tupleName + "_accessor_" + std::to_string(i));
sorts = smtSortAbstractFunction(tupleType->components()); sorts = smtSortAbstractFunction(tupleType->components());
} }
else if (auto const* structType = dynamic_cast<frontend::StructType const*>(&_type)) else if (auto const* structType = dynamic_cast<frontend::StructType const*>(&_type))
@ -161,7 +160,7 @@ SortPointer smtSort(frontend::Type const& _type)
else else
solAssert(false, ""); solAssert(false, "");
return make_shared<TupleSort>(tupleName, members, sorts); return std::make_shared<TupleSort>(tupleName, members, sorts);
} }
default: default:
// Abstract case. // Abstract case.
@ -169,9 +168,9 @@ SortPointer smtSort(frontend::Type const& _type)
} }
} }
vector<SortPointer> smtSort(vector<frontend::Type const*> const& _types) std::vector<SortPointer> smtSort(std::vector<frontend::Type const*> const& _types)
{ {
vector<SortPointer> sorts; std::vector<SortPointer> sorts;
for (auto const& type: _types) for (auto const& type: _types)
sorts.push_back(smtSort(*type)); sorts.push_back(smtSort(*type));
return sorts; return sorts;
@ -184,9 +183,9 @@ SortPointer smtSortAbstractFunction(frontend::Type const& _type)
return smtSort(_type); return smtSort(_type);
} }
vector<SortPointer> smtSortAbstractFunction(vector<frontend::Type const*> const& _types) std::vector<SortPointer> smtSortAbstractFunction(std::vector<frontend::Type const*> const& _types)
{ {
vector<SortPointer> sorts; std::vector<SortPointer> sorts;
for (auto const& type: _types) for (auto const& type: _types)
if (type) if (type)
sorts.push_back(smtSortAbstractFunction(*type)); sorts.push_back(smtSortAbstractFunction(*type));
@ -233,14 +232,14 @@ bool isSupportedTypeDeclaration(frontend::Type const& _type)
isFunction(_type); isFunction(_type);
} }
pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable( std::pair<bool, std::shared_ptr<SymbolicVariable>> newSymbolicVariable(
frontend::Type const& _type, frontend::Type const& _type,
std::string const& _uniqueName, std::string const& _uniqueName,
EncodingContext& _context EncodingContext& _context
) )
{ {
bool abstract = false; bool abstract = false;
shared_ptr<SymbolicVariable> var; std::shared_ptr<SymbolicVariable> var;
frontend::Type const* type = &_type; frontend::Type const* type = &_type;
if (auto userType = dynamic_cast<UserDefinedValueType const*>(type)) if (auto userType = dynamic_cast<UserDefinedValueType const*>(type))
@ -249,10 +248,10 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
if (!isSupportedTypeDeclaration(_type)) if (!isSupportedTypeDeclaration(_type))
{ {
abstract = true; abstract = true;
var = make_shared<SymbolicIntVariable>(frontend::TypeProvider::uint256(), type, _uniqueName, _context); var = std::make_shared<SymbolicIntVariable>(frontend::TypeProvider::uint256(), type, _uniqueName, _context);
} }
else if (isBool(_type)) else if (isBool(_type))
var = make_shared<SymbolicBoolVariable>(type, _uniqueName, _context); var = std::make_shared<SymbolicBoolVariable>(type, _uniqueName, _context);
else if (isFunction(_type)) else if (isFunction(_type))
{ {
auto const& fType = dynamic_cast<FunctionType const*>(type); auto const& fType = dynamic_cast<FunctionType const*>(type);
@ -271,45 +270,45 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
) )
{ {
abstract = true; abstract = true;
var = make_shared<SymbolicIntVariable>(TypeProvider::uint256(), type, _uniqueName, _context); var = std::make_shared<SymbolicIntVariable>(TypeProvider::uint256(), type, _uniqueName, _context);
} }
else else
var = make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context); var = std::make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context);
} }
else if (isInteger(_type)) else if (isInteger(_type))
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); var = std::make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
else if (isFixedPoint(_type)) else if (isFixedPoint(_type))
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); var = std::make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
else if (isFixedBytes(_type)) else if (isFixedBytes(_type))
{ {
auto fixedBytesType = dynamic_cast<frontend::FixedBytesType const*>(type); auto fixedBytesType = dynamic_cast<frontend::FixedBytesType const*>(type);
solAssert(fixedBytesType, ""); solAssert(fixedBytesType, "");
var = make_shared<SymbolicFixedBytesVariable>(type, fixedBytesType->numBytes(), _uniqueName, _context); var = std::make_shared<SymbolicFixedBytesVariable>(type, fixedBytesType->numBytes(), _uniqueName, _context);
} }
else if (isAddress(_type) || isContract(_type)) else if (isAddress(_type) || isContract(_type))
var = make_shared<SymbolicAddressVariable>(_uniqueName, _context); var = std::make_shared<SymbolicAddressVariable>(_uniqueName, _context);
else if (isEnum(_type)) else if (isEnum(_type))
var = make_shared<SymbolicEnumVariable>(type, _uniqueName, _context); var = std::make_shared<SymbolicEnumVariable>(type, _uniqueName, _context);
else if (isRational(_type)) else if (isRational(_type))
{ {
auto rational = dynamic_cast<frontend::RationalNumberType const*>(&_type); auto rational = dynamic_cast<frontend::RationalNumberType const*>(&_type);
solAssert(rational, ""); solAssert(rational, "");
if (rational->isFractional()) if (rational->isFractional())
var = make_shared<SymbolicIntVariable>(frontend::TypeProvider::uint256(), type, _uniqueName, _context); var = std::make_shared<SymbolicIntVariable>(frontend::TypeProvider::uint256(), type, _uniqueName, _context);
else else
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); var = std::make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
} }
else if (isMapping(_type) || isArray(_type)) else if (isMapping(_type) || isArray(_type))
var = make_shared<SymbolicArrayVariable>(type, type, _uniqueName, _context); var = std::make_shared<SymbolicArrayVariable>(type, type, _uniqueName, _context);
else if (isTuple(_type)) else if (isTuple(_type))
var = make_shared<SymbolicTupleVariable>(type, _uniqueName, _context); var = std::make_shared<SymbolicTupleVariable>(type, _uniqueName, _context);
else if (isStringLiteral(_type)) else if (isStringLiteral(_type))
{ {
auto stringType = TypeProvider::stringMemory(); auto stringType = TypeProvider::stringMemory();
var = make_shared<SymbolicArrayVariable>(stringType, type, _uniqueName, _context); var = std::make_shared<SymbolicArrayVariable>(stringType, type, _uniqueName, _context);
} }
else if (isNonRecursiveStruct(_type)) else if (isNonRecursiveStruct(_type))
var = make_shared<SymbolicStructVariable>(type, _uniqueName, _context); var = std::make_shared<SymbolicStructVariable>(type, _uniqueName, _context);
else else
solAssert(false, ""); solAssert(false, "");
return make_pair(abstract, var); return make_pair(abstract, var);
@ -482,9 +481,9 @@ smtutil::Expression zeroValue(frontend::Type const* _type)
return smtutil::Expression(false); return smtutil::Expression(false);
if (isArray(*_type) || isMapping(*_type)) if (isArray(*_type) || isMapping(*_type))
{ {
auto tupleSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type)); auto tupleSort = std::dynamic_pointer_cast<TupleSort>(smtSort(*_type));
solAssert(tupleSort, ""); solAssert(tupleSort, "");
auto sortSort = make_shared<SortSort>(tupleSort->components.front()); auto sortSort = std::make_shared<SortSort>(tupleSort->components.front());
std::optional<smtutil::Expression> zeroArray; std::optional<smtutil::Expression> zeroArray;
auto length = bigint(0); auto length = bigint(0);
@ -502,16 +501,16 @@ smtutil::Expression zeroValue(frontend::Type const* _type)
solAssert(zeroArray, ""); solAssert(zeroArray, "");
return smtutil::Expression::tuple_constructor( return smtutil::Expression::tuple_constructor(
smtutil::Expression(std::make_shared<SortSort>(tupleSort), tupleSort->name), smtutil::Expression(std::make_shared<SortSort>(tupleSort), tupleSort->name),
vector<smtutil::Expression>{*zeroArray, length} std::vector<smtutil::Expression>{*zeroArray, length}
); );
} }
if (isNonRecursiveStruct(*_type)) if (isNonRecursiveStruct(*_type))
{ {
auto const* structType = dynamic_cast<StructType const*>(_type); auto const* structType = dynamic_cast<StructType const*>(_type);
auto structSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type)); auto structSort = std::dynamic_pointer_cast<TupleSort>(smtSort(*_type));
return smtutil::Expression::tuple_constructor( return smtutil::Expression::tuple_constructor(
smtutil::Expression(make_shared<SortSort>(structSort), structSort->name), smtutil::Expression(std::make_shared<SortSort>(structSort), structSort->name),
applyMap( applyMap(
structType->structDefinition().members(), structType->structDefinition().members(),
[](auto var) { return zeroValue(var->type()); } [](auto var) { return zeroValue(var->type()); }
@ -550,7 +549,7 @@ bool isSigned(frontend::Type const* _type)
return isSigned; return isSigned;
} }
pair<unsigned, bool> typeBvSizeAndSignedness(frontend::Type const* _type) std::pair<unsigned, bool> typeBvSizeAndSignedness(frontend::Type const* _type)
{ {
if (auto userType = dynamic_cast<UserDefinedValueType const*>(_type)) if (auto userType = dynamic_cast<UserDefinedValueType const*>(_type))
return typeBvSizeAndSignedness(&userType->underlyingType()); return typeBvSizeAndSignedness(&userType->underlyingType());
@ -596,7 +595,7 @@ smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, fronte
return smtutil::Expression(true); return smtutil::Expression(true);
} }
optional<smtutil::Expression> symbolicTypeConversion(frontend::Type const* _from, frontend::Type const* _to) std::optional<smtutil::Expression> symbolicTypeConversion(frontend::Type const* _from, frontend::Type const* _to)
{ {
if (auto userType = dynamic_cast<UserDefinedValueType const*>(_to)) if (auto userType = dynamic_cast<UserDefinedValueType const*>(_to))
return symbolicTypeConversion(_from, &userType->underlyingType()); return symbolicTypeConversion(_from, &userType->underlyingType());
@ -618,7 +617,7 @@ optional<smtutil::Expression> symbolicTypeConversion(frontend::Type const* _from
return std::nullopt; return std::nullopt;
} }
smtutil::Expression member(smtutil::Expression const& _tuple, string const& _member) smtutil::Expression member(smtutil::Expression const& _tuple, std::string const& _member)
{ {
TupleSort const& _sort = dynamic_cast<TupleSort const&>(*_tuple.sort); TupleSort const& _sort = dynamic_cast<TupleSort const&>(*_tuple.sort);
return smtutil::Expression::tuple_get( return smtutil::Expression::tuple_get(
@ -627,16 +626,16 @@ smtutil::Expression member(smtutil::Expression const& _tuple, string const& _mem
); );
} }
smtutil::Expression assignMember(smtutil::Expression const _tuple, map<string, smtutil::Expression> const& _values) smtutil::Expression assignMember(smtutil::Expression const _tuple, std::map<std::string, smtutil::Expression> const& _values)
{ {
TupleSort const& _sort = dynamic_cast<TupleSort const&>(*_tuple.sort); TupleSort const& _sort = dynamic_cast<TupleSort const&>(*_tuple.sort);
vector<smtutil::Expression> args; std::vector<smtutil::Expression> args;
for (auto const& m: _sort.members) for (auto const& m: _sort.members)
if (auto* value = util::valueOrNullptr(_values, m)) if (auto* value = util::valueOrNullptr(_values, m))
args.emplace_back(*value); args.emplace_back(*value);
else else
args.emplace_back(member(_tuple, m)); args.emplace_back(member(_tuple, m));
auto sortExpr = smtutil::Expression(make_shared<smtutil::SortSort>(_tuple.sort), _tuple.name); auto sortExpr = smtutil::Expression(std::make_shared<smtutil::SortSort>(_tuple.sort), _tuple.name);
return smtutil::Expression::tuple_constructor(sortExpr, args); return smtutil::Expression::tuple_constructor(sortExpr, args);
} }

View File

@ -23,7 +23,6 @@
#include <libsolutil/Algorithms.h> #include <libsolutil/Algorithms.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::smtutil; using namespace solidity::smtutil;
@ -33,14 +32,14 @@ using namespace solidity::frontend::smt;
SymbolicVariable::SymbolicVariable( SymbolicVariable::SymbolicVariable(
frontend::Type const* _type, frontend::Type const* _type,
frontend::Type const* _originalType, frontend::Type const* _originalType,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
m_type(_type), m_type(_type),
m_originalType(_originalType), m_originalType(_originalType),
m_uniqueName(std::move(_uniqueName)), m_uniqueName(std::move(_uniqueName)),
m_context(_context), m_context(_context),
m_ssa(make_unique<SSAVariable>()) m_ssa(std::make_unique<SSAVariable>())
{ {
solAssert(m_type, ""); solAssert(m_type, "");
m_sort = smtSort(*m_type); m_sort = smtSort(*m_type);
@ -49,13 +48,13 @@ SymbolicVariable::SymbolicVariable(
SymbolicVariable::SymbolicVariable( SymbolicVariable::SymbolicVariable(
SortPointer _sort, SortPointer _sort,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
m_sort(std::move(_sort)), m_sort(std::move(_sort)),
m_uniqueName(std::move(_uniqueName)), m_uniqueName(std::move(_uniqueName)),
m_context(_context), m_context(_context),
m_ssa(make_unique<SSAVariable>()) m_ssa(std::make_unique<SSAVariable>())
{ {
solAssert(m_sort, ""); solAssert(m_sort, "");
} }
@ -65,7 +64,7 @@ smtutil::Expression SymbolicVariable::currentValue(frontend::Type const*) const
return valueAtIndex(m_ssa->index()); return valueAtIndex(m_ssa->index());
} }
string SymbolicVariable::currentName() const std::string SymbolicVariable::currentName() const
{ {
return uniqueSymbol(m_ssa->index()); return uniqueSymbol(m_ssa->index());
} }
@ -75,14 +74,14 @@ smtutil::Expression SymbolicVariable::valueAtIndex(unsigned _index) const
return m_context.newVariable(uniqueSymbol(_index), m_sort); return m_context.newVariable(uniqueSymbol(_index), m_sort);
} }
string SymbolicVariable::nameAtIndex(unsigned _index) const std::string SymbolicVariable::nameAtIndex(unsigned _index) const
{ {
return uniqueSymbol(_index); return uniqueSymbol(_index);
} }
string SymbolicVariable::uniqueSymbol(unsigned _index) const std::string SymbolicVariable::uniqueSymbol(unsigned _index) const
{ {
return m_uniqueName + "_" + to_string(_index); return m_uniqueName + "_" + std::to_string(_index);
} }
smtutil::Expression SymbolicVariable::resetIndex() smtutil::Expression SymbolicVariable::resetIndex()
@ -105,7 +104,7 @@ smtutil::Expression SymbolicVariable::increaseIndex()
SymbolicBoolVariable::SymbolicBoolVariable( SymbolicBoolVariable::SymbolicBoolVariable(
frontend::Type const* _type, frontend::Type const* _type,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _type, std::move(_uniqueName), _context) SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
@ -116,7 +115,7 @@ SymbolicBoolVariable::SymbolicBoolVariable(
SymbolicIntVariable::SymbolicIntVariable( SymbolicIntVariable::SymbolicIntVariable(
frontend::Type const* _type, frontend::Type const* _type,
frontend::Type const* _originalType, frontend::Type const* _originalType,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _originalType, std::move(_uniqueName), _context) SymbolicVariable(_type, _originalType, std::move(_uniqueName), _context)
@ -125,7 +124,7 @@ SymbolicIntVariable::SymbolicIntVariable(
} }
SymbolicAddressVariable::SymbolicAddressVariable( SymbolicAddressVariable::SymbolicAddressVariable(
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicIntVariable(TypeProvider::uint(160), TypeProvider::uint(160), std::move(_uniqueName), _context) SymbolicIntVariable(TypeProvider::uint(160), TypeProvider::uint(160), std::move(_uniqueName), _context)
@ -135,7 +134,7 @@ SymbolicAddressVariable::SymbolicAddressVariable(
SymbolicFixedBytesVariable::SymbolicFixedBytesVariable( SymbolicFixedBytesVariable::SymbolicFixedBytesVariable(
frontend::Type const* _originalType, frontend::Type const* _originalType,
unsigned _numBytes, unsigned _numBytes,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicIntVariable(TypeProvider::uint(_numBytes * 8), _originalType, std::move(_uniqueName), _context) SymbolicIntVariable(TypeProvider::uint(_numBytes * 8), _originalType, std::move(_uniqueName), _context)
@ -144,7 +143,7 @@ SymbolicFixedBytesVariable::SymbolicFixedBytesVariable(
SymbolicFunctionVariable::SymbolicFunctionVariable( SymbolicFunctionVariable::SymbolicFunctionVariable(
frontend::Type const* _type, frontend::Type const* _type,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _type, std::move(_uniqueName), _context), SymbolicVariable(_type, _type, std::move(_uniqueName), _context),
@ -155,7 +154,7 @@ SymbolicFunctionVariable::SymbolicFunctionVariable(
SymbolicFunctionVariable::SymbolicFunctionVariable( SymbolicFunctionVariable::SymbolicFunctionVariable(
SortPointer _sort, SortPointer _sort,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context), SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context),
@ -204,7 +203,7 @@ smtutil::Expression SymbolicFunctionVariable::increaseIndex()
return m_abstract.currentValue(); return m_abstract.currentValue();
} }
smtutil::Expression SymbolicFunctionVariable::operator()(vector<smtutil::Expression> _arguments) const smtutil::Expression SymbolicFunctionVariable::operator()(std::vector<smtutil::Expression> _arguments) const
{ {
return m_declaration(_arguments); return m_declaration(_arguments);
} }
@ -216,7 +215,7 @@ void SymbolicFunctionVariable::resetDeclaration()
SymbolicEnumVariable::SymbolicEnumVariable( SymbolicEnumVariable::SymbolicEnumVariable(
frontend::Type const* _type, frontend::Type const* _type,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _type, std::move(_uniqueName), _context) SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
@ -226,7 +225,7 @@ SymbolicEnumVariable::SymbolicEnumVariable(
SymbolicTupleVariable::SymbolicTupleVariable( SymbolicTupleVariable::SymbolicTupleVariable(
frontend::Type const* _type, frontend::Type const* _type,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _type, std::move(_uniqueName), _context) SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
@ -236,7 +235,7 @@ SymbolicTupleVariable::SymbolicTupleVariable(
SymbolicTupleVariable::SymbolicTupleVariable( SymbolicTupleVariable::SymbolicTupleVariable(
SortPointer _sort, SortPointer _sort,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context) SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context)
@ -249,22 +248,22 @@ smtutil::Expression SymbolicTupleVariable::currentValue(frontend::Type const* _t
if (!_targetType || sort() == smtSort(*_targetType)) if (!_targetType || sort() == smtSort(*_targetType))
return SymbolicVariable::currentValue(); return SymbolicVariable::currentValue();
auto thisTuple = dynamic_pointer_cast<TupleSort>(sort()); auto thisTuple = std::dynamic_pointer_cast<TupleSort>(sort());
auto otherTuple = dynamic_pointer_cast<TupleSort>(smtSort(*_targetType)); auto otherTuple = std::dynamic_pointer_cast<TupleSort>(smtSort(*_targetType));
solAssert(thisTuple && otherTuple, ""); solAssert(thisTuple && otherTuple, "");
solAssert(thisTuple->components.size() == otherTuple->components.size(), ""); solAssert(thisTuple->components.size() == otherTuple->components.size(), "");
vector<smtutil::Expression> args; std::vector<smtutil::Expression> args;
for (size_t i = 0; i < thisTuple->components.size(); ++i) for (size_t i = 0; i < thisTuple->components.size(); ++i)
args.emplace_back(component(i, type(), _targetType)); args.emplace_back(component(i, type(), _targetType));
return smtutil::Expression::tuple_constructor( return smtutil::Expression::tuple_constructor(
smtutil::Expression(make_shared<smtutil::SortSort>(smtSort(*_targetType)), ""), smtutil::Expression(std::make_shared<smtutil::SortSort>(smtSort(*_targetType)), ""),
args args
); );
} }
vector<SortPointer> const& SymbolicTupleVariable::components() const std::vector<SortPointer> const& SymbolicTupleVariable::components() const
{ {
auto tupleSort = dynamic_pointer_cast<TupleSort>(m_sort); auto tupleSort = std::dynamic_pointer_cast<TupleSort>(m_sort);
solAssert(tupleSort, ""); solAssert(tupleSort, "");
return tupleSort->components; return tupleSort->components;
} }
@ -275,7 +274,7 @@ smtutil::Expression SymbolicTupleVariable::component(
frontend::Type const* _toType frontend::Type const* _toType
) const ) const
{ {
optional<smtutil::Expression> conversion = symbolicTypeConversion(_fromType, _toType); std::optional<smtutil::Expression> conversion = symbolicTypeConversion(_fromType, _toType);
if (conversion) if (conversion)
return *conversion; return *conversion;
@ -285,7 +284,7 @@ smtutil::Expression SymbolicTupleVariable::component(
SymbolicArrayVariable::SymbolicArrayVariable( SymbolicArrayVariable::SymbolicArrayVariable(
frontend::Type const* _type, frontend::Type const* _type,
frontend::Type const* _originalType, frontend::Type const* _originalType,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _originalType, std::move(_uniqueName), _context), SymbolicVariable(_type, _originalType, std::move(_uniqueName), _context),
@ -300,7 +299,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
SymbolicArrayVariable::SymbolicArrayVariable( SymbolicArrayVariable::SymbolicArrayVariable(
SortPointer _sort, SortPointer _sort,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context), SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context),
@ -319,7 +318,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
smtutil::Expression SymbolicArrayVariable::currentValue(frontend::Type const* _targetType) const smtutil::Expression SymbolicArrayVariable::currentValue(frontend::Type const* _targetType) const
{ {
optional<smtutil::Expression> conversion = symbolicTypeConversion(m_originalType, _targetType); std::optional<smtutil::Expression> conversion = symbolicTypeConversion(m_originalType, _targetType);
if (conversion) if (conversion)
return *conversion; return *conversion;
@ -343,7 +342,7 @@ smtutil::Expression SymbolicArrayVariable::length() const
SymbolicStructVariable::SymbolicStructVariable( SymbolicStructVariable::SymbolicStructVariable(
frontend::Type const* _type, frontend::Type const* _type,
string _uniqueName, std::string _uniqueName,
EncodingContext& _context EncodingContext& _context
): ):
SymbolicVariable(_type, _type, std::move(_uniqueName), _context) SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
@ -359,12 +358,12 @@ SymbolicStructVariable::SymbolicStructVariable(
} }
} }
smtutil::Expression SymbolicStructVariable::member(string const& _member) const smtutil::Expression SymbolicStructVariable::member(std::string const& _member) const
{ {
return smtutil::Expression::tuple_get(currentValue(), m_memberIndices.at(_member)); return smtutil::Expression::tuple_get(currentValue(), m_memberIndices.at(_member));
} }
smtutil::Expression SymbolicStructVariable::assignMember(string const& _member, smtutil::Expression const& _memberValue) smtutil::Expression SymbolicStructVariable::assignMember(std::string const& _member, smtutil::Expression const& _memberValue)
{ {
auto const* structType = dynamic_cast<StructType const*>(m_type); auto const* structType = dynamic_cast<StructType const*>(m_type);
solAssert(structType, ""); solAssert(structType, "");
@ -385,7 +384,7 @@ smtutil::Expression SymbolicStructVariable::assignMember(string const& _member,
return currentValue(); return currentValue();
} }
smtutil::Expression SymbolicStructVariable::assignAllMembers(vector<smtutil::Expression> const& _memberValues) smtutil::Expression SymbolicStructVariable::assignAllMembers(std::vector<smtutil::Expression> const& _memberValues)
{ {
auto structType = dynamic_cast<StructType const*>(m_type); auto structType = dynamic_cast<StructType const*>(m_type);
solAssert(structType, ""); solAssert(structType, "");

View File

@ -25,13 +25,12 @@
#include <algorithm> #include <algorithm>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::frontend::smt; using namespace solidity::frontend::smt;
set<VariableDeclaration const*> VariableUsage::touchedVariables(ASTNode const& _node, vector<CallableDeclaration const*> const& _outerCallstack) std::set<VariableDeclaration const*> VariableUsage::touchedVariables(ASTNode const& _node, std::vector<CallableDeclaration const*> const& _outerCallstack)
{ {
m_touchedVariables.clear(); m_touchedVariables.clear();
m_callStack.clear(); m_callStack.clear();

View File

@ -23,7 +23,6 @@
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -42,9 +41,9 @@ bool anyDataStoredInStorage(TypePointers const& _pointers)
Json::Value ABI::generate(ContractDefinition const& _contractDef) Json::Value ABI::generate(ContractDefinition const& _contractDef)
{ {
auto compare = [](Json::Value const& _a, Json::Value const& _b) -> bool { auto compare = [](Json::Value const& _a, Json::Value const& _b) -> bool {
return make_tuple(_a["type"], _a["name"]) < make_tuple(_b["type"], _b["name"]); return std::make_tuple(_a["type"], _a["name"]) < std::make_tuple(_b["type"], _b["name"]);
}; };
multiset<Json::Value, decltype(compare)> abi(compare); std::multiset<Json::Value, decltype(compare)> abi(compare);
for (auto it: _contractDef.interfaceFunctions()) for (auto it: _contractDef.interfaceFunctions())
{ {
@ -144,9 +143,9 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
} }
Json::Value ABI::formatTypeList( Json::Value ABI::formatTypeList(
vector<string> const& _names, std::vector<std::string> const& _names,
vector<Type const*> const& _encodingTypes, std::vector<Type const*> const& _encodingTypes,
vector<Type const*> const& _solidityTypes, std::vector<Type const*> const& _solidityTypes,
bool _forLibrary bool _forLibrary
) )
{ {
@ -162,7 +161,7 @@ Json::Value ABI::formatTypeList(
} }
Json::Value ABI::formatType( Json::Value ABI::formatType(
string const& _name, std::string const& _name,
Type const& _encodingType, Type const& _encodingType,
Type const& _solidityType, Type const& _solidityType,
bool _forLibrary bool _forLibrary
@ -171,7 +170,7 @@ Json::Value ABI::formatType(
Json::Value ret{Json::objectValue}; Json::Value ret{Json::objectValue};
ret["name"] = _name; ret["name"] = _name;
ret["internalType"] = _solidityType.toString(true); ret["internalType"] = _solidityType.toString(true);
string suffix = (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)) ? " storage" : ""; std::string suffix = (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)) ? " storage" : "";
if (_encodingType.isValueType() || (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage))) if (_encodingType.isValueType() || (_forLibrary && _encodingType.dataStoredIn(DataLocation::Storage)))
ret["type"] = _encodingType.canonicalName() + suffix; ret["type"] = _encodingType.canonicalName() + suffix;
else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType)) else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType))
@ -180,11 +179,11 @@ Json::Value ABI::formatType(
ret["type"] = _encodingType.canonicalName() + suffix; ret["type"] = _encodingType.canonicalName() + suffix;
else else
{ {
string suffix; std::string suffix;
if (arrayType->isDynamicallySized()) if (arrayType->isDynamicallySized())
suffix = "[]"; suffix = "[]";
else else
suffix = string("[") + arrayType->length().str() + "]"; suffix = std::string("[") + arrayType->length().str() + "]";
solAssert(arrayType->baseType(), ""); solAssert(arrayType->baseType(), "");
Json::Value subtype = formatType( Json::Value subtype = formatType(
"", "",

File diff suppressed because it is too large Load Diff

View File

@ -81,13 +81,15 @@ class Compiler;
class GlobalContext; class GlobalContext;
class Natspec; class Natspec;
class DeclarationContainer; class DeclarationContainer;
namespace experimental
{
class Analysis;
}
/** /**
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible. * Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
* It holds state and can be used to either step through the compilation stages (and abort e.g. * It holds state and can be used to either step through the compilation stages (and abort e.g.
* before compilation to bytecode) or run the whole compilation in one call. * before compilation to bytecode) or run the whole compilation in one call.
* If error recovery is active, it is possible to progress through the stages even when
* there are errors. In any case, producing code is only possible without errors.
*/ */
class CompilerStack: public langutil::CharStreamProvider class CompilerStack: public langutil::CharStreamProvider
{ {
@ -101,7 +103,7 @@ public:
SourcesSet, SourcesSet,
Parsed, Parsed,
ParsedAndImported, ParsedAndImported,
AnalysisPerformed, AnalysisSuccessful,
CompilationSuccessful CompilationSuccessful
}; };
@ -137,10 +139,6 @@ public:
/// @returns the current state. /// @returns the current state.
State state() const { return m_stackState; } State state() const { return m_stackState; }
bool hasError() const { return m_hasError; }
bool compilationSuccessful() const { return m_stackState >= CompilationSuccessful; }
/// Resets the compiler to an empty state. Unless @a _keepSettings is set to true, /// Resets the compiler to an empty state. Unless @a _keepSettings is set to true,
/// all settings are reset as well. /// all settings are reset as well.
void reset(bool _keepSettings = false); void reset(bool _keepSettings = false);
@ -164,14 +162,6 @@ public:
/// Sets whether to strip revert strings, add additional strings or do nothing at all. /// Sets whether to strip revert strings, add additional strings or do nothing at all.
void setRevertStringBehaviour(RevertStrings _revertStrings); void setRevertStringBehaviour(RevertStrings _revertStrings);
/// Set whether or not parser error is desired.
/// When called without an argument it will revert to the default.
/// Must be set before parsing.
void setParserErrorRecovery(bool _wantErrorRecovery = false)
{
m_parserErrorRecovery = _wantErrorRecovery;
}
/// Sets the pipeline to go through the Yul IR or not. /// Sets the pipeline to go through the Yul IR or not.
/// Must be set before parsing. /// Must be set before parsing.
void setViaIR(bool _viaIR); void setViaIR(bool _viaIR);
@ -421,6 +411,14 @@ private:
/// @returns true if the contract is requested to be compiled. /// @returns true if the contract is requested to be compiled.
bool isRequestedContract(ContractDefinition const& _contract) const; bool isRequestedContract(ContractDefinition const& _contract) const;
/// Perform the analysis steps of legacy language mode.
/// @returns false on error.
bool analyzeLegacy(bool _noErrorsSoFar);
/// Perform the analysis steps of experimental language mode.
/// @returns false on error.
bool analyzeExperimental();
/// Assembles the contract. /// Assembles the contract.
/// This function should only be internally called by compileContract and generateEVMFromIR. /// This function should only be internally called by compileContract and generateEVMFromIR.
void assembleYul( void assembleYul(
@ -514,15 +512,12 @@ private:
langutil::ErrorList m_errorList; langutil::ErrorList m_errorList;
langutil::ErrorReporter m_errorReporter; langutil::ErrorReporter m_errorReporter;
std::unique_ptr<experimental::Analysis> m_experimentalAnalysis;
bool m_metadataLiteralSources = false; bool m_metadataLiteralSources = false;
MetadataHash m_metadataHash = MetadataHash::IPFS; MetadataHash m_metadataHash = MetadataHash::IPFS;
langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default();
bool m_parserErrorRecovery = false;
State m_stackState = Empty; State m_stackState = Empty;
CompilationSourceType m_compilationSourceType = CompilationSourceType::Solidity; CompilationSourceType m_compilationSourceType = CompilationSourceType::Solidity;
/// Whether or not there has been an error during processing.
/// If this is true, the stack will refuse to generate code.
bool m_hasError = false;
MetadataFormat m_metadataFormat = defaultMetadataFormat(); MetadataFormat m_metadataFormat = defaultMetadataFormat();
}; };

View File

@ -35,17 +35,13 @@ using solidity::langutil::InternalCompilerError;
using solidity::util::errinfo_comment; using solidity::util::errinfo_comment;
using solidity::util::readFileAsString; using solidity::util::readFileAsString;
using solidity::util::joinHumanReadable; using solidity::util::joinHumanReadable;
using std::map;
using std::reference_wrapper;
using std::string;
using std::vector;
namespace solidity::frontend namespace solidity::frontend
{ {
FileReader::FileReader( FileReader::FileReader(
boost::filesystem::path _basePath, boost::filesystem::path _basePath,
vector<boost::filesystem::path> const& _includePaths, std::vector<boost::filesystem::path> const& _includePaths,
FileSystemPathSet _allowedDirectories FileSystemPathSet _allowedDirectories
): ):
m_allowedDirectories(std::move(_allowedDirectories)), m_allowedDirectories(std::move(_allowedDirectories)),
@ -99,19 +95,19 @@ void FileReader::setSourceUnits(StringMap _sources)
m_sourceCodes = std::move(_sources); m_sourceCodes = std::move(_sources);
} }
ReadCallback::Result FileReader::readFile(string const& _kind, string const& _sourceUnitName) ReadCallback::Result FileReader::readFile(std::string const& _kind, std::string const& _sourceUnitName)
{ {
try try
{ {
if (_kind != ReadCallback::kindString(ReadCallback::Kind::ReadFile)) if (_kind != ReadCallback::kindString(ReadCallback::Kind::ReadFile))
solAssert(false, "ReadFile callback used as callback kind " + _kind); solAssert(false, "ReadFile callback used as callback kind " + _kind);
string strippedSourceUnitName = _sourceUnitName; std::string strippedSourceUnitName = _sourceUnitName;
if (strippedSourceUnitName.find("file://") == 0) if (strippedSourceUnitName.find("file://") == 0)
strippedSourceUnitName.erase(0, 7); strippedSourceUnitName.erase(0, 7);
vector<boost::filesystem::path> candidates; std::vector<boost::filesystem::path> candidates;
vector<reference_wrapper<boost::filesystem::path>> prefixes = {m_basePath}; std::vector<std::reference_wrapper<boost::filesystem::path>> prefixes = {m_basePath};
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path>>>); prefixes += (m_includePaths | ranges::to<std::vector<std::reference_wrapper<boost::filesystem::path>>>);
for (auto const& prefix: prefixes) for (auto const& prefix: prefixes)
{ {
@ -183,9 +179,9 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
} }
} }
string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPath) const std::string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPath) const
{ {
vector<boost::filesystem::path> prefixes = {m_basePath.empty() ? normalizeCLIPathForVFS(".") : m_basePath}; std::vector<boost::filesystem::path> prefixes = {m_basePath.empty() ? normalizeCLIPathForVFS(".") : m_basePath};
prefixes += m_includePaths; prefixes += m_includePaths;
boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(_cliPath); boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(_cliPath);
@ -200,17 +196,17 @@ string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPa
return normalizedPath.generic_string(); return normalizedPath.generic_string();
} }
map<string, FileReader::FileSystemPathSet> FileReader::detectSourceUnitNameCollisions(FileSystemPathSet const& _cliPaths) const std::map<std::string, FileReader::FileSystemPathSet> FileReader::detectSourceUnitNameCollisions(FileSystemPathSet const& _cliPaths) const
{ {
map<string, FileReader::FileSystemPathSet> nameToPaths; std::map<std::string, FileReader::FileSystemPathSet> nameToPaths;
for (boost::filesystem::path const& cliPath: _cliPaths) for (boost::filesystem::path const& cliPath: _cliPaths)
{ {
string sourceUnitName = cliPathToSourceUnitName(cliPath); std::string sourceUnitName = cliPathToSourceUnitName(cliPath);
boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(cliPath); boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(cliPath);
nameToPaths[sourceUnitName].insert(normalizedPath); nameToPaths[sourceUnitName].insert(normalizedPath);
} }
map<string, FileReader::FileSystemPathSet> collisions; std::map<std::string, FileReader::FileSystemPathSet> collisions;
for (auto&& [sourceUnitName, cliPaths]: nameToPaths) for (auto&& [sourceUnitName, cliPaths]: nameToPaths)
if (cliPaths.size() >= 2) if (cliPaths.size() >= 2)
collisions[sourceUnitName] = std::move(cliPaths); collisions[sourceUnitName] = std::move(cliPaths);
@ -377,7 +373,7 @@ bool FileReader::hasDotDotSegments(boost::filesystem::path const& _path)
bool FileReader::isUNCPath(boost::filesystem::path const& _path) bool FileReader::isUNCPath(boost::filesystem::path const& _path)
{ {
string rootName = _path.root_name().string(); std::string rootName = _path.root_name().string();
return ( return (
rootName.size() == 2 || rootName.size() == 2 ||

View File

@ -37,7 +37,6 @@
#include <map> #include <map>
#include <memory> #include <memory>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::evmasm; using namespace solidity::evmasm;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -45,16 +44,16 @@ using namespace solidity::langutil;
GasEstimator::GasConsumption GasEstimator::functionalEstimation( GasEstimator::GasConsumption GasEstimator::functionalEstimation(
AssemblyItems const& _items, AssemblyItems const& _items,
string const& _signature std::string const& _signature
) const ) const
{ {
auto state = make_shared<KnownState>(); auto state = std::make_shared<KnownState>();
if (!_signature.empty()) if (!_signature.empty())
{ {
ExpressionClasses& classes = state->expressionClasses(); ExpressionClasses& classes = state->expressionClasses();
using Id = ExpressionClasses::Id; using Id = ExpressionClasses::Id;
using Ids = vector<Id>; using Ids = std::vector<Id>;
Id hashValue = classes.find(u256(util::selectorFromSignatureU32(_signature))); Id hashValue = classes.find(u256(util::selectorFromSignatureU32(_signature)));
Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))});
if (!m_evmVersion.hasBitwiseShifting()) if (!m_evmVersion.hasBitwiseShifting())
@ -88,7 +87,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
FunctionDefinition const& _function FunctionDefinition const& _function
) const ) const
{ {
auto state = make_shared<KnownState>(); auto state = std::make_shared<KnownState>();
unsigned parametersSize = CompilerUtils::sizeOnStack(_function.parameters()); unsigned parametersSize = CompilerUtils::sizeOnStack(_function.parameters());
if (parametersSize > 16) if (parametersSize > 16)
@ -104,13 +103,13 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
return PathGasMeter::estimateMax(_items, m_evmVersion, _offset, state); return PathGasMeter::estimateMax(_items, m_evmVersion, _offset, state);
} }
set<ASTNode const*> GasEstimator::finestNodesAtLocation( std::set<ASTNode const*> GasEstimator::finestNodesAtLocation(
vector<ASTNode const*> const& _roots std::vector<ASTNode const*> const& _roots
) )
{ {
map<SourceLocation, ASTNode const*> locations; std::map<SourceLocation, ASTNode const*> locations;
set<ASTNode const*> nodes; std::set<ASTNode const*> nodes;
SimpleASTVisitor visitor(function<bool(ASTNode const&)>(), [&](ASTNode const& _n) SimpleASTVisitor visitor(std::function<bool(ASTNode const&)>(), [&](ASTNode const& _n)
{ {
if (!locations.count(_n.location())) if (!locations.count(_n.location()))
{ {

View File

@ -19,29 +19,20 @@
#include <libsolutil/CommonIO.h> #include <libsolutil/CommonIO.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
using std::equal;
using std::find;
using std::move;
using std::nullopt;
using std::optional;
using std::string;
using std::string_view;
using std::vector;
namespace solidity::frontend namespace solidity::frontend
{ {
void ImportRemapper::setRemappings(vector<Remapping> _remappings) void ImportRemapper::setRemappings(std::vector<Remapping> _remappings)
{ {
for (auto const& remapping: _remappings) for (auto const& remapping: _remappings)
solAssert(!remapping.prefix.empty(), ""); solAssert(!remapping.prefix.empty(), "");
m_remappings = std::move(_remappings); m_remappings = std::move(_remappings);
} }
SourceUnitName ImportRemapper::apply(ImportPath const& _path, string const& _context) const SourceUnitName ImportRemapper::apply(ImportPath const& _path, std::string const& _context) const
{ {
// Try to find the longest prefix match in all remappings that are active in the current context. // Try to find the longest prefix match in all remappings that are active in the current context.
auto isPrefixOf = [](string const& _a, string const& _b) auto isPrefixOf = [](std::string const& _a, std::string const& _b)
{ {
if (_a.length() > _b.length()) if (_a.length() > _b.length())
return false; return false;
@ -50,12 +41,12 @@ SourceUnitName ImportRemapper::apply(ImportPath const& _path, string const& _con
size_t longestPrefix = 0; size_t longestPrefix = 0;
size_t longestContext = 0; size_t longestContext = 0;
string bestMatchTarget; std::string bestMatchTarget;
for (auto const& redir: m_remappings) for (auto const& redir: m_remappings)
{ {
string context = util::sanitizePath(redir.context); std::string context = util::sanitizePath(redir.context);
string prefix = util::sanitizePath(redir.prefix); std::string prefix = util::sanitizePath(redir.prefix);
// Skip if current context is closer // Skip if current context is closer
if (context.length() < longestContext) if (context.length() < longestContext)
@ -74,32 +65,32 @@ SourceUnitName ImportRemapper::apply(ImportPath const& _path, string const& _con
longestPrefix = prefix.length(); longestPrefix = prefix.length();
bestMatchTarget = util::sanitizePath(redir.target); bestMatchTarget = util::sanitizePath(redir.target);
} }
string path = bestMatchTarget; std::string path = bestMatchTarget;
path.append(_path.begin() + static_cast<string::difference_type>(longestPrefix), _path.end()); path.append(_path.begin() + static_cast<std::string::difference_type>(longestPrefix), _path.end());
return path; return path;
} }
bool ImportRemapper::isRemapping(string_view _input) bool ImportRemapper::isRemapping(std::string_view _input)
{ {
return _input.find("=") != string::npos; return _input.find("=") != std::string::npos;
} }
optional<ImportRemapper::Remapping> ImportRemapper::parseRemapping(string_view _input) std::optional<ImportRemapper::Remapping> ImportRemapper::parseRemapping(std::string_view _input)
{ {
auto equals = find(_input.cbegin(), _input.cend(), '='); auto equals = std::find(_input.cbegin(), _input.cend(), '=');
if (equals == _input.end()) if (equals == _input.end())
return nullopt; return std::nullopt;
auto const colon = find(_input.cbegin(), equals, ':'); auto const colon = std::find(_input.cbegin(), equals, ':');
Remapping remapping{ Remapping remapping{
(colon == equals ? "" : string(_input.cbegin(), colon)), (colon == equals ? "" : std::string(_input.cbegin(), colon)),
(colon == equals ? string(_input.cbegin(), equals) : string(colon + 1, equals)), (colon == equals ? std::string(_input.cbegin(), equals) : std::string(colon + 1, equals)),
string(equals + 1, _input.cend()), std::string(equals + 1, _input.cend()),
}; };
if (remapping.prefix.empty()) if (remapping.prefix.empty())
return nullopt; return std::nullopt;
return remapping; return remapping;
} }

View File

@ -30,8 +30,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -46,7 +44,7 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
auto constructorDefinition(_contractDef.constructor()); auto constructorDefinition(_contractDef.constructor());
if (constructorDefinition) if (constructorDefinition)
{ {
string const value = extractDoc(constructorDefinition->annotation().docTags, "notice"); std::string const value = extractDoc(constructorDefinition->annotation().docTags, "notice");
if (!value.empty()) if (!value.empty())
{ {
// add the constructor, only if we have any documentation to add // add the constructor, only if we have any documentation to add
@ -56,14 +54,14 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
} }
} }
string notice = extractDoc(_contractDef.annotation().docTags, "notice"); std::string notice = extractDoc(_contractDef.annotation().docTags, "notice");
if (!notice.empty()) if (!notice.empty())
doc["notice"] = Json::Value(notice); doc["notice"] = Json::Value(notice);
for (auto const& it: _contractDef.interfaceFunctions()) for (auto const& it: _contractDef.interfaceFunctions())
if (it.second->hasDeclaration()) if (it.second->hasDeclaration())
{ {
string value; std::string value;
if (auto const* f = dynamic_cast<FunctionDefinition const*>(&it.second->declaration())) if (auto const* f = dynamic_cast<FunctionDefinition const*>(&it.second->declaration()))
value = extractDoc(f->annotation().docTags, "notice"); value = extractDoc(f->annotation().docTags, "notice");
@ -80,14 +78,14 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
for (auto const& event: uniqueInterfaceEvents(_contractDef)) for (auto const& event: uniqueInterfaceEvents(_contractDef))
{ {
string value = extractDoc(event->annotation().docTags, "notice"); std::string value = extractDoc(event->annotation().docTags, "notice");
if (!value.empty()) if (!value.empty())
doc["events"][event->functionType(true)->externalSignature()]["notice"] = value; doc["events"][event->functionType(true)->externalSignature()]["notice"] = value;
} }
for (auto const& error: _contractDef.interfaceErrors()) for (auto const& error: _contractDef.interfaceErrors())
{ {
string value = extractDoc(error->annotation().docTags, "notice"); std::string value = extractDoc(error->annotation().docTags, "notice");
if (!value.empty()) if (!value.empty())
{ {
Json::Value errorDoc{Json::objectValue}; Json::Value errorDoc{Json::objectValue};
@ -152,7 +150,7 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty()) if (auto devDoc = devDocumentation(varDecl->annotation().docTags); !devDoc.empty())
doc["stateVariables"][varDecl->name()] = devDoc; doc["stateVariables"][varDecl->name()] = devDoc;
auto const assignIfNotEmpty = [&](string const& _name, Json::Value const& _content) auto const assignIfNotEmpty = [&](std::string const& _name, Json::Value const& _content)
{ {
if (!_content.empty()) if (!_content.empty())
doc["stateVariables"][varDecl->name()][_name] = _content; doc["stateVariables"][varDecl->name()][_name] = _content;
@ -178,7 +176,7 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
return doc; return doc;
} }
Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTag> const& _tags, vector<string> const& _returnParameterNames) Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTag> const& _tags, std::vector<std::string> const& _returnParameterNames)
{ {
Json::Value jsonReturn{Json::objectValue}; Json::Value jsonReturn{Json::objectValue};
auto returnDocs = _tags.equal_range("return"); auto returnDocs = _tags.equal_range("return");
@ -188,8 +186,8 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTa
size_t n = 0; size_t n = 0;
for (auto i = returnDocs.first; i != returnDocs.second; i++) for (auto i = returnDocs.first; i != returnDocs.second; i++)
{ {
string paramName = _returnParameterNames.at(n); std::string paramName = _returnParameterNames.at(n);
string content = i->second.content; std::string content = i->second.content;
if (paramName.empty()) if (paramName.empty())
paramName = "_" + std::to_string(n); paramName = "_" + std::to_string(n);
@ -209,18 +207,18 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTa
return jsonReturn; return jsonReturn;
} }
string Natspec::extractDoc(multimap<string, DocTag> const& _tags, string const& _name) std::string Natspec::extractDoc(std::multimap<std::string, DocTag> const& _tags, std::string const& _name)
{ {
string value; std::string value;
auto range = _tags.equal_range(_name); auto range = _tags.equal_range(_name);
for (auto i = range.first; i != range.second; i++) for (auto i = range.first; i != range.second; i++)
value += i->second.content; value += i->second.content;
return value; return value;
} }
Json::Value Natspec::extractCustomDoc(multimap<string, DocTag> const& _tags) Json::Value Natspec::extractCustomDoc(std::multimap<std::string, DocTag> const& _tags)
{ {
std::map<string, string> concatenated; std::map<std::string, std::string> concatenated;
for (auto const& [tag, value]: _tags) for (auto const& [tag, value]: _tags)
if (boost::starts_with(tag, "custom")) if (boost::starts_with(tag, "custom"))
concatenated[tag] += value.content; concatenated[tag] += value.content;
@ -255,9 +253,9 @@ Json::Value Natspec::devDocumentation(std::multimap<std::string, DocTag> const&
return json; return json;
} }
vector<EventDefinition const*> Natspec::uniqueInterfaceEvents(ContractDefinition const& _contract) std::vector<EventDefinition const*> Natspec::uniqueInterfaceEvents(ContractDefinition const& _contract)
{ {
auto eventSignature = [](EventDefinition const* _event) -> string { auto eventSignature = [](EventDefinition const* _event) -> std::string {
FunctionType const* functionType = _event->functionType(true); FunctionType const* functionType = _event->functionType(true);
solAssert(functionType, ""); solAssert(functionType, "");
return functionType->externalSignature(); return functionType->externalSignature();
@ -267,13 +265,13 @@ vector<EventDefinition const*> Natspec::uniqueInterfaceEvents(ContractDefinitio
return eventSignature(_lhs) < eventSignature(_rhs); return eventSignature(_lhs) < eventSignature(_rhs);
}; };
set<EventDefinition const*, decltype(compareBySignature)> uniqueEvents{compareBySignature}; std::set<EventDefinition const*, decltype(compareBySignature)> uniqueEvents{compareBySignature};
// Insert events defined in the contract first so that in case of a conflict // Insert events defined in the contract first so that in case of a conflict
// they're the ones that get selected. // they're the ones that get selected.
uniqueEvents += _contract.definedInterfaceEvents(); uniqueEvents += _contract.definedInterfaceEvents();
set<EventDefinition const*, decltype(compareBySignature)> filteredUsedEvents{compareBySignature}; std::set<EventDefinition const*, decltype(compareBySignature)> filteredUsedEvents{compareBySignature};
set<string> usedSignatures; std::set<std::string> usedSignatures;
for (EventDefinition const* event: _contract.usedInterfaceEvents()) for (EventDefinition const* event: _contract.usedInterfaceEvents())
{ {
auto&& [eventIt, eventInserted] = filteredUsedEvents.insert(event); auto&& [eventIt, eventInserted] = filteredUsedEvents.insert(event);
@ -283,5 +281,5 @@ vector<EventDefinition const*> Natspec::uniqueInterfaceEvents(ContractDefinitio
} }
uniqueEvents += filteredUsedEvents; uniqueEvents += filteredUsedEvents;
return util::convertContainer<vector<EventDefinition const*>>(std::move(uniqueEvents)); return util::convertContainer<std::vector<EventDefinition const*>>(std::move(uniqueEvents));
} }

View File

@ -59,7 +59,7 @@ struct OptimiserSettings
"]" "]"
"jmul[jul] VcTOcul jmul"; // Make source short and pretty "jmul[jul] VcTOcul jmul"; // Make source short and pretty
static char constexpr DefaultYulOptimiserCleanupSteps[] = "fDnTOc"; static char constexpr DefaultYulOptimiserCleanupSteps[] = "fDnTOcmu";
/// No optimisations at all - not recommended. /// No optimisations at all - not recommended.
static OptimiserSettings none() static OptimiserSettings none()

View File

@ -33,14 +33,13 @@
using solidity::langutil::InternalCompilerError; using solidity::langutil::InternalCompilerError;
using solidity::util::errinfo_comment; using solidity::util::errinfo_comment;
using namespace std;
namespace solidity::frontend namespace solidity::frontend
{ {
SMTSolverCommand::SMTSolverCommand(string _solverCmd) : m_solverCmd(_solverCmd) {} SMTSolverCommand::SMTSolverCommand(std::string _solverCmd) : m_solverCmd(_solverCmd) {}
ReadCallback::Result SMTSolverCommand::solve(string const& _kind, string const& _query) ReadCallback::Result SMTSolverCommand::solve(std::string const& _kind, std::string const& _query)
{ {
try try
{ {
@ -66,8 +65,8 @@ ReadCallback::Result SMTSolverCommand::solve(string const& _kind, string const&
boost::process::std_out > pipe boost::process::std_out > pipe
); );
vector<string> data; std::vector<std::string> data;
string line; std::string line;
while (eld.running() && std::getline(pipe, line)) while (eld.running() && std::getline(pipe, line))
if (!line.empty()) if (!line.empty())
data.push_back(line); data.push_back(line);

View File

@ -44,20 +44,20 @@
#include <algorithm> #include <algorithm>
#include <optional> #include <optional>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace std::string_literals;
namespace namespace
{ {
Json::Value formatError( Json::Value formatError(
Error::Type _type, Error::Type _type,
string const& _component, std::string const& _component,
string const& _message, std::string const& _message,
string const& _formattedMessage = "", std::string const& _formattedMessage = "",
Json::Value const& _sourceLocation = Json::Value(), Json::Value const& _sourceLocation = Json::Value(),
Json::Value const& _secondarySourceLocation = Json::Value() Json::Value const& _secondarySourceLocation = Json::Value()
) )
@ -75,7 +75,7 @@ Json::Value formatError(
return error; return error;
} }
Json::Value formatFatalError(Error::Type _type, string const& _message) Json::Value formatFatalError(Error::Type _type, std::string const& _message)
{ {
Json::Value output{Json::objectValue}; Json::Value output{Json::objectValue};
output["errors"] = Json::arrayValue; output["errors"] = Json::arrayValue;
@ -114,22 +114,21 @@ Json::Value formatErrorWithException(
CharStreamProvider const& _charStreamProvider, CharStreamProvider const& _charStreamProvider,
util::Exception const& _exception, util::Exception const& _exception,
Error::Type _type, Error::Type _type,
string const& _component, std::string const& _component,
string const& _message, std::string const& _message,
optional<ErrorId> _errorId = nullopt std::optional<ErrorId> _errorId = std::nullopt
) )
{ {
string message; std::string message;
// TODO: consider enabling color // TODO: consider enabling color
string formattedMessage = SourceReferenceFormatter::formatExceptionInformation( std::string formattedMessage = SourceReferenceFormatter::formatExceptionInformation(
_exception, _exception,
_type, _type,
_charStreamProvider, _charStreamProvider,
false, // colored false // colored
false // _withErrorIds
); );
if (string const* description = _exception.comment()) if (std::string const* description = _exception.comment())
message = ((_message.length() > 0) ? (_message + ":") : "") + *description; message = ((_message.length() > 0) ? (_message + ":") : "") + *description;
else else
message = _message; message = _message;
@ -144,20 +143,20 @@ Json::Value formatErrorWithException(
); );
if (_errorId) if (_errorId)
error["errorCode"] = to_string(_errorId.value().error); error["errorCode"] = std::to_string(_errorId.value().error);
return error; return error;
} }
map<string, set<string>> requestedContractNames(Json::Value const& _outputSelection) std::map<std::string, std::set<std::string>> requestedContractNames(Json::Value const& _outputSelection)
{ {
map<string, set<string>> contracts; std::map<std::string, std::set<std::string>> contracts;
for (auto const& sourceName: _outputSelection.getMemberNames()) for (auto const& sourceName: _outputSelection.getMemberNames())
{ {
string key = (sourceName == "*") ? "" : sourceName; std::string key = (sourceName == "*") ? "" : sourceName;
for (auto const& contractName: _outputSelection[sourceName].getMemberNames()) for (auto const& contractName: _outputSelection[sourceName].getMemberNames())
{ {
string value = (contractName == "*") ? "" : contractName; std::string value = (contractName == "*") ? "" : contractName;
contracts[key].insert(value); contracts[key].insert(value);
} }
} }
@ -165,7 +164,7 @@ map<string, set<string>> requestedContractNames(Json::Value const& _outputSelect
} }
/// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content. /// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content.
bool hashMatchesContent(string const& _hash, string const& _content) bool hashMatchesContent(std::string const& _hash, std::string const& _content)
{ {
try try
{ {
@ -177,12 +176,12 @@ bool hashMatchesContent(string const& _hash, string const& _content)
} }
} }
bool isArtifactRequested(Json::Value const& _outputSelection, string const& _artifact, bool _wildcardMatchesExperimental) bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental)
{ {
static set<string> experimental{"ir", "irAst", "irOptimized", "irOptimizedAst"}; static std::set<std::string> experimental{"ir", "irAst", "irOptimized", "irOptimizedAst"};
for (auto const& selectedArtifactJson: _outputSelection) for (auto const& selectedArtifactJson: _outputSelection)
{ {
string const& selectedArtifact = selectedArtifactJson.asString(); std::string const& selectedArtifact = selectedArtifactJson.asString();
if ( if (
_artifact == selectedArtifact || _artifact == selectedArtifact ||
boost::algorithm::starts_with(_artifact, selectedArtifact + ".") boost::algorithm::starts_with(_artifact, selectedArtifact + ".")
@ -211,17 +210,17 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _art
/// ///
/// @TODO optimise this. Perhaps flatten the structure upfront. /// @TODO optimise this. Perhaps flatten the structure upfront.
/// ///
bool isArtifactRequested(Json::Value const& _outputSelection, string const& _file, string const& _contract, string const& _artifact, bool _wildcardMatchesExperimental) bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _file, std::string const& _contract, std::string const& _artifact, bool _wildcardMatchesExperimental)
{ {
if (!_outputSelection.isObject()) if (!_outputSelection.isObject())
return false; return false;
for (auto const& file: { _file, string("*") }) for (auto const& file: { _file, std::string("*") })
if (_outputSelection.isMember(file) && _outputSelection[file].isObject()) if (_outputSelection.isMember(file) && _outputSelection[file].isObject())
{ {
/// For SourceUnit-level targets (such as AST) only allow empty name, otherwise /// For SourceUnit-level targets (such as AST) only allow empty name, otherwise
/// for Contract-level targets try both contract name and wildcard /// for Contract-level targets try both contract name and wildcard
vector<string> contracts{ _contract }; std::vector<std::string> contracts{ _contract };
if (!_contract.empty()) if (!_contract.empty())
contracts.emplace_back("*"); contracts.emplace_back("*");
for (auto const& contract: contracts) for (auto const& contract: contracts)
@ -236,7 +235,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _fil
return false; return false;
} }
bool isArtifactRequested(Json::Value const& _outputSelection, string const& _file, string const& _contract, vector<string> const& _artifacts, bool _wildcardMatchesExperimental) bool isArtifactRequested(Json::Value const& _outputSelection, std::string const& _file, std::string const& _contract, std::vector<std::string> const& _artifacts, bool _wildcardMatchesExperimental)
{ {
for (auto const& artifact: _artifacts) for (auto const& artifact: _artifacts)
if (isArtifactRequested(_outputSelection, _file, _contract, artifact, _wildcardMatchesExperimental)) if (isArtifactRequested(_outputSelection, _file, _contract, artifact, _wildcardMatchesExperimental))
@ -245,10 +244,10 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _fil
} }
/// @returns all artifact names of the EVM object, either for creation or deploy time. /// @returns all artifact names of the EVM object, either for creation or deploy time.
vector<string> evmObjectComponents(string const& _objectKind) std::vector<std::string> evmObjectComponents(std::string const& _objectKind)
{ {
solAssert(_objectKind == "bytecode" || _objectKind == "deployedBytecode", ""); solAssert(_objectKind == "bytecode" || _objectKind == "deployedBytecode", "");
vector<string> components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences"}; std::vector<std::string> components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences"};
if (_objectKind == "deployedBytecode") if (_objectKind == "deployedBytecode")
components.push_back(".immutableReferences"); components.push_back(".immutableReferences");
return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; }); return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; });
@ -261,7 +260,7 @@ bool isBinaryRequested(Json::Value const& _outputSelection)
return false; return false;
// This does not include "evm.methodIdentifiers" on purpose! // This does not include "evm.methodIdentifiers" on purpose!
static vector<string> const outputsThatRequireBinaries = vector<string>{ static std::vector<std::string> const outputsThatRequireBinaries = std::vector<std::string>{
"*", "*",
"ir", "irAst", "irOptimized", "irOptimizedAst", "ir", "irAst", "irOptimized", "irOptimizedAst",
"evm.gasEstimates", "evm.legacyAssembly", "evm.assembly" "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly"
@ -281,7 +280,7 @@ bool isEvmBytecodeRequested(Json::Value const& _outputSelection)
if (!_outputSelection.isObject()) if (!_outputSelection.isObject())
return false; return false;
static vector<string> const outputsThatRequireEvmBinaries = vector<string>{ static std::vector<std::string> const outputsThatRequireEvmBinaries = std::vector<std::string>{
"*", "*",
"evm.gasEstimates", "evm.legacyAssembly", "evm.assembly" "evm.gasEstimates", "evm.legacyAssembly", "evm.assembly"
} + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode"); } + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode");
@ -321,13 +320,13 @@ Json::Value formatLinkReferences(std::map<size_t, std::string> const& linkRefere
for (auto const& ref: linkReferences) for (auto const& ref: linkReferences)
{ {
string const& fullname = ref.second; std::string const& fullname = ref.second;
// If the link reference does not contain a colon, assume that the file name is missing and // If the link reference does not contain a colon, assume that the file name is missing and
// the whole string represents the library name. // the whole string represents the library name.
size_t colon = fullname.rfind(':'); size_t colon = fullname.rfind(':');
string file = (colon != string::npos ? fullname.substr(0, colon) : ""); std::string file = (colon != std::string::npos ? fullname.substr(0, colon) : "");
string name = (colon != string::npos ? fullname.substr(colon + 1) : fullname); std::string name = (colon != std::string::npos ? fullname.substr(colon + 1) : fullname);
Json::Value fileObject = ret.get(file, Json::objectValue); Json::Value fileObject = ret.get(file, Json::objectValue);
Json::Value libraryArray = fileObject.get(name, Json::arrayValue); Json::Value libraryArray = fileObject.get(name, Json::arrayValue);
@ -344,7 +343,7 @@ Json::Value formatLinkReferences(std::map<size_t, std::string> const& linkRefere
return ret; return ret;
} }
Json::Value formatImmutableReferences(map<u256, pair<string, vector<size_t>>> const& _immutableReferences) Json::Value formatImmutableReferences(std::map<u256, std::pair<std::string, std::vector<size_t>>> const& _immutableReferences)
{ {
Json::Value ret{Json::objectValue}; Json::Value ret{Json::objectValue};
@ -368,10 +367,10 @@ Json::Value formatImmutableReferences(map<u256, pair<string, vector<size_t>>> co
Json::Value collectEVMObject( Json::Value collectEVMObject(
langutil::EVMVersion _evmVersion, langutil::EVMVersion _evmVersion,
evmasm::LinkerObject const& _object, evmasm::LinkerObject const& _object,
string const* _sourceMap, std::string const* _sourceMap,
Json::Value _generatedSources, Json::Value _generatedSources,
bool _runtimeObject, bool _runtimeObject,
function<bool(string)> const& _artifactRequested std::function<bool(std::string)> const& _artifactRequested
) )
{ {
Json::Value output{Json::objectValue}; Json::Value output{Json::objectValue};
@ -392,7 +391,7 @@ Json::Value collectEVMObject(
return output; return output;
} }
std::optional<Json::Value> checkKeys(Json::Value const& _input, set<string> const& _keys, string const& _name) std::optional<Json::Value> checkKeys(Json::Value const& _input, std::set<std::string> const& _keys, std::string const& _name)
{ {
if (!!_input && !_input.isObject()) if (!!_input && !_input.isObject())
return formatFatalError(Error::Type::JSONError, "\"" + _name + "\" must be an object"); return formatFatalError(Error::Type::JSONError, "\"" + _name + "\" must be an object");
@ -406,43 +405,43 @@ std::optional<Json::Value> checkKeys(Json::Value const& _input, set<string> cons
std::optional<Json::Value> checkRootKeys(Json::Value const& _input) std::optional<Json::Value> checkRootKeys(Json::Value const& _input)
{ {
static set<string> keys{"auxiliaryInput", "language", "settings", "sources"}; static std::set<std::string> keys{"auxiliaryInput", "language", "settings", "sources"};
return checkKeys(_input, keys, "root"); return checkKeys(_input, keys, "root");
} }
std::optional<Json::Value> checkSourceKeys(Json::Value const& _input, string const& _name) std::optional<Json::Value> checkSourceKeys(Json::Value const& _input, std::string const& _name)
{ {
static set<string> keys{"content", "keccak256", "urls"}; static std::set<std::string> keys{"content", "keccak256", "urls"};
return checkKeys(_input, keys, "sources." + _name); return checkKeys(_input, keys, "sources." + _name);
} }
std::optional<Json::Value> checkAuxiliaryInputKeys(Json::Value const& _input) std::optional<Json::Value> checkAuxiliaryInputKeys(Json::Value const& _input)
{ {
static set<string> keys{"smtlib2responses"}; static std::set<std::string> keys{"smtlib2responses"};
return checkKeys(_input, keys, "auxiliaryInput"); return checkKeys(_input, keys, "auxiliaryInput");
} }
std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input) std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
{ {
static set<string> keys{"parserErrorRecovery", "debug", "evmVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"}; static std::set<std::string> keys{"debug", "evmVersion", "libraries", "metadata", "modelChecker", "optimizer", "outputSelection", "remappings", "stopAfter", "viaIR"};
return checkKeys(_input, keys, "settings"); return checkKeys(_input, keys, "settings");
} }
std::optional<Json::Value> checkModelCheckerSettingsKeys(Json::Value const& _input) std::optional<Json::Value> checkModelCheckerSettingsKeys(Json::Value const& _input)
{ {
static set<string> keys{"bmcLoopIterations", "contracts", "divModNoSlacks", "engine", "extCalls", "invariants", "printQuery", "showProvedSafe", "showUnproved", "showUnsupported", "solvers", "targets", "timeout"}; static std::set<std::string> keys{"bmcLoopIterations", "contracts", "divModNoSlacks", "engine", "extCalls", "invariants", "printQuery", "showProvedSafe", "showUnproved", "showUnsupported", "solvers", "targets", "timeout"};
return checkKeys(_input, keys, "modelChecker"); return checkKeys(_input, keys, "modelChecker");
} }
std::optional<Json::Value> checkOptimizerKeys(Json::Value const& _input) std::optional<Json::Value> checkOptimizerKeys(Json::Value const& _input)
{ {
static set<string> keys{"details", "enabled", "runs"}; static std::set<std::string> keys{"details", "enabled", "runs"};
return checkKeys(_input, keys, "settings.optimizer"); return checkKeys(_input, keys, "settings.optimizer");
} }
std::optional<Json::Value> checkOptimizerDetailsKeys(Json::Value const& _input) std::optional<Json::Value> checkOptimizerDetailsKeys(Json::Value const& _input)
{ {
static set<string> keys{"peephole", "inliner", "jumpdestRemover", "orderLiterals", "deduplicate", "cse", "constantOptimizer", "yul", "yulDetails"}; static std::set<std::string> keys{"peephole", "inliner", "jumpdestRemover", "orderLiterals", "deduplicate", "cse", "constantOptimizer", "yul", "yulDetails"};
return checkKeys(_input, keys, "settings.optimizer.details"); return checkKeys(_input, keys, "settings.optimizer.details");
} }
@ -457,7 +456,7 @@ std::optional<Json::Value> checkOptimizerDetail(Json::Value const& _details, std
return {}; return {};
} }
std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, string& _optimiserSetting, string& _cleanupSetting) std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting)
{ {
if (_details.isMember(_name)) if (_details.isMember(_name))
{ {
@ -475,11 +474,11 @@ std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details
); );
} }
string const fullSequence = _details[_name].asString(); std::string const fullSequence = _details[_name].asString();
auto const delimiterPos = fullSequence.find(":"); auto const delimiterPos = fullSequence.find(":");
_optimiserSetting = fullSequence.substr(0, delimiterPos); _optimiserSetting = fullSequence.substr(0, delimiterPos);
if (delimiterPos != string::npos) if (delimiterPos != std::string::npos)
_cleanupSetting = fullSequence.substr(delimiterPos + 1); _cleanupSetting = fullSequence.substr(delimiterPos + 1);
else else
solAssert(_cleanupSetting == OptimiserSettings::DefaultYulOptimiserCleanupSteps); solAssert(_cleanupSetting == OptimiserSettings::DefaultYulOptimiserCleanupSteps);
@ -500,11 +499,11 @@ std::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
if (_input.isMember("useLiteralContent") && !_input["useLiteralContent"].isBool()) if (_input.isMember("useLiteralContent") && !_input["useLiteralContent"].isBool())
return formatFatalError(Error::Type::JSONError, "\"settings.metadata.useLiteralContent\" must be Boolean"); return formatFatalError(Error::Type::JSONError, "\"settings.metadata.useLiteralContent\" must be Boolean");
static set<string> hashes{"ipfs", "bzzr1", "none"}; static std::set<std::string> hashes{"ipfs", "bzzr1", "none"};
if (_input.isMember("bytecodeHash") && !hashes.count(_input["bytecodeHash"].asString())) if (_input.isMember("bytecodeHash") && !hashes.count(_input["bytecodeHash"].asString()))
return formatFatalError(Error::Type::JSONError, "\"settings.metadata.bytecodeHash\" must be \"ipfs\", \"bzzr1\" or \"none\""); return formatFatalError(Error::Type::JSONError, "\"settings.metadata.bytecodeHash\" must be \"ipfs\", \"bzzr1\" or \"none\"");
} }
static set<string> keys{"appendCBOR", "useLiteralContent", "bytecodeHash"}; static std::set<std::string> keys{"appendCBOR", "useLiteralContent", "bytecodeHash"};
return checkKeys(_input, keys, "settings.metadata"); return checkKeys(_input, keys, "settings.metadata");
} }
@ -646,7 +645,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
{ {
for (auto const& sourceName: sources.getMemberNames()) for (auto const& sourceName: sources.getMemberNames())
{ {
string hash; std::string hash;
if (auto result = checkSourceKeys(sources[sourceName], sourceName)) if (auto result = checkSourceKeys(sources[sourceName], sourceName))
return *result; return *result;
@ -656,7 +655,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
if (sources[sourceName]["content"].isString()) if (sources[sourceName]["content"].isString())
{ {
string content = sources[sourceName]["content"].asString(); std::string content = sources[sourceName]["content"].asString();
if (!hash.empty() && !hashMatchesContent(hash, content)) if (!hash.empty() && !hashMatchesContent(hash, content))
ret.errors.append(formatError( ret.errors.append(formatError(
Error::Type::IOError, Error::Type::IOError,
@ -673,7 +672,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
Error::Type::JSONError, "No import callback supplied, but URL is requested." Error::Type::JSONError, "No import callback supplied, but URL is requested."
); );
vector<string> failures; std::vector<std::string> failures;
bool found = false; bool found = false;
for (auto const& url: sources[sourceName]["urls"]) for (auto const& url: sources[sourceName]["urls"])
@ -774,13 +773,6 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
ret.stopAfter = CompilerStack::State::Parsed; ret.stopAfter = CompilerStack::State::Parsed;
} }
if (settings.isMember("parserErrorRecovery"))
{
if (!settings["parserErrorRecovery"].isBool())
return formatFatalError(Error::Type::JSONError, "\"settings.parserErrorRecovery\" must be a Boolean.");
ret.parserErrorRecovery = settings["parserErrorRecovery"].asBool();
}
if (settings.isMember("viaIR")) if (settings.isMember("viaIR"))
{ {
if (!settings["viaIR"].isBool()) if (!settings["viaIR"].isBool())
@ -833,11 +825,11 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
if (!settings["debug"]["debugInfo"].isArray()) if (!settings["debug"]["debugInfo"].isArray())
return formatFatalError(Error::Type::JSONError, "settings.debug.debugInfo must be an array."); return formatFatalError(Error::Type::JSONError, "settings.debug.debugInfo must be an array.");
vector<string> components; std::vector<std::string> components;
for (Json::Value const& arrayValue: settings["debug"]["debugInfo"]) for (Json::Value const& arrayValue: settings["debug"]["debugInfo"])
components.push_back(arrayValue.asString()); components.push_back(arrayValue.asString());
optional<DebugInfoSelection> debugInfoSelection = DebugInfoSelection::fromComponents( std::optional<DebugInfoSelection> debugInfoSelection = DebugInfoSelection::fromComponents(
components, components,
true /* _acceptWildcards */ true /* _acceptWildcards */
); );
@ -888,7 +880,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
{ {
if (!jsonSourceName[library].isString()) if (!jsonSourceName[library].isString())
return formatFatalError(Error::Type::JSONError, "Library address must be a string."); return formatFatalError(Error::Type::JSONError, "Library address must be a string.");
string address = jsonSourceName[library].asString(); std::string address = jsonSourceName[library].asString();
if (!boost::starts_with(address, "0x")) if (!boost::starts_with(address, "0x"))
return formatFatalError( return formatFatalError(
@ -970,7 +962,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
if (!sources.isObject() && !sources.isNull()) if (!sources.isObject() && !sources.isNull())
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.contracts is not a JSON object."); return formatFatalError(Error::Type::JSONError, "settings.modelChecker.contracts is not a JSON object.");
map<string, set<string>> sourceContracts; std::map<std::string, std::set<std::string>> sourceContracts;
for (auto const& source: sources.getMemberNames()) for (auto const& source: sources.getMemberNames())
{ {
if (source.empty()) if (source.empty())
@ -1139,14 +1131,14 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
return {std::move(ret)}; return {std::move(ret)};
} }
map<string, Json::Value> StandardCompiler::parseAstFromInput(StringMap const& _sources) std::map<std::string, Json::Value> StandardCompiler::parseAstFromInput(StringMap const& _sources)
{ {
map<string, Json::Value> sourceJsons; std::map<std::string, Json::Value> sourceJsons;
for (auto const& [sourceName, sourceCode]: _sources) for (auto const& [sourceName, sourceCode]: _sources)
{ {
Json::Value ast; Json::Value ast;
astAssert(util::jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON"); astAssert(util::jsonParseStrict(sourceCode, ast), "Input file could not be parsed to JSON");
string astKey = ast.isMember("ast") ? "ast" : "AST"; std::string astKey = ast.isMember("ast") ? "ast" : "AST";
astAssert(ast.isMember(astKey), "astkey is not member"); astAssert(ast.isMember(astKey), "astkey is not member");
astAssert(ast[astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'"); astAssert(ast[astKey]["nodeType"].asString() == "SourceUnit", "Top-level node should be a 'SourceUnit'");
@ -1167,7 +1159,6 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
compilerStack.addSMTLib2Response(smtLib2Response.first, smtLib2Response.second); compilerStack.addSMTLib2Response(smtLib2Response.first, smtLib2Response.second);
compilerStack.setViaIR(_inputsAndSettings.viaIR); compilerStack.setViaIR(_inputsAndSettings.viaIR);
compilerStack.setEVMVersion(_inputsAndSettings.evmVersion); compilerStack.setEVMVersion(_inputsAndSettings.evmVersion);
compilerStack.setParserErrorRecovery(_inputsAndSettings.parserErrorRecovery);
compilerStack.setRemappings(std::move(_inputsAndSettings.remappings)); compilerStack.setRemappings(std::move(_inputsAndSettings.remappings));
compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings)); compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings));
compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings); compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings);
@ -1318,21 +1309,18 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
} }
bool parsingSuccess = compilerStack.state() >= CompilerStack::State::Parsed; bool parsingSuccess = compilerStack.state() >= CompilerStack::State::Parsed;
bool analysisPerformed = compilerStack.state() >= CompilerStack::State::AnalysisPerformed; bool analysisSuccess = compilerStack.state() >= CompilerStack::State::AnalysisSuccessful;
bool compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful; bool compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful;
if (compilerStack.hasError() && !_inputsAndSettings.parserErrorRecovery)
analysisPerformed = false;
// If analysis fails, the artifacts inside CompilerStack are potentially incomplete and must not be returned. // If analysis fails, the artifacts inside CompilerStack are potentially incomplete and must not be returned.
// Note that not completing analysis due to stopAfter does not count as a failure. It's neither failure nor success. // Note that not completing analysis due to stopAfter does not count as a failure. It's neither failure nor success.
bool analysisFailed = !analysisPerformed && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed; bool analysisFailed = !analysisSuccess && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisSuccessful;
bool compilationFailed = !compilationSuccess && binariesRequested; bool compilationFailed = !compilationSuccess && binariesRequested;
/// Inconsistent state - stop here to receive error reports from users /// Inconsistent state - stop here to receive error reports from users
if ( if (
(compilationFailed || !analysisPerformed) && (compilationFailed || analysisFailed || !parsingSuccess) &&
(errors.empty() && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed) errors.empty()
) )
return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed."); return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed.");
@ -1342,15 +1330,17 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
output["errors"] = std::move(errors); output["errors"] = std::move(errors);
if (!compilerStack.unhandledSMTLib2Queries().empty()) if (!compilerStack.unhandledSMTLib2Queries().empty())
for (string const& query: compilerStack.unhandledSMTLib2Queries()) for (std::string const& query: compilerStack.unhandledSMTLib2Queries())
output["auxiliaryInputRequested"]["smtlib2queries"]["0x" + util::keccak256(query).hex()] = query; output["auxiliaryInputRequested"]["smtlib2queries"]["0x" + util::keccak256(query).hex()] = query;
bool const wildcardMatchesExperimental = false; bool const wildcardMatchesExperimental = false;
output["sources"] = Json::objectValue; output["sources"] = Json::objectValue;
unsigned sourceIndex = 0; unsigned sourceIndex = 0;
if (parsingSuccess && !analysisFailed && (!compilerStack.hasError() || _inputsAndSettings.parserErrorRecovery)) // NOTE: A case that will pass `parsingSuccess && !analysisFailed` but not `analysisSuccess` is
for (string const& sourceName: compilerStack.sourceNames()) // stopAfter: parsing with no parsing errors.
if (parsingSuccess && !analysisFailed)
for (std::string const& sourceName: compilerStack.sourceNames())
{ {
Json::Value sourceResult = Json::objectValue; Json::Value sourceResult = Json::objectValue;
sourceResult["id"] = sourceIndex++; sourceResult["id"] = sourceIndex++;
@ -1360,12 +1350,12 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
} }
Json::Value contractsOutput = Json::objectValue; Json::Value contractsOutput = Json::objectValue;
for (string const& contractName: analysisPerformed ? compilerStack.contractNames() : vector<string>()) for (std::string const& contractName: analysisSuccess ? compilerStack.contractNames() : std::vector<std::string>())
{ {
size_t colon = contractName.rfind(':'); size_t colon = contractName.rfind(':');
solAssert(colon != string::npos, ""); solAssert(colon != std::string::npos, "");
string file = contractName.substr(0, colon); std::string file = contractName.substr(0, colon);
string name = contractName.substr(colon + 1); std::string name = contractName.substr(colon + 1);
// ABI, storage layout, documentation and metadata // ABI, storage layout, documentation and metadata
Json::Value contractData(Json::objectValue); Json::Value contractData(Json::objectValue);
@ -1414,7 +1404,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
compilerStack.sourceMapping(contractName), compilerStack.sourceMapping(contractName),
compilerStack.generatedSources(contractName), compilerStack.generatedSources(contractName),
false, false,
[&](string const& _element) { return isArtifactRequested( [&](std::string const& _element) { return isArtifactRequested(
_inputsAndSettings.outputSelection, _inputsAndSettings.outputSelection,
file, file,
name, name,
@ -1436,7 +1426,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
compilerStack.runtimeSourceMapping(contractName), compilerStack.runtimeSourceMapping(contractName),
compilerStack.generatedSources(contractName, true), compilerStack.generatedSources(contractName, true),
true, true,
[&](string const& _element) { return isArtifactRequested( [&](std::string const& _element) { return isArtifactRequested(
_inputsAndSettings.outputSelection, _inputsAndSettings.outputSelection,
file, file,
name, name,
@ -1513,8 +1503,8 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
_inputsAndSettings.debugInfoSelection.value() : _inputsAndSettings.debugInfoSelection.value() :
DebugInfoSelection::Default() DebugInfoSelection::Default()
); );
string const& sourceName = _inputsAndSettings.sources.begin()->first; std::string const& sourceName = _inputsAndSettings.sources.begin()->first;
string const& sourceContents = _inputsAndSettings.sources.begin()->second; std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;
// Inconsistent state - stop here to receive error reports from users // Inconsistent state - stop here to receive error reports from users
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty()) if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
@ -1531,7 +1521,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
{ {
for (auto const& error: stack.errors()) for (auto const& error: stack.errors())
{ {
auto err = dynamic_pointer_cast<Error const>(error); auto err = std::dynamic_pointer_cast<Error const>(error);
output["errors"].append(formatErrorWithException( output["errors"].append(formatErrorWithException(
stack, stack,
@ -1544,7 +1534,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
return output; return output;
} }
string contractName = stack.parserResult()->name.str(); std::string contractName = stack.parserResult()->name.str();
bool const wildcardMatchesExperimental = true; bool const wildcardMatchesExperimental = true;
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental))
@ -1561,7 +1551,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
MachineAssemblyObject object; MachineAssemblyObject object;
MachineAssemblyObject deployedObject; MachineAssemblyObject deployedObject;
tie(object, deployedObject) = stack.assembleWithDeployed(); std::tie(object, deployedObject) = stack.assembleWithDeployed();
if (object.bytecode) if (object.bytecode)
object.bytecode->link(_inputsAndSettings.libraries); object.bytecode->link(_inputsAndSettings.libraries);
@ -1586,7 +1576,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
o.sourceMappings.get(), o.sourceMappings.get(),
Json::arrayValue, Json::arrayValue,
isDeployed, isDeployed,
[&, kind = kind](string const& _element) { return isArtifactRequested( [&, kind = kind](std::string const& _element) { return isArtifactRequested(
_inputsAndSettings.outputSelection, _inputsAndSettings.outputSelection,
sourceName, sourceName,
contractName, contractName,
@ -1626,11 +1616,11 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
} }
catch (Json::LogicError const& _exception) catch (Json::LogicError const& _exception)
{ {
return formatFatalError(Error::Type::InternalCompilerError, string("JSON logic exception: ") + _exception.what()); return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON logic exception: ") + _exception.what());
} }
catch (Json::RuntimeError const& _exception) catch (Json::RuntimeError const& _exception)
{ {
return formatFatalError(Error::Type::InternalCompilerError, string("JSON runtime exception: ") + _exception.what()); return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + _exception.what());
} }
catch (util::Exception const& _exception) catch (util::Exception const& _exception)
{ {
@ -1642,10 +1632,10 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
} }
} }
string StandardCompiler::compile(string const& _input) noexcept std::string StandardCompiler::compile(std::string const& _input) noexcept
{ {
Json::Value input; Json::Value input;
string errors; std::string errors;
try try
{ {
if (!util::jsonParseStrict(_input, input, &errors)) if (!util::jsonParseStrict(_input, input, &errors))
@ -1671,7 +1661,7 @@ string StandardCompiler::compile(string const& _input) noexcept
} }
Json::Value StandardCompiler::formatFunctionDebugData( Json::Value StandardCompiler::formatFunctionDebugData(
map<string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo std::map<std::string, evmasm::LinkerObject::FunctionDebugData> const& _debugInfo
) )
{ {
Json::Value ret(Json::objectValue); Json::Value ret(Json::objectValue);

View File

@ -72,7 +72,6 @@ private:
{ {
std::string language; std::string language;
Json::Value errors; Json::Value errors;
bool parserErrorRecovery = false;
CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful; CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful;
std::map<std::string, std::string> sources; std::map<std::string, std::string> sources;
std::map<util::h256, std::string> smtLib2Responses; std::map<util::h256, std::string> smtLib2Responses;

View File

@ -20,7 +20,6 @@
#include <libsolidity/ast/TypeProvider.h> #include <libsolidity/ast/TypeProvider.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -112,7 +111,7 @@ void StorageLayout::generate(Type const* _type)
solAssert(typeInfo.isMember("encoding"), ""); solAssert(typeInfo.isMember("encoding"), "");
} }
string StorageLayout::typeKeyName(Type const* _type) std::string StorageLayout::typeKeyName(Type const* _type)
{ {
if (auto refType = dynamic_cast<ReferenceType const*>(_type)) if (auto refType = dynamic_cast<ReferenceType const*>(_type))
return TypeProvider::withLocationIfReference(refType->location(), _type)->richIdentifier(); return TypeProvider::withLocationIfReference(refType->location(), _type)->richIdentifier();

View File

@ -25,19 +25,17 @@
#include <solidity/BuildInfo.h> #include <solidity/BuildInfo.h>
using namespace std;
char const* solidity::frontend::VersionNumber = ETH_PROJECT_VERSION; char const* solidity::frontend::VersionNumber = ETH_PROJECT_VERSION;
string const solidity::frontend::VersionString = std::string const solidity::frontend::VersionString =
string(solidity::frontend::VersionNumber) + std::string(solidity::frontend::VersionNumber) +
(string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) + (std::string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + std::string(SOL_VERSION_PRERELEASE)) +
(string(SOL_VERSION_BUILDINFO).empty() ? "" : "+" + string(SOL_VERSION_BUILDINFO)); (std::string(SOL_VERSION_BUILDINFO).empty() ? "" : "+" + std::string(SOL_VERSION_BUILDINFO));
string const solidity::frontend::VersionStringStrict = std::string const solidity::frontend::VersionStringStrict =
string(solidity::frontend::VersionNumber) + std::string(solidity::frontend::VersionNumber) +
(string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) + (std::string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + std::string(SOL_VERSION_PRERELEASE)) +
(string(SOL_VERSION_COMMIT).empty() ? "" : "+" + string(SOL_VERSION_COMMIT)); (std::string(SOL_VERSION_COMMIT).empty() ? "" : "+" + std::string(SOL_VERSION_COMMIT));
solidity::bytes const solidity::frontend::VersionCompactBytes = { solidity::bytes const solidity::frontend::VersionCompactBytes = {
ETH_PROJECT_VERSION_MAJOR, ETH_PROJECT_VERSION_MAJOR,
@ -45,4 +43,4 @@ solidity::bytes const solidity::frontend::VersionCompactBytes = {
ETH_PROJECT_VERSION_PATCH ETH_PROJECT_VERSION_PATCH
}; };
bool const solidity::frontend::VersionIsRelease = string(SOL_VERSION_PRERELEASE).empty(); bool const solidity::frontend::VersionIsRelease = std::string(SOL_VERSION_PRERELEASE).empty();

View File

@ -23,9 +23,6 @@
namespace solidity::lsp namespace solidity::lsp
{ {
using namespace std;
using namespace solidity::lsp; using namespace solidity::lsp;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -35,16 +32,16 @@ namespace
struct MarkdownBuilder struct MarkdownBuilder
{ {
stringstream result; std::stringstream result;
MarkdownBuilder& solidityCode(string const& _code) MarkdownBuilder& solidityCode(std::string const& _code)
{ {
auto constexpr SolidityLanguageId = "solidity"; auto constexpr SolidityLanguageId = "solidity";
result << "```" << SolidityLanguageId << '\n' << _code << "\n```\n\n"; result << "```" << SolidityLanguageId << '\n' << _code << "\n```\n\n";
return *this; return *this;
} }
MarkdownBuilder& paragraph(string const& _text) MarkdownBuilder& paragraph(std::string const& _text)
{ {
if (!_text.empty()) if (!_text.empty())
{ {

View File

@ -34,7 +34,6 @@
#include <fmt/format.h> #include <fmt/format.h>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::lsp; using namespace solidity::lsp;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -54,11 +53,11 @@ void FileRepository::setIncludePaths(std::vector<boost::filesystem::path> _paths
m_includePaths = std::move(_paths); m_includePaths = std::move(_paths);
} }
string FileRepository::sourceUnitNameToUri(string const& _sourceUnitName) const std::string FileRepository::sourceUnitNameToUri(std::string const& _sourceUnitName) const
{ {
regex const windowsDriveLetterPath("^[a-zA-Z]:/"); std::regex const windowsDriveLetterPath("^[a-zA-Z]:/");
auto const ensurePathIsUnixLike = [&](string inputPath) -> string { auto const ensurePathIsUnixLike = [&](std::string inputPath) -> std::string {
if (!regex_search(inputPath, windowsDriveLetterPath)) if (!regex_search(inputPath, windowsDriveLetterPath))
return inputPath; return inputPath;
else else
@ -86,13 +85,13 @@ string FileRepository::sourceUnitNameToUri(string const& _sourceUnitName) const
return "file:///" + _sourceUnitName; return "file:///" + _sourceUnitName;
} }
string FileRepository::uriToSourceUnitName(string const& _path) const std::string FileRepository::uriToSourceUnitName(std::string const& _path) const
{ {
lspRequire(boost::algorithm::starts_with(_path, "file://"), ErrorCode::InternalError, "URI must start with file://"); lspRequire(boost::algorithm::starts_with(_path, "file://"), ErrorCode::InternalError, "URI must start with file://");
return stripFileUriSchemePrefix(_path); return stripFileUriSchemePrefix(_path);
} }
void FileRepository::setSourceByUri(string const& _uri, string _source) void FileRepository::setSourceByUri(std::string const& _uri, std::string _source)
{ {
// This is needed for uris outside the base path. It can lead to collisions, // This is needed for uris outside the base path. It can lead to collisions,
// but we need to mostly rewrite this in a future version anyway. // but we need to mostly rewrite this in a future version anyway.
@ -110,9 +109,9 @@ Result<boost::filesystem::path> FileRepository::tryResolvePath(std::string const
) )
return boost::filesystem::path(_strippedSourceUnitName); return boost::filesystem::path(_strippedSourceUnitName);
vector<boost::filesystem::path> candidates; std::vector<boost::filesystem::path> candidates;
vector<reference_wrapper<boost::filesystem::path const>> prefixes = {m_basePath}; std::vector<std::reference_wrapper<boost::filesystem::path const>> prefixes = {m_basePath};
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path const>>>); prefixes += (m_includePaths | ranges::to<std::vector<std::reference_wrapper<boost::filesystem::path const>>>);
auto const defaultInclude = m_basePath / "node_modules"; auto const defaultInclude = m_basePath / "node_modules";
if (m_includePaths.empty()) if (m_includePaths.empty())
prefixes.emplace_back(defaultInclude); prefixes.emplace_back(defaultInclude);
@ -148,7 +147,7 @@ Result<boost::filesystem::path> FileRepository::tryResolvePath(std::string const
return candidates[0]; return candidates[0];
} }
frontend::ReadCallback::Result FileRepository::readFile(string const& _kind, string const& _sourceUnitName) frontend::ReadCallback::Result FileRepository::readFile(std::string const& _kind, std::string const& _sourceUnitName)
{ {
solAssert( solAssert(
_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile), _kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile),
@ -161,7 +160,7 @@ frontend::ReadCallback::Result FileRepository::readFile(string const& _kind, str
if (m_sourceCodes.count(_sourceUnitName)) if (m_sourceCodes.count(_sourceUnitName))
return ReadCallback::Result{true, m_sourceCodes.at(_sourceUnitName)}; return ReadCallback::Result{true, m_sourceCodes.at(_sourceUnitName)};
string const strippedSourceUnitName = stripFileUriSchemePrefix(_sourceUnitName); std::string const strippedSourceUnitName = stripFileUriSchemePrefix(_sourceUnitName);
Result<boost::filesystem::path> const resolvedPath = tryResolvePath(strippedSourceUnitName); Result<boost::filesystem::path> const resolvedPath = tryResolvePath(strippedSourceUnitName);
if (!resolvedPath.message().empty()) if (!resolvedPath.message().empty())
return ReadCallback::Result{false, resolvedPath.message()}; return ReadCallback::Result{false, resolvedPath.message()};

View File

@ -30,7 +30,6 @@
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::lsp; using namespace solidity::lsp;
using namespace std;
void GotoDefinition::operator()(MessageID _id, Json::Value const& _args) void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
{ {
@ -38,7 +37,7 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn); ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
vector<SourceLocation> locations; std::vector<SourceLocation> locations;
if (auto const* expression = dynamic_cast<Expression const*>(sourceNode)) if (auto const* expression = dynamic_cast<Expression const*>(sourceNode))
{ {
// Handles all expressions that can have one or more declaration annotation. // Handles all expressions that can have one or more declaration annotation.
@ -56,7 +55,7 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
{ {
auto const& path = *importDirective->annotation().absolutePath; auto const& path = *importDirective->annotation().absolutePath;
if (fileRepository().sourceUnits().count(path)) if (fileRepository().sourceUnits().count(path))
locations.emplace_back(SourceLocation{0, 0, make_shared<string const>(path)}); locations.emplace_back(SourceLocation{0, 0, std::make_shared<std::string const>(path)});
} }
Json::Value reply = Json::arrayValue; Json::Value reply = Json::arrayValue;

View File

@ -29,7 +29,6 @@
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::lsp; using namespace solidity::lsp;
using namespace solidity::util; using namespace solidity::util;
using namespace std;
Json::Value HandlerBase::toRange(SourceLocation const& _location) const Json::Value HandlerBase::toRange(SourceLocation const& _location) const
{ {
@ -52,10 +51,10 @@ Json::Value HandlerBase::toJson(SourceLocation const& _location) const
return item; return item;
} }
pair<string, LineColumn> HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const std::pair<std::string, LineColumn> HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const
{ {
string const uri = _args["textDocument"]["uri"].asString(); std::string const uri = _args["textDocument"]["uri"].asString();
string const sourceUnitName = fileRepository().uriToSourceUnitName(uri); std::string const sourceUnitName = fileRepository().uriToSourceUnitName(uri);
if (!fileRepository().sourceUnits().count(sourceUnitName)) if (!fileRepository().sourceUnits().count(sourceUnitName))
BOOST_THROW_EXCEPTION( BOOST_THROW_EXCEPTION(
RequestError(ErrorCode::RequestFailed) << RequestError(ErrorCode::RequestFailed) <<

View File

@ -46,7 +46,6 @@
#include <fmt/format.h> #include <fmt/format.h>
using namespace std;
using namespace std::string_literals; using namespace std::string_literals;
using namespace std::placeholders; using namespace std::placeholders;
@ -109,7 +108,7 @@ Json::Value semanticTokensLegend()
tokenTypes.append("operator"); tokenTypes.append("operator");
tokenTypes.append("parameter"); tokenTypes.append("parameter");
tokenTypes.append("property"); tokenTypes.append("property");
tokenTypes.append("string"); tokenTypes.append("std::string");
tokenTypes.append("struct"); tokenTypes.append("struct");
tokenTypes.append("type"); tokenTypes.append("type");
tokenTypes.append("typeParameter"); tokenTypes.append("typeParameter");
@ -137,19 +136,19 @@ LanguageServer::LanguageServer(Transport& _transport):
{"$/cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}}, {"$/cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}},
{"cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}}, {"cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}},
{"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }}, {"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }},
{"initialize", bind(&LanguageServer::handleInitialize, this, _1, _2)}, {"initialize", std::bind(&LanguageServer::handleInitialize, this, _1, _2)},
{"initialized", bind(&LanguageServer::handleInitialized, this, _1, _2)}, {"initialized", std::bind(&LanguageServer::handleInitialized, this, _1, _2)},
{"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }}, {"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }},
{"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }}, {"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }},
{"textDocument/definition", GotoDefinition(*this) }, {"textDocument/definition", GotoDefinition(*this) },
{"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)}, {"textDocument/didOpen", std::bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
{"textDocument/didChange", bind(&LanguageServer::handleTextDocumentDidChange, this, _2)}, {"textDocument/didChange", std::bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
{"textDocument/didClose", bind(&LanguageServer::handleTextDocumentDidClose, this, _2)}, {"textDocument/didClose", std::bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
{"textDocument/hover", DocumentHoverHandler(*this) }, {"textDocument/hover", DocumentHoverHandler(*this) },
{"textDocument/rename", RenameSymbol(*this) }, {"textDocument/rename", RenameSymbol(*this) },
{"textDocument/implementation", GotoDefinition(*this) }, {"textDocument/implementation", GotoDefinition(*this) },
{"textDocument/semanticTokens/full", bind(&LanguageServer::semanticTokensFull, this, _1, _2)}, {"textDocument/semanticTokens/full", std::bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
{"workspace/didChangeConfiguration", bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)}, {"workspace/didChangeConfiguration", std::bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
}, },
m_fileRepository("/" /* basePath */, {} /* no search paths */), m_fileRepository("/" /* basePath */, {} /* no search paths */),
m_compilerStack{m_fileRepository.reader()} m_compilerStack{m_fileRepository.reader()}
@ -196,7 +195,7 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
int typeFailureCount = 0; int typeFailureCount = 0;
if (jsonIncludePaths.isArray()) if (jsonIncludePaths.isArray())
{ {
vector<boost::filesystem::path> includePaths; std::vector<boost::filesystem::path> includePaths;
for (Json::Value const& jsonPath: jsonIncludePaths) for (Json::Value const& jsonPath: jsonIncludePaths)
{ {
if (jsonPath.isString()) if (jsonPath.isString())
@ -214,9 +213,9 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
} }
} }
vector<boost::filesystem::path> LanguageServer::allSolidityFilesFromProject() const std::vector<boost::filesystem::path> LanguageServer::allSolidityFilesFromProject() const
{ {
vector<fs::path> collectedPaths{}; std::vector<fs::path> collectedPaths{};
// We explicitly decided against including all files from include paths but leave the possibility // We explicitly decided against including all files from include paths but leave the possibility
// open for a future PR to enable such a feature to be optionally enabled (default disabled). // open for a future PR to enable such a feature to be optionally enabled (default disabled).
@ -242,7 +241,7 @@ void LanguageServer::compile()
// so we just remove all non-open files. // so we just remove all non-open files.
FileRepository oldRepository(m_fileRepository.basePath(), m_fileRepository.includePaths()); FileRepository oldRepository(m_fileRepository.basePath(), m_fileRepository.includePaths());
swap(oldRepository, m_fileRepository); std::swap(oldRepository, m_fileRepository);
// Load all solidity files from project. // Load all solidity files from project.
if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory) if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory)
@ -256,7 +255,7 @@ void LanguageServer::compile()
} }
// Overwrite all files as opened by the client, including the ones which might potentially have changes. // Overwrite all files as opened by the client, including the ones which might potentially have changes.
for (string const& fileName: m_openFiles) for (std::string const& fileName: m_openFiles)
m_fileRepository.setSourceByUri( m_fileRepository.setSourceByUri(
fileName, fileName,
oldRepository.sourceUnits().at(oldRepository.uriToSourceUnitName(fileName)) oldRepository.sourceUnits().at(oldRepository.uriToSourceUnitName(fileName))
@ -266,7 +265,7 @@ void LanguageServer::compile()
m_compilerStack.reset(false); m_compilerStack.reset(false);
m_compilerStack.setSources(m_fileRepository.sourceUnits()); m_compilerStack.setSources(m_fileRepository.sourceUnits());
m_compilerStack.compile(CompilerStack::State::AnalysisPerformed); m_compilerStack.compile(CompilerStack::State::AnalysisSuccessful);
} }
void LanguageServer::compileAndUpdateDiagnostics() void LanguageServer::compileAndUpdateDiagnostics()
@ -275,13 +274,13 @@ void LanguageServer::compileAndUpdateDiagnostics()
// These are the source units we will sent diagnostics to the client for sure, // These are the source units we will sent diagnostics to the client for sure,
// even if it is just to clear previous diagnostics. // even if it is just to clear previous diagnostics.
map<string, Json::Value> diagnosticsBySourceUnit; std::map<std::string, Json::Value> diagnosticsBySourceUnit;
for (string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys) for (std::string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys)
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
for (string const& sourceUnitName: m_nonemptyDiagnostics) for (std::string const& sourceUnitName: m_nonemptyDiagnostics)
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue; diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
for (shared_ptr<Error const> const& error: m_compilerStack.errors()) for (std::shared_ptr<Error const> const& error: m_compilerStack.errors())
{ {
SourceLocation const* location = error->sourceLocation(); SourceLocation const* location = error->sourceLocation();
if (!location || !location->sourceName) if (!location || !location->sourceName)
@ -292,8 +291,8 @@ void LanguageServer::compileAndUpdateDiagnostics()
jsonDiag["source"] = "solc"; jsonDiag["source"] = "solc";
jsonDiag["severity"] = toDiagnosticSeverity(error->type()); jsonDiag["severity"] = toDiagnosticSeverity(error->type());
jsonDiag["code"] = Json::UInt64{error->errorId().error}; jsonDiag["code"] = Json::UInt64{error->errorId().error};
string message = Error::formatErrorType(error->type()) + ":"; std::string message = Error::formatErrorType(error->type()) + ":";
if (string const* comment = error->comment()) if (std::string const* comment = error->comment())
message += " " + *comment; message += " " + *comment;
jsonDiag["message"] = std::move(message); jsonDiag["message"] = std::move(message);
jsonDiag["range"] = toRange(*location); jsonDiag["range"] = toRange(*location);
@ -314,7 +313,7 @@ void LanguageServer::compileAndUpdateDiagnostics()
{ {
Json::Value extra; Json::Value extra;
extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size()); extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size());
m_client.trace("Number of currently open files: " + to_string(diagnosticsBySourceUnit.size()), extra); m_client.trace("Number of currently open files: " + std::to_string(diagnosticsBySourceUnit.size()), extra);
} }
m_nonemptyDiagnostics.clear(); m_nonemptyDiagnostics.clear();
@ -336,13 +335,13 @@ bool LanguageServer::run()
MessageID id; MessageID id;
try try
{ {
optional<Json::Value> const jsonMessage = m_client.receive(); std::optional<Json::Value> const jsonMessage = m_client.receive();
if (!jsonMessage) if (!jsonMessage)
continue; continue;
if ((*jsonMessage)["method"].isString()) if ((*jsonMessage)["method"].isString())
{ {
string const methodName = (*jsonMessage)["method"].asString(); std::string const methodName = (*jsonMessage)["method"].asString();
id = (*jsonMessage)["id"]; id = (*jsonMessage)["id"];
lspDebug(fmt::format("received method call: {}", methodName)); lspDebug(fmt::format("received method call: {}", methodName));
@ -391,7 +390,7 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
// The default of FileReader is to use `.`, but the path from where the LSP was started // The default of FileReader is to use `.`, but the path from where the LSP was started
// should not matter. // should not matter.
string rootPath("/"); std::string rootPath("/");
if (Json::Value uri = _args["rootUri"]) if (Json::Value uri = _args["rootUri"])
{ {
rootPath = uri.asString(); rootPath = uri.asString();
@ -414,7 +413,7 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
Json::Value replyArgs; Json::Value replyArgs;
replyArgs["serverInfo"]["name"] = "solc"; replyArgs["serverInfo"]["name"] = "solc";
replyArgs["serverInfo"]["version"] = string(VersionNumber); replyArgs["serverInfo"]["version"] = std::string(VersionNumber);
replyArgs["capabilities"]["definitionProvider"] = true; replyArgs["capabilities"]["definitionProvider"] = true;
replyArgs["capabilities"]["implementationProvider"] = true; replyArgs["capabilities"]["implementationProvider"] = true;
replyArgs["capabilities"]["textDocumentSync"]["change"] = 2; // 0=none, 1=full, 2=incremental replyArgs["capabilities"]["textDocumentSync"]["change"] = 2; // 0=none, 1=full, 2=incremental
@ -440,7 +439,7 @@ void LanguageServer::semanticTokensFull(MessageID _id, Json::Value const& _args)
compile(); compile();
auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as<string>()); auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as<std::string>());
SourceUnit const& ast = m_compilerStack.ast(sourceName); SourceUnit const& ast = m_compilerStack.ast(sourceName);
m_compilerStack.charStream(sourceName); m_compilerStack.charStream(sourceName);
Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName)); Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName));
@ -465,7 +464,7 @@ void LanguageServer::setTrace(Json::Value const& _args)
// Simply ignore invalid parameter. // Simply ignore invalid parameter.
return; return;
string const stringValue = _args.asString(); std::string const stringValue = _args.asString();
if (stringValue == "off") if (stringValue == "off")
m_client.setTrace(TraceValue::Off); m_client.setTrace(TraceValue::Off);
else if (stringValue == "messages") else if (stringValue == "messages")
@ -484,8 +483,8 @@ void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args)
"Text document parameter missing." "Text document parameter missing."
); );
string text = _args["textDocument"]["text"].asString(); std::string text = _args["textDocument"]["text"].asString();
string uri = _args["textDocument"]["uri"].asString(); std::string uri = _args["textDocument"]["uri"].asString();
m_openFiles.insert(uri); m_openFiles.insert(uri);
m_fileRepository.setSourceByUri(uri, std::move(text)); m_fileRepository.setSourceByUri(uri, std::move(text));
compileAndUpdateDiagnostics(); compileAndUpdateDiagnostics();
@ -495,7 +494,7 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
{ {
requireServerInitialized(); requireServerInitialized();
string const uri = _args["textDocument"]["uri"].asString(); std::string const uri = _args["textDocument"]["uri"].asString();
for (Json::Value jsonContentChange: _args["contentChanges"]) for (Json::Value jsonContentChange: _args["contentChanges"])
{ {
@ -505,24 +504,24 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
"Invalid content reference." "Invalid content reference."
); );
string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri); std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri);
lspRequire( lspRequire(
m_fileRepository.sourceUnits().count(sourceUnitName), m_fileRepository.sourceUnits().count(sourceUnitName),
ErrorCode::RequestFailed, ErrorCode::RequestFailed,
"Unknown file: " + uri "Unknown file: " + uri
); );
string text = jsonContentChange["text"].asString(); std::string text = jsonContentChange["text"].asString();
if (jsonContentChange["range"].isObject()) // otherwise full content update if (jsonContentChange["range"].isObject()) // otherwise full content update
{ {
optional<SourceLocation> change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]); std::optional<SourceLocation> change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]);
lspRequire( lspRequire(
change && change->hasText(), change && change->hasText(),
ErrorCode::RequestFailed, ErrorCode::RequestFailed,
"Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"]) "Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"])
); );
string buffer = m_fileRepository.sourceUnits().at(sourceUnitName); std::string buffer = m_fileRepository.sourceUnits().at(sourceUnitName);
buffer.replace(static_cast<size_t>(change->start), static_cast<size_t>(change->end - change->start), std::move(text)); buffer.replace(static_cast<size_t>(change->start), static_cast<size_t>(change->end - change->start), std::move(text));
text = std::move(buffer); text = std::move(buffer);
} }
@ -542,7 +541,7 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
"Text document parameter missing." "Text document parameter missing."
); );
string uri = _args["textDocument"]["uri"].asString(); std::string uri = _args["textDocument"]["uri"].asString();
m_openFiles.erase(uri); m_openFiles.erase(uri);
compileAndUpdateDiagnostics(); compileAndUpdateDiagnostics();
@ -550,17 +549,17 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos) ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
{ {
return get<ASTNode const*>(astNodeAndOffsetAtSourceLocation(_sourceUnitName, _filePos)); return std::get<ASTNode const*>(astNodeAndOffsetAtSourceLocation(_sourceUnitName, _filePos));
} }
tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos) std::tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
{ {
if (m_compilerStack.state() < CompilerStack::AnalysisPerformed) if (m_compilerStack.state() < CompilerStack::AnalysisSuccessful)
return {nullptr, -1}; return {nullptr, -1};
if (!m_fileRepository.sourceUnits().count(_sourceUnitName)) if (!m_fileRepository.sourceUnits().count(_sourceUnitName))
return {nullptr, -1}; return {nullptr, -1};
optional<int> sourcePos = m_compilerStack.charStream(_sourceUnitName).translateLineColumnToPosition(_filePos); std::optional<int> sourcePos = m_compilerStack.charStream(_sourceUnitName).translateLineColumnToPosition(_filePos);
if (!sourcePos) if (!sourcePos)
return {nullptr, -1}; return {nullptr, -1};

View File

@ -29,7 +29,6 @@
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::lsp; using namespace solidity::lsp;
using namespace std;
namespace namespace
{ {
@ -51,8 +50,8 @@ CallableDeclaration const* extractCallableDeclaration(FunctionCall const& _funct
void RenameSymbol::operator()(MessageID _id, Json::Value const& _args) void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
{ {
auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args); auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
string const newName = _args["newName"].asString(); std::string const newName = _args["newName"].asString();
string const uri = _args["textDocument"]["uri"].asString(); std::string const uri = _args["textDocument"]["uri"].asString();
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn); ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
@ -61,7 +60,7 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
m_sourceUnits = { &m_server.compilerStack().ast(sourceUnitName) }; m_sourceUnits = { &m_server.compilerStack().ast(sourceUnitName) };
m_locations.clear(); m_locations.clear();
optional<int> cursorBytePosition = charStreamProvider() std::optional<int> cursorBytePosition = charStreamProvider()
.charStream(sourceUnitName) .charStream(sourceUnitName)
.translateLineColumnToPosition(lineColumn); .translateLineColumnToPosition(lineColumn);
solAssert(cursorBytePosition.has_value(), "Expected source pos"); solAssert(cursorBytePosition.has_value(), "Expected source pos");
@ -72,7 +71,7 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
for (auto const& [name, content]: fileRepository().sourceUnits()) for (auto const& [name, content]: fileRepository().sourceUnits())
{ {
auto const& sourceUnit = m_server.compilerStack().ast(name); auto const& sourceUnit = m_server.compilerStack().ast(name);
for (auto const* referencedSourceUnit: sourceUnit.referencedSourceUnits(true, util::convertContainer<set<SourceUnit const*>>(m_sourceUnits))) for (auto const* referencedSourceUnit: sourceUnit.referencedSourceUnits(true, util::convertContainer<std::set<SourceUnit const*>>(m_sourceUnits)))
if (*referencedSourceUnit->location().sourceName == sourceUnitName) if (*referencedSourceUnit->location().sourceName == sourceUnitName)
{ {
m_sourceUnits.insert(&sourceUnit); m_sourceUnits.insert(&sourceUnit);
@ -101,8 +100,8 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
solAssert(i->isValid()); solAssert(i->isValid());
// Replace in our file repository // Replace in our file repository
string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName); std::string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName);
string buffer = fileRepository().sourceUnits().at(*i->sourceName); std::string buffer = fileRepository().sourceUnits().at(*i->sourceName);
buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName); buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName);
fileRepository().setSourceByUri(uri, std::move(buffer)); fileRepository().setSourceByUri(uri, std::move(buffer));
@ -155,7 +154,7 @@ void RenameSymbol::extractNameAndDeclaration(ASTNode const& _node, int _cursorBy
else if (auto const* inlineAssembly = dynamic_cast<InlineAssembly const*>(&_node)) else if (auto const* inlineAssembly = dynamic_cast<InlineAssembly const*>(&_node))
extractNameAndDeclaration(*inlineAssembly, _cursorBytePosition); extractNameAndDeclaration(*inlineAssembly, _cursorBytePosition);
else else
solAssert(false, "Unexpected ASTNODE id: " + to_string(_node.id())); solAssert(false, "Unexpected ASTNODE id: " + std::to_string(_node.id()));
lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end)); lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end));
} }
@ -297,7 +296,7 @@ void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node)
{ {
for (auto&& [identifier, externalReference]: _node.annotation().externalReferences) for (auto&& [identifier, externalReference]: _node.annotation().externalReferences)
{ {
string identifierName = identifier->name.str(); std::string identifierName = identifier->name.str();
if (!externalReference.suffix.empty()) if (!externalReference.suffix.empty())
identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1); identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1);

View File

@ -23,7 +23,6 @@
#include <fmt/format.h> #include <fmt/format.h>
using namespace std;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -33,10 +32,10 @@ namespace solidity::lsp
namespace namespace
{ {
optional<SemanticTokenType> semanticTokenTypeForType(frontend::Type const* _type) std::optional<SemanticTokenType> semanticTokenTypeForType(frontend::Type const* _type)
{ {
if (!_type) if (!_type)
return nullopt; return std::nullopt;
switch (_type->category()) switch (_type->category())
{ {
@ -119,7 +118,7 @@ void SemanticTokensBuilder::encode(
auto const [line, startChar] = m_charStream->translatePositionToLineColumn(_sourceLocation.start); auto const [line, startChar] = m_charStream->translatePositionToLineColumn(_sourceLocation.start);
auto const length = _sourceLocation.end - _sourceLocation.start; auto const length = _sourceLocation.end - _sourceLocation.start;
lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, _tokenType)); lspDebug(fmt::format("encode [{}:{}..{}] {}", line, startChar, length, static_cast<int>(_tokenType)));
m_encodedTokens.append(line - m_lastLine); m_encodedTokens.append(line - m_lastLine);
if (line == m_lastLine) if (line == m_lastLine)

View File

@ -37,34 +37,33 @@
#include <fcntl.h> #include <fcntl.h>
#endif #endif
using namespace std;
using namespace solidity::lsp; using namespace solidity::lsp;
// {{{ Transport // {{{ Transport
optional<Json::Value> Transport::receive() std::optional<Json::Value> Transport::receive()
{ {
auto const headers = parseHeaders(); auto const headers = parseHeaders();
if (!headers) if (!headers)
{ {
error({}, ErrorCode::ParseError, "Could not parse RPC headers."); error({}, ErrorCode::ParseError, "Could not parse RPC headers.");
return nullopt; return std::nullopt;
} }
if (!headers->count("content-length")) if (!headers->count("content-length"))
{ {
error({}, ErrorCode::ParseError, "No content-length header found."); error({}, ErrorCode::ParseError, "No content-length header found.");
return nullopt; return std::nullopt;
} }
string const data = readBytes(stoul(headers->at("content-length"))); std::string const data = readBytes(stoul(headers->at("content-length")));
Json::Value jsonMessage; Json::Value jsonMessage;
string jsonParsingErrors; std::string jsonParsingErrors;
solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors); solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors);
if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject()) if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject())
{ {
error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors); error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors);
return nullopt; return std::nullopt;
} }
return {std::move(jsonMessage)}; return {std::move(jsonMessage)};
@ -82,9 +81,9 @@ void Transport::trace(std::string _message, Json::Value _extra)
} }
} }
optional<map<string, string>> Transport::parseHeaders() std::optional<std::map<std::string, std::string>> Transport::parseHeaders()
{ {
map<string, string> headers; std::map<std::string, std::string> headers;
while (true) while (true)
{ {
@ -93,18 +92,18 @@ optional<map<string, string>> Transport::parseHeaders()
break; break;
auto const delimiterPos = line.find(':'); auto const delimiterPos = line.find(':');
if (delimiterPos == string::npos) if (delimiterPos == std::string::npos)
return nullopt; return std::nullopt;
auto const name = boost::to_lower_copy(line.substr(0, delimiterPos)); auto const name = boost::to_lower_copy(line.substr(0, delimiterPos));
auto const value = line.substr(delimiterPos + 1); auto const value = line.substr(delimiterPos + 1);
if (!headers.emplace(boost::trim_copy(name), boost::trim_copy(value)).second) if (!headers.emplace(boost::trim_copy(name), boost::trim_copy(value)).second)
return nullopt; return std::nullopt;
} }
return {std::move(headers)}; return {std::move(headers)};
} }
void Transport::notify(string _method, Json::Value _message) void Transport::notify(std::string _method, Json::Value _message)
{ {
Json::Value json; Json::Value json;
json["method"] = std::move(_method); json["method"] = std::move(_method);
@ -119,7 +118,7 @@ void Transport::reply(MessageID _id, Json::Value _message)
send(std::move(json), _id); send(std::move(json), _id);
} }
void Transport::error(MessageID _id, ErrorCode _code, string _message) void Transport::error(MessageID _id, ErrorCode _code, std::string _message)
{ {
Json::Value json; Json::Value json;
json["error"]["code"] = static_cast<int>(_code); json["error"]["code"] = static_cast<int>(_code);
@ -135,7 +134,7 @@ void Transport::send(Json::Value _json, MessageID _id)
_json["id"] = _id; _json["id"] = _id;
// Trailing CRLF only for easier readability. // Trailing CRLF only for easier readability.
string const jsonString = solidity::util::jsonCompactPrint(_json); std::string const jsonString = solidity::util::jsonCompactPrint(_json);
writeBytes(fmt::format("Content-Length: {}\r\n\r\n", jsonString.size())); writeBytes(fmt::format("Content-Length: {}\r\n\r\n", jsonString.size()));
writeBytes(jsonString); writeBytes(jsonString);
@ -144,7 +143,7 @@ void Transport::send(Json::Value _json, MessageID _id)
// }}} // }}}
// {{{ IOStreamTransport // {{{ IOStreamTransport
IOStreamTransport::IOStreamTransport(istream& _in, ostream& _out): IOStreamTransport::IOStreamTransport(std::istream& _in, std::ostream& _out):
m_input{_in}, m_input{_in},
m_output{_out} m_output{_out}
{ {
@ -162,7 +161,7 @@ std::string IOStreamTransport::readBytes(size_t _length)
std::string IOStreamTransport::getline() std::string IOStreamTransport::getline()
{ {
string line; std::string line;
std::getline(m_input, line); std::getline(m_input, line);
return line; return line;
} }

View File

@ -30,21 +30,20 @@ namespace solidity::lsp
using namespace frontend; using namespace frontend;
using namespace langutil; using namespace langutil;
using namespace std;
optional<LineColumn> parseLineColumn(Json::Value const& _lineColumn) std::optional<LineColumn> parseLineColumn(Json::Value const& _lineColumn)
{ {
if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt()) if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt())
return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()}; return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()};
else else
return nullopt; return std::nullopt;
} }
Json::Value toJson(LineColumn const& _pos) Json::Value toJson(LineColumn const& _pos)
{ {
Json::Value json = Json::objectValue; Json::Value json = Json::objectValue;
json["line"] = max(_pos.line, 0); json["line"] = std::max(_pos.line, 0);
json["character"] = max(_pos.column, 0); json["character"] = std::max(_pos.column, 0);
return json; return json;
} }
@ -70,10 +69,10 @@ Declaration const* referencedDeclaration(Expression const* _expression)
return nullptr; return nullptr;
} }
optional<SourceLocation> declarationLocation(Declaration const* _declaration) std::optional<SourceLocation> declarationLocation(Declaration const* _declaration)
{ {
if (!_declaration) if (!_declaration)
return nullopt; return std::nullopt;
if (_declaration->nameLocation().isValid()) if (_declaration->nameLocation().isValid())
return _declaration->nameLocation(); return _declaration->nameLocation();
@ -81,43 +80,43 @@ optional<SourceLocation> declarationLocation(Declaration const* _declaration)
if (_declaration->location().isValid()) if (_declaration->location().isValid())
return _declaration->location(); return _declaration->location();
return nullopt; return std::nullopt;
} }
optional<SourceLocation> parsePosition( std::optional<SourceLocation> parsePosition(
FileRepository const& _fileRepository, FileRepository const& _fileRepository,
string const& _sourceUnitName, std::string const& _sourceUnitName,
Json::Value const& _position Json::Value const& _position
) )
{ {
if (!_fileRepository.sourceUnits().count(_sourceUnitName)) if (!_fileRepository.sourceUnits().count(_sourceUnitName))
return nullopt; return std::nullopt;
if (optional<LineColumn> lineColumn = parseLineColumn(_position)) if (std::optional<LineColumn> lineColumn = parseLineColumn(_position))
if (optional<int> const offset = CharStream::translateLineColumnToPosition( if (std::optional<int> const offset = CharStream::translateLineColumnToPosition(
_fileRepository.sourceUnits().at(_sourceUnitName), _fileRepository.sourceUnits().at(_sourceUnitName),
*lineColumn *lineColumn
)) ))
return SourceLocation{*offset, *offset, make_shared<string>(_sourceUnitName)}; return SourceLocation{*offset, *offset, std::make_shared<std::string>(_sourceUnitName)};
return nullopt; return std::nullopt;
} }
optional<SourceLocation> parseRange(FileRepository const& _fileRepository, string const& _sourceUnitName, Json::Value const& _range) std::optional<SourceLocation> parseRange(FileRepository const& _fileRepository, std::string const& _sourceUnitName, Json::Value const& _range)
{ {
if (!_range.isObject()) if (!_range.isObject())
return nullopt; return std::nullopt;
optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]); std::optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]);
optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]); std::optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]);
if (!start || !end) if (!start || !end)
return nullopt; return std::nullopt;
solAssert(*start->sourceName == *end->sourceName); solAssert(*start->sourceName == *end->sourceName);
start->end = end->end; start->end = end->end;
return start; return start;
} }
string stripFileUriSchemePrefix(string const& _path) std::string stripFileUriSchemePrefix(std::string const& _path)
{ {
regex const windowsDriveLetterPath("^file:///[a-zA-Z]:/"); std::regex const windowsDriveLetterPath("^file:///[a-zA-Z]:/");
if (regex_search(_path, windowsDriveLetterPath)) if (regex_search(_path, windowsDriveLetterPath))
return _path.substr(8); return _path.substr(8);
if (_path.find("file://") == 0) if (_path.find("file://") == 0)

View File

@ -28,7 +28,6 @@
#include <range/v3/algorithm/find_if_not.hpp> #include <range/v3/algorithm/find_if_not.hpp>
#include <range/v3/view/subrange.hpp> #include <range/v3/view/subrange.hpp>
using namespace std;
using namespace solidity; using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
@ -36,17 +35,17 @@ using namespace solidity::frontend;
namespace namespace
{ {
string::const_iterator skipLineOrEOS( std::string::const_iterator skipLineOrEOS(
string::const_iterator _nlPos, std::string::const_iterator _nlPos,
string::const_iterator _end std::string::const_iterator _end
) )
{ {
return (_nlPos == _end) ? _end : ++_nlPos; return (_nlPos == _end) ? _end : ++_nlPos;
} }
string::const_iterator firstNonIdentifier( std::string::const_iterator firstNonIdentifier(
string::const_iterator _pos, std::string::const_iterator _pos,
string::const_iterator _end std::string::const_iterator _end
) )
{ {
auto currPos = _pos; auto currPos = _pos;
@ -58,18 +57,18 @@ string::const_iterator firstNonIdentifier(
return currPos; return currPos;
} }
string::const_iterator firstWhitespaceOrNewline( std::string::const_iterator firstWhitespaceOrNewline(
string::const_iterator _pos, std::string::const_iterator _pos,
string::const_iterator _end std::string::const_iterator _end
) )
{ {
return ranges::find_first_of(ranges::make_subrange(_pos, _end), " \t\n"); return ranges::find_first_of(ranges::make_subrange(_pos, _end), " \t\n");
} }
string::const_iterator skipWhitespace( std::string::const_iterator skipWhitespace(
string::const_iterator _pos, std::string::const_iterator _pos,
string::const_iterator _end std::string::const_iterator _end
) )
{ {
auto isWhitespace = [](char const& c) { return (c == ' ' || c == '\t'); }; auto isWhitespace = [](char const& c) { return (c == ' ' || c == '\t'); };
@ -78,7 +77,7 @@ string::const_iterator skipWhitespace(
} }
multimap<string, DocTag> DocStringParser::parse() std::multimap<std::string, DocTag> DocStringParser::parse()
{ {
m_lastTag = nullptr; m_lastTag = nullptr;
m_docTags = {}; m_docTags = {};
@ -96,7 +95,7 @@ multimap<string, DocTag> DocStringParser::parse()
{ {
// we found a tag // we found a tag
iter tagNameEndPos = firstWhitespaceOrNewline(tagPos, end); iter tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
string tagName{tagPos + 1, tagNameEndPos}; std::string tagName{tagPos + 1, tagNameEndPos};
iter tagDataPos = (tagNameEndPos != end) ? tagNameEndPos + 1 : tagNameEndPos; iter tagDataPos = (tagNameEndPos != end) ? tagNameEndPos + 1 : tagNameEndPos;
currPos = parseDocTag(tagDataPos, end, tagName); currPos = parseDocTag(tagDataPos, end, tagName);
} }
@ -141,7 +140,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
return _end; return _end;
} }
auto nameEndPos = firstNonIdentifier(nameStartPos, _end); auto nameEndPos = firstNonIdentifier(nameStartPos, _end);
auto paramName = string(nameStartPos, nameEndPos); auto paramName = std::string(nameStartPos, nameEndPos);
auto descStartPos = skipWhitespace(nameEndPos, _end); auto descStartPos = skipWhitespace(nameEndPos, _end);
auto nlPos = find(descStartPos, _end, '\n'); auto nlPos = find(descStartPos, _end, '\n');
@ -152,7 +151,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
return _end; return _end;
} }
auto paramDesc = string(descStartPos, nlPos); auto paramDesc = std::string(descStartPos, nlPos);
newTag("param"); newTag("param");
m_lastTag->paramName = paramName; m_lastTag->paramName = paramName;
m_lastTag->content = paramDesc; m_lastTag->content = paramDesc;
@ -160,7 +159,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
return skipLineOrEOS(nlPos, _end); return skipLineOrEOS(nlPos, _end);
} }
DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, string const& _tag) DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, std::string const& _tag)
{ {
// TODO: need to check for @(start of a tag) between here and the end of line // TODO: need to check for @(start of a tag) between here and the end of line
// for all cases. // for all cases.
@ -178,7 +177,7 @@ DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, string
return parseDocTagLine(_pos, _end, true); return parseDocTagLine(_pos, _end, true);
} }
void DocStringParser::newTag(string const& _tagName) void DocStringParser::newTag(std::string const& _tagName)
{ {
m_lastTag = &m_docTags.insert(make_pair(_tagName, DocTag()))->second; m_lastTag = &m_docTags.insert(make_pair(_tagName, DocTag()))->second;
} }

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