mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'develop' into patch-2
This commit is contained in:
commit
c43c3c3a3a
@ -179,47 +179,199 @@ commands:
|
||||
paths:
|
||||
- << parameters.install_path >>
|
||||
|
||||
defaults:
|
||||
# --------------------------------------------------------------------------
|
||||
# Build Commands
|
||||
|
||||
setup_prerelease_commit_hash:
|
||||
steps:
|
||||
- run:
|
||||
name: Store commit hash and prerelease
|
||||
command: |
|
||||
if [[ $CIRCLE_BRANCH == release || -n $CIRCLE_TAG ]]; then
|
||||
echo -n > prerelease.txt;
|
||||
else
|
||||
date -u +"nightly.%Y.%-m.%-d" > prerelease.txt;
|
||||
fi
|
||||
echo -n "$CIRCLE_SHA1" > commit_hash.txt
|
||||
|
||||
run_build:
|
||||
steps:
|
||||
- run:
|
||||
name: Build
|
||||
command: scripts/ci/build.sh
|
||||
|
||||
run_build_ossfuzz:
|
||||
steps:
|
||||
- run:
|
||||
name: Build_ossfuzz
|
||||
command: scripts/ci/build_ossfuzz.sh
|
||||
|
||||
run_proofs:
|
||||
steps:
|
||||
- run:
|
||||
name: Correctness proofs for optimization rules
|
||||
command: scripts/run_proofs.sh
|
||||
|
||||
run_soltest:
|
||||
steps:
|
||||
- run:
|
||||
name: soltest
|
||||
no_output_timeout: 30m
|
||||
command: .circleci/soltest.sh
|
||||
|
||||
run_soltest_all:
|
||||
steps:
|
||||
- run:
|
||||
name: soltest_all
|
||||
no_output_timeout: 30m
|
||||
command: .circleci/soltest_all.sh
|
||||
|
||||
run_cmdline_tests:
|
||||
steps:
|
||||
- run:
|
||||
name: command line tests
|
||||
no_output_timeout: 30m
|
||||
command: .circleci/parallel_cli_tests.py
|
||||
|
||||
run_docs_pragma_min_version:
|
||||
steps:
|
||||
- run:
|
||||
name: docs pragma version check
|
||||
command: scripts/docs_version_pragma_check.sh
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Build Templates
|
||||
# Artifact Commands
|
||||
|
||||
- setup_prerelease_commit_hash: &setup_prerelease_commit_hash
|
||||
name: Store commit hash and prerelease
|
||||
command: |
|
||||
if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
|
||||
echo -n "$CIRCLE_SHA1" > commit_hash.txt
|
||||
store_artifacts_solc:
|
||||
description: Store compiled solc executable as artifact
|
||||
steps:
|
||||
- store_artifacts:
|
||||
path: build/solc/solc
|
||||
destination: solc
|
||||
|
||||
- run_build: &run_build
|
||||
name: Build
|
||||
command: scripts/ci/build.sh
|
||||
store_artifacts_yul_phaser:
|
||||
steps:
|
||||
- store_artifacts:
|
||||
path: build/tools/yul-phaser
|
||||
destination: yul-phaser
|
||||
|
||||
- run_build_ossfuzz: &run_build_ossfuzz
|
||||
name: Build_ossfuzz
|
||||
command: scripts/ci/build_ossfuzz.sh
|
||||
persist_executables_to_workspace:
|
||||
description: Persist compiled target executables to workspace
|
||||
steps:
|
||||
- persist_to_workspace:
|
||||
root: build
|
||||
paths:
|
||||
- solc/solc
|
||||
- test/soltest
|
||||
- test/tools/solfuzzer
|
||||
|
||||
- run_proofs: &run_proofs
|
||||
name: Correctness proofs for optimization rules
|
||||
command: scripts/run_proofs.sh
|
||||
persist_executables_to_workspace_osx:
|
||||
description: Persist compiled target executables to workspace on macOS
|
||||
steps:
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- build/solc/solc
|
||||
- build/test/soltest
|
||||
- build/test/tools/solfuzzer
|
||||
|
||||
- run_soltest: &run_soltest
|
||||
name: soltest
|
||||
no_output_timeout: 30m
|
||||
command: ./.circleci/soltest.sh
|
||||
persist_ossfuzz_executables_to_workspace:
|
||||
description: Persist compiled OSSFUZZ executables to workspace
|
||||
steps:
|
||||
- persist_to_workspace:
|
||||
root: build
|
||||
paths:
|
||||
- test/tools/ossfuzz/abiv2_proto_ossfuzz
|
||||
- test/tools/ossfuzz/abiv2_isabelle_ossfuzz
|
||||
- test/tools/ossfuzz/const_opt_ossfuzz
|
||||
- test/tools/ossfuzz/solc_mutator_ossfuzz
|
||||
- test/tools/ossfuzz/solc_ossfuzz
|
||||
- test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_diff_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_opt_ossfuzz
|
||||
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
|
||||
- test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
|
||||
- test/tools/ossfuzz/yul_proto_ossfuzz
|
||||
- test/tools/ossfuzz/sol_proto_ossfuzz
|
||||
|
||||
- run_soltest_all: &run_soltest_all
|
||||
name: soltest_all
|
||||
no_output_timeout: 30m
|
||||
command: ./.circleci/soltest_all.sh
|
||||
store_artifacts_test_results:
|
||||
description: Store test output dir as artifact
|
||||
steps:
|
||||
- store_artifacts:
|
||||
path: test_results/
|
||||
destination: test_results/
|
||||
|
||||
- run_cmdline_tests: &run_cmdline_tests
|
||||
name: command line tests
|
||||
no_output_timeout: 30m
|
||||
command: .circleci/parallel_cli_tests.py
|
||||
# --------------------------------------------------------------------------
|
||||
# Complex Build Commands
|
||||
|
||||
- run_docs_pragma_min_version: &run_docs_pragma_min_version
|
||||
name: docs pragma version check
|
||||
command: ./scripts/docs_version_pragma_check.sh
|
||||
soltest:
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
# NOTE: Different build jobs produce different soltest executables (release/debug,
|
||||
# clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the
|
||||
# attached workspace and we only see the items added to the workspace by jobs we depend on.
|
||||
- run_soltest
|
||||
- store_test_results:
|
||||
path: test_results/
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
test_lsp:
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: pip install --user deepdiff colorama
|
||||
- run:
|
||||
name: Executing solc LSP test suite
|
||||
command: test/lsp.py build/solc/solc --non-interactive
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
build:
|
||||
steps:
|
||||
- checkout
|
||||
- run_build
|
||||
- store_artifacts_solc
|
||||
- store_artifacts_yul_phaser
|
||||
- persist_executables_to_workspace
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
soltest_all:
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run_soltest_all
|
||||
- store_test_results:
|
||||
path: test_results/
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
cmdline_tests:
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run_cmdline_tests
|
||||
- store_test_results:
|
||||
path: test_results/
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
install_dependencies_osx:
|
||||
steps:
|
||||
# FIXME: We used to cache dependencies on macOS but now it takes longer than just installing
|
||||
# them each time. See https://github.com/ethereum/solidity/issues/12925.
|
||||
- run:
|
||||
name: Install build dependencies
|
||||
command: .circleci/osx_install_dependencies.sh
|
||||
|
||||
defaults:
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Matrix templates
|
||||
@ -241,122 +393,6 @@ defaults:
|
||||
- via-ir-no-optimize
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Artifacts Templates
|
||||
|
||||
# compiled solc executable target
|
||||
- artifacts_solc: &artifacts_solc
|
||||
path: build/solc/solc
|
||||
destination: solc
|
||||
|
||||
# windows artifacts
|
||||
- artifact_solc_windows: &artifact_solc_windows
|
||||
path: upload/
|
||||
|
||||
- artifact_yul_phaser: &artifact_yul_phaser
|
||||
path: build/tools/yul-phaser
|
||||
destination: yul-phaser
|
||||
|
||||
# compiled executable targets
|
||||
- artifacts_executables: &artifacts_executables
|
||||
root: build
|
||||
paths:
|
||||
- solc/solc
|
||||
- test/soltest
|
||||
- test/tools/solfuzzer
|
||||
|
||||
# compiled OSSFUZZ targets
|
||||
- artifacts_executables_ossfuzz: &artifacts_executables_ossfuzz
|
||||
root: build
|
||||
paths:
|
||||
- test/tools/ossfuzz/abiv2_proto_ossfuzz
|
||||
- test/tools/ossfuzz/abiv2_isabelle_ossfuzz
|
||||
- test/tools/ossfuzz/const_opt_ossfuzz
|
||||
- test/tools/ossfuzz/solc_mutator_ossfuzz
|
||||
- test/tools/ossfuzz/solc_ossfuzz
|
||||
- test/tools/ossfuzz/stack_reuse_codegen_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_assembly_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_diff_ossfuzz
|
||||
- test/tools/ossfuzz/strictasm_opt_ossfuzz
|
||||
- test/tools/ossfuzz/yul_proto_diff_ossfuzz
|
||||
- test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz
|
||||
- test/tools/ossfuzz/yul_proto_ossfuzz
|
||||
- test/tools/ossfuzz/sol_proto_ossfuzz
|
||||
|
||||
# test result output directory
|
||||
- artifacts_test_results: &artifacts_test_results
|
||||
path: test_results/
|
||||
destination: test_results/
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Step Templates
|
||||
|
||||
# store_test_results helper
|
||||
- store_test_results: &store_test_results
|
||||
path: test_results/
|
||||
|
||||
- steps_soltest: &steps_soltest
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
# NOTE: Different build jobs produce different soltest executables (release/debug,
|
||||
# clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the
|
||||
# attached workspace and we only see the items added to the workspace by jobs we depend on.
|
||||
- run: *run_soltest
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
- steps_test_lsp: &steps_test_lsp
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: pip install --user deepdiff colorama
|
||||
- run:
|
||||
name: Executing solc LSP test suite
|
||||
command: ./test/lsp.py ./build/solc/solc --non-interactive
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
- steps_build: &steps_build
|
||||
steps:
|
||||
- checkout
|
||||
- run: *run_build
|
||||
- store_artifacts: *artifacts_solc
|
||||
- store_artifacts: *artifact_yul_phaser
|
||||
- persist_to_workspace: *artifacts_executables
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
- steps_soltest_all: &steps_soltest_all
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run: *run_soltest_all
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
- steps_cmdline_tests: &steps_cmdline_tests
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run: *run_cmdline_tests
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
- steps_install_dependencies_osx: &steps_install_dependencies_osx
|
||||
steps:
|
||||
# FIXME: We used to cache dependencies on macOS but now it takes longer than just installing
|
||||
# them each time. See https://github.com/ethereum/solidity/issues/12925.
|
||||
- run:
|
||||
name: Install build dependencies
|
||||
command: ./.circleci/osx_install_dependencies.sh
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Base Image Templates
|
||||
|
||||
@ -767,7 +803,11 @@ jobs:
|
||||
pip install --user codespell
|
||||
- run:
|
||||
name: Check spelling
|
||||
command: ~/.local/bin/codespell --skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" --ignore-words ./scripts/codespell_whitelist.txt --exclude-file ./scripts/codespell_ignored_lines.txt
|
||||
command: |
|
||||
~/.local/bin/codespell \
|
||||
--skip "*.enc,.git,Dockerfile*,LICENSE,codespell_whitelist.txt,codespell_ignored_lines.txt" \
|
||||
--ignore-words scripts/codespell_whitelist.txt \
|
||||
--exclude-file scripts/codespell_ignored_lines.txt
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_docs_examples:
|
||||
@ -781,7 +821,7 @@ jobs:
|
||||
command: sudo npm install -g solhint
|
||||
- run:
|
||||
name: Test Docs examples
|
||||
command: ./test/docsCodeStyle.sh
|
||||
command: test/docsCodeStyle.sh
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_coding_style:
|
||||
@ -795,13 +835,13 @@ jobs:
|
||||
sudo apt install -y shellcheck
|
||||
- run:
|
||||
name: Check for C++ coding style
|
||||
command: ./scripts/check_style.sh
|
||||
command: scripts/check_style.sh
|
||||
- run:
|
||||
name: checking shell scripts
|
||||
command: ./scripts/chk_shellscripts/chk_shellscripts.sh
|
||||
command: scripts/chk_shellscripts/chk_shellscripts.sh
|
||||
- run:
|
||||
name: Check for broken symlinks
|
||||
command: ./scripts/check_symlinks.sh
|
||||
command: scripts/check_symlinks.sh
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_errorcodes:
|
||||
@ -810,7 +850,7 @@ jobs:
|
||||
- checkout
|
||||
- run:
|
||||
name: Check for error codes
|
||||
command: ./scripts/error_codes.py --check
|
||||
command: scripts/error_codes.py --check
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_pylint:
|
||||
@ -830,7 +870,7 @@ jobs:
|
||||
- run: pylint --version
|
||||
- run:
|
||||
name: Linting Python Scripts
|
||||
command: ./scripts/pylint_all.py
|
||||
command: scripts/pylint_all.py
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_antlr_grammar:
|
||||
@ -844,7 +884,7 @@ jobs:
|
||||
sudo apt install -y openjdk-17-jdk
|
||||
- run:
|
||||
name: Run tests
|
||||
command: ./scripts/test_antlr_grammar.sh
|
||||
command: scripts/test_antlr_grammar.sh
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_buglist:
|
||||
@ -859,7 +899,7 @@ jobs:
|
||||
npm install mktemp
|
||||
- run:
|
||||
name: Test buglist
|
||||
command: ./test/buglistTests.js
|
||||
command: test/buglistTests.js
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_proofs:
|
||||
@ -868,14 +908,14 @@ jobs:
|
||||
- checkout
|
||||
- install_python3:
|
||||
packages: z3-solver
|
||||
- run: *run_proofs
|
||||
- run_proofs
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
chk_docs_pragma_min_version:
|
||||
<<: *base_ubuntu2204_small
|
||||
steps:
|
||||
- checkout
|
||||
- run: *run_docs_pragma_min_version
|
||||
- run_docs_pragma_min_version
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
t_ubu_pyscripts:
|
||||
@ -901,7 +941,8 @@ jobs:
|
||||
# this runs 2x faster on xlarge but takes 4x more resources (compared to medium).
|
||||
# Enough other jobs depend on it that it's worth it though.
|
||||
<<: *base_ubuntu2204_xlarge
|
||||
<<: *steps_build
|
||||
steps:
|
||||
- build
|
||||
|
||||
# x64 ASAN build, for testing for memory related bugs
|
||||
b_ubu_asan: &b_ubu_asan
|
||||
@ -911,14 +952,16 @@ jobs:
|
||||
<<: *base_ubuntu2204_env
|
||||
CMAKE_OPTIONS: -DSANITIZE=address
|
||||
CMAKE_BUILD_TYPE: Release
|
||||
<<: *steps_build
|
||||
steps:
|
||||
- build
|
||||
|
||||
b_ubu_clang: &b_ubu_clang
|
||||
<<: *base_ubuntu2204_clang_large
|
||||
environment:
|
||||
<<: *base_ubuntu2204_clang_large_env
|
||||
MAKEFLAGS: -j 10
|
||||
<<: *steps_build
|
||||
steps:
|
||||
- build
|
||||
|
||||
b_ubu_san_clang:
|
||||
# This runs a bit faster on large and xlarge but on nightly efficiency matters more.
|
||||
@ -929,7 +972,8 @@ jobs:
|
||||
environment:
|
||||
<<: *base_ubuntu2204_clang_env
|
||||
CMAKE_OPTIONS: << parameters.cmake_options >>
|
||||
<<: *steps_build
|
||||
steps:
|
||||
- build
|
||||
|
||||
b_ubu_force_release: &b_ubu_force_release
|
||||
<<: *b_ubu
|
||||
@ -948,7 +992,7 @@ jobs:
|
||||
CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DUSE_Z3_DLOPEN=ON -DUSE_CVC4=OFF -DSOLC_STATIC_STDLIBS=ON
|
||||
steps:
|
||||
- checkout
|
||||
- run: *run_build
|
||||
- run_build
|
||||
- run:
|
||||
name: strip binary
|
||||
command: strip build/solc/solc
|
||||
@ -971,8 +1015,8 @@ jobs:
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
steps:
|
||||
- checkout
|
||||
- run: *run_build
|
||||
- persist_to_workspace: *artifacts_executables
|
||||
- run_build
|
||||
- persist_executables_to_workspace
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
t_ubu_codecov:
|
||||
@ -991,11 +1035,11 @@ jobs:
|
||||
- run:
|
||||
name: "Code Coverage: Syntax Tests"
|
||||
command: codecov --flags syntax --gcov-root build
|
||||
- run: *run_soltest
|
||||
- run_soltest
|
||||
- run:
|
||||
name: "Coverage: All"
|
||||
command: codecov --flags all --gcov-root build
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
# Builds in C++20 mode and uses debug build in order to speed up.
|
||||
@ -1009,16 +1053,16 @@ jobs:
|
||||
MAKEFLAGS: -j 10
|
||||
steps:
|
||||
- checkout
|
||||
- run: *run_build
|
||||
- run_build
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
b_ubu_ossfuzz: &b_ubu_ossfuzz
|
||||
<<: *base_ubuntu_clang
|
||||
steps:
|
||||
- checkout
|
||||
- run: *setup_prerelease_commit_hash
|
||||
- run: *run_build_ossfuzz
|
||||
- persist_to_workspace: *artifacts_executables_ossfuzz
|
||||
- setup_prerelease_commit_hash
|
||||
- run_build_ossfuzz
|
||||
- persist_ossfuzz_executables_to_workspace
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
t_ubu_ossfuzz: &t_ubu_ossfuzz
|
||||
@ -1033,8 +1077,9 @@ jobs:
|
||||
git clone https://github.com/ethereum/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus
|
||||
mkdir -p test_results
|
||||
scripts/regressions.py -o test_results
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- store_test_results:
|
||||
path: test_results/
|
||||
- store_artifacts_test_results
|
||||
|
||||
b_archlinux:
|
||||
<<: *base_archlinux_large
|
||||
@ -1048,9 +1093,9 @@ jobs:
|
||||
command: |
|
||||
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake cvc4 git openssh tar
|
||||
- checkout
|
||||
- run: *run_build
|
||||
- store_artifacts: *artifacts_solc
|
||||
- persist_to_workspace: *artifacts_executables
|
||||
- run_build
|
||||
- store_artifacts_solc
|
||||
- persist_executables_to_workspace
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
b_osx:
|
||||
@ -1060,18 +1105,11 @@ jobs:
|
||||
CMAKE_BUILD_TYPE: Release
|
||||
steps:
|
||||
- checkout
|
||||
- when:
|
||||
condition: true
|
||||
<<: *steps_install_dependencies_osx
|
||||
- run: *run_build
|
||||
- store_artifacts: *artifacts_solc
|
||||
- store_artifacts: *artifact_yul_phaser
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- build/solc/solc
|
||||
- build/test/soltest
|
||||
- build/test/tools/solfuzzer
|
||||
- install_dependencies_osx
|
||||
- run_build
|
||||
- store_artifacts_solc
|
||||
- store_artifacts_yul_phaser
|
||||
- persist_executables_to_workspace_osx
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
t_osx_soltest: &t_osx_soltest
|
||||
@ -1082,14 +1120,13 @@ jobs:
|
||||
OPTIMIZE: 0
|
||||
steps:
|
||||
- checkout
|
||||
- when:
|
||||
condition: true
|
||||
<<: *steps_install_dependencies_osx
|
||||
- install_dependencies_osx
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *run_soltest
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- run_soltest
|
||||
- store_test_results:
|
||||
path: test_results/
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
t_osx_cli:
|
||||
@ -1097,13 +1134,11 @@ jobs:
|
||||
parallelism: 7 # Should match number of tests in .circleci/cli.sh
|
||||
steps:
|
||||
- checkout
|
||||
- when:
|
||||
condition: true
|
||||
<<: *steps_install_dependencies_osx
|
||||
- install_dependencies_osx
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: *run_cmdline_tests
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- run_cmdline_tests
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
b_ems:
|
||||
@ -1134,10 +1169,10 @@ jobs:
|
||||
<<: *base_ubuntu2204_small
|
||||
steps:
|
||||
- checkout
|
||||
- run: *setup_prerelease_commit_hash
|
||||
- setup_prerelease_commit_hash
|
||||
- run:
|
||||
name: Build documentation
|
||||
command: ./docs/docs.sh
|
||||
command: docs/docs.sh
|
||||
- store_artifacts:
|
||||
path: docs/_build/html/
|
||||
destination: docs-html
|
||||
@ -1146,11 +1181,13 @@ jobs:
|
||||
t_ubu_soltest_all: &t_ubu_soltest_all
|
||||
<<: *base_ubuntu2204_large
|
||||
parallelism: 50
|
||||
<<: *steps_soltest_all
|
||||
steps:
|
||||
- soltest_all
|
||||
|
||||
t_ubu_lsp: &t_ubu_lsp
|
||||
<<: *base_ubuntu2204_small
|
||||
<<: *steps_test_lsp
|
||||
steps:
|
||||
- test_lsp
|
||||
|
||||
t_archlinux_soltest: &t_archlinux_soltest
|
||||
<<: *base_archlinux
|
||||
@ -1167,9 +1204,7 @@ jobs:
|
||||
name: Install runtime dependencies
|
||||
command: |
|
||||
pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar
|
||||
- when:
|
||||
condition: true
|
||||
<<: *steps_soltest
|
||||
- soltest
|
||||
|
||||
t_ubu_clang_soltest: &t_ubu_clang_soltest
|
||||
<<: *base_ubuntu2204_clang
|
||||
@ -1181,7 +1216,8 @@ jobs:
|
||||
# The high parallelism in this job is causing the SMT tests to run out of memory,
|
||||
# so disabling for now.
|
||||
SOLTEST_FLAGS: --no-smt
|
||||
<<: *steps_soltest
|
||||
steps:
|
||||
- soltest
|
||||
|
||||
t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all
|
||||
# NOTE: This definition is identical to t_ubu_soltest_all but in the workflow we make it depend on
|
||||
@ -1191,7 +1227,8 @@ jobs:
|
||||
t_ubu_cli: &t_ubu_cli
|
||||
<<: *base_ubuntu2204_small
|
||||
parallelism: 7 # Should match number of tests in .circleci/cli.sh
|
||||
<<: *steps_cmdline_tests
|
||||
steps:
|
||||
- cmdline_tests
|
||||
|
||||
t_ubu_force_release_cli: &t_ubu_force_release_cli
|
||||
<<: *t_ubu_cli
|
||||
@ -1215,7 +1252,8 @@ jobs:
|
||||
# Suppress CLN memory leak.
|
||||
# See: https://github.com/ethereum/solidity/issues/13891 for details.
|
||||
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0
|
||||
<<: *steps_cmdline_tests
|
||||
steps:
|
||||
- cmdline_tests
|
||||
|
||||
t_ubu_asan_soltest:
|
||||
<<: *base_ubuntu2204
|
||||
@ -1229,7 +1267,8 @@ jobs:
|
||||
# Suppress CLN memory leak.
|
||||
# See: https://github.com/ethereum/solidity/issues/13891 for details.
|
||||
LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp
|
||||
<<: *steps_soltest
|
||||
steps:
|
||||
- soltest
|
||||
|
||||
t_ubu_asan_clang_soltest:
|
||||
<<: *base_ubuntu2204_clang
|
||||
@ -1240,7 +1279,8 @@ jobs:
|
||||
OPTIMIZE: 0
|
||||
SOLTEST_FLAGS: --no-smt
|
||||
ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2
|
||||
<<: *steps_soltest
|
||||
steps:
|
||||
- soltest
|
||||
|
||||
t_ubu_ubsan_clang_soltest:
|
||||
<<: *base_ubuntu2204_clang
|
||||
@ -1249,12 +1289,14 @@ jobs:
|
||||
<<: *base_ubuntu2204_clang_env
|
||||
EVM: << pipeline.parameters.evm-version >>
|
||||
SOLTEST_FLAGS: --no-smt
|
||||
<<: *steps_soltest
|
||||
steps:
|
||||
- soltest
|
||||
|
||||
t_ubu_ubsan_clang_cli:
|
||||
<<: *base_ubuntu2204_clang
|
||||
parallelism: 7 # Should match number of tests in .circleci/cli.sh
|
||||
<<: *steps_cmdline_tests
|
||||
steps:
|
||||
- cmdline_tests
|
||||
|
||||
t_ems_solcjs:
|
||||
# Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small).
|
||||
@ -1478,7 +1520,8 @@ jobs:
|
||||
name: "Run solc.exe to make sure build was successful."
|
||||
command: .\build\solc\Release\solc.exe --version
|
||||
shell: powershell.exe
|
||||
- store_artifacts: *artifact_solc_windows
|
||||
- store_artifacts:
|
||||
path: upload/
|
||||
- persist_to_workspace:
|
||||
root: build
|
||||
paths:
|
||||
@ -1507,10 +1550,11 @@ jobs:
|
||||
command: python -m pip install --user deepdiff colorama
|
||||
- run:
|
||||
name: Executing solc LSP test suite
|
||||
command: python ./test/lsp.py .\build\solc\Release\solc.exe --non-interactive
|
||||
command: python test/lsp.py build\solc\Release\solc.exe --non-interactive
|
||||
shell: powershell.exe
|
||||
- store_test_results: *store_test_results
|
||||
- store_artifacts: *artifacts_test_results
|
||||
- store_test_results:
|
||||
path: test_results/
|
||||
- store_artifacts_test_results
|
||||
- matrix_notify_failure_unless_pr
|
||||
|
||||
# Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu
|
||||
|
||||
@ -52,6 +52,8 @@ function validate_checksum {
|
||||
|
||||
if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not restored), rebuild dependencies
|
||||
then
|
||||
brew update
|
||||
brew upgrade
|
||||
brew install boost
|
||||
brew install cmake
|
||||
brew install wget
|
||||
|
||||
@ -4,7 +4,9 @@ Language 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: Run the ``Rematerializer`` and ``UnusedPruner`` steps at the end of the default clean-up sequence.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
||||
@ -4,9 +4,9 @@ FetchContent_Declare(
|
||||
fmtlib
|
||||
PREFIX "${PROJECT_BINARY_DIR}/deps"
|
||||
DOWNLOAD_DIR "${PROJECT_SOURCE_DIR}/deps/downloads"
|
||||
DOWNLOAD_NAME fmt-8.0.1.tar.gz
|
||||
URL https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz
|
||||
URL_HASH SHA256=b06ca3130158c625848f3fb7418f235155a4d389b2abc3a6245fb01cb0eb1e01
|
||||
DOWNLOAD_NAME fmt-9.1.0.tar.gz
|
||||
URL https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
|
||||
URL_HASH SHA256=5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
|
||||
)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS "3.14.0")
|
||||
|
||||
@ -338,7 +338,7 @@ You can override this sequence and supply your own using the ``--yul-optimizatio
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOc'
|
||||
solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOcmu'
|
||||
|
||||
The order of steps is significant and affects the quality of the output.
|
||||
Moreover, applying a step may uncover new optimization opportunities for others that were already applied,
|
||||
|
||||
@ -109,7 +109,7 @@ public:
|
||||
|
||||
/// Resets any knowledge about storage.
|
||||
void resetStorage() { m_storageContent.clear(); }
|
||||
/// Resets any knowledge about storage.
|
||||
/// Resets any knowledge about memory.
|
||||
void resetMemory() { m_memoryContent.clear(); }
|
||||
/// Resets known Keccak-256 hashes
|
||||
void resetKnownKeccak256Hashes() { m_knownKeccak256Hashes.clear(); }
|
||||
|
||||
@ -170,6 +170,8 @@ class Error: virtual public util::Exception
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
Info,
|
||||
Warning,
|
||||
CodeGenerationError,
|
||||
DeclarationError,
|
||||
DocstringParsingError,
|
||||
@ -185,15 +187,14 @@ public:
|
||||
UnimplementedFeatureError,
|
||||
YulException,
|
||||
SMTLogicException,
|
||||
Warning,
|
||||
Info
|
||||
};
|
||||
|
||||
enum class Severity
|
||||
{
|
||||
Error,
|
||||
// NOTE: We rely on these being ordered from least to most severe.
|
||||
Info,
|
||||
Warning,
|
||||
Info
|
||||
Error,
|
||||
};
|
||||
|
||||
Error(
|
||||
@ -206,6 +207,7 @@ public:
|
||||
|
||||
ErrorId errorId() const { return m_errorId; }
|
||||
Type type() const { return m_type; }
|
||||
Severity severity() const { return errorSeverity(m_type); }
|
||||
|
||||
SourceLocation const* sourceLocation() const noexcept;
|
||||
SecondarySourceLocation const* secondarySourceLocation() const noexcept;
|
||||
|
||||
@ -74,56 +74,10 @@ void ParserBase::expectToken(Token _value, bool _advance)
|
||||
{
|
||||
Token tok = m_scanner->currentToken();
|
||||
if (tok != _value)
|
||||
{
|
||||
std::string const expectedToken = ParserBase::tokenName(_value);
|
||||
if (m_parserErrorRecovery)
|
||||
parserError(6635_error, "Expected " + expectedToken + " but got " + tokenName(tok));
|
||||
else
|
||||
fatalParserError(2314_error, "Expected " + expectedToken + " but got " + tokenName(tok));
|
||||
// Do not advance so that recovery can sync or make use of the current token.
|
||||
// This is especially useful if the expected token
|
||||
// is the only one that is missing and is at the end of a construct.
|
||||
// "{ ... ; }" is such an example.
|
||||
// ^
|
||||
_advance = false;
|
||||
}
|
||||
if (_advance)
|
||||
advance();
|
||||
}
|
||||
|
||||
void ParserBase::expectTokenOrConsumeUntil(Token _value, std::string const& _currentNodeName, bool _advance)
|
||||
{
|
||||
solAssert(m_inParserRecovery, "The function is supposed to be called during parser recovery only.");
|
||||
|
||||
Token tok = m_scanner->currentToken();
|
||||
if (tok != _value)
|
||||
{
|
||||
SourceLocation errorLoc = currentLocation();
|
||||
int startPosition = errorLoc.start;
|
||||
while (m_scanner->currentToken() != _value && m_scanner->currentToken() != Token::EOS)
|
||||
advance();
|
||||
|
||||
std::string const expectedToken = ParserBase::tokenName(_value);
|
||||
if (m_scanner->currentToken() == Token::EOS)
|
||||
{
|
||||
// rollback to where the token started, and raise exception to be caught at a higher level.
|
||||
m_scanner->setPosition(static_cast<size_t>(startPosition));
|
||||
std::string const msg = "In " + _currentNodeName + ", " + expectedToken + "is expected; got " + ParserBase::tokenName(tok) + " instead.";
|
||||
fatalParserError(1957_error, errorLoc, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
parserWarning(3796_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
|
||||
m_inParserRecovery = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string expectedToken = ParserBase::tokenName(_value);
|
||||
parserWarning(3347_error, "Recovered in " + _currentNodeName + " at " + expectedToken + ".");
|
||||
m_inParserRecovery = false;
|
||||
}
|
||||
|
||||
fatalParserError(
|
||||
2314_error,
|
||||
"Expected " + ParserBase::tokenName(_value) + " but got " + tokenName(tok)
|
||||
);
|
||||
if (_advance)
|
||||
advance();
|
||||
}
|
||||
|
||||
@ -38,14 +38,9 @@ struct ErrorId;
|
||||
class ParserBase
|
||||
{
|
||||
public:
|
||||
/// Set @a _parserErrorRecovery to true for additional error
|
||||
/// recovery. This is experimental and intended for use
|
||||
/// by front-end tools that need partial AST information even
|
||||
/// when errors occur.
|
||||
explicit ParserBase(ErrorReporter& errorReporter, bool _parserErrorRecovery = false): m_errorReporter(errorReporter)
|
||||
{
|
||||
m_parserErrorRecovery = _parserErrorRecovery;
|
||||
}
|
||||
explicit ParserBase(ErrorReporter& errorReporter):
|
||||
m_errorReporter(errorReporter)
|
||||
{}
|
||||
|
||||
virtual ~ParserBase() = default;
|
||||
|
||||
@ -70,13 +65,9 @@ protected:
|
||||
///@{
|
||||
///@name Helper functions
|
||||
/// If current token value is not @a _value, throw exception otherwise advance token
|
||||
// @a if _advance is true and error recovery is in effect.
|
||||
// if @a _advance is true
|
||||
void expectToken(Token _value, bool _advance = true);
|
||||
|
||||
/// Like expectToken but if there is an error ignores tokens until
|
||||
/// the expected token or EOS is seen. If EOS is encountered, back up to the error point,
|
||||
/// and throw an exception so that a higher grammar rule has an opportunity to recover.
|
||||
void expectTokenOrConsumeUntil(Token _value, std::string const& _currentNodeName, bool _advance = true);
|
||||
Token currentToken() const;
|
||||
Token peekNextToken() const;
|
||||
std::string tokenName(Token _token);
|
||||
@ -108,10 +99,6 @@ protected:
|
||||
ErrorReporter& m_errorReporter;
|
||||
/// Current recursion depth during parsing.
|
||||
size_t m_recursionDepth = 0;
|
||||
/// True if we are in parser error recovery. Usually this means we are scanning for
|
||||
/// a synchronization token like ';', or '}'. We use this to reduce cascaded error messages.
|
||||
bool m_inParserRecovery = false;
|
||||
bool m_parserErrorRecovery = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -1019,15 +1019,28 @@ std::tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
|
||||
while (isIdentifierPart(m_char) || (m_char == '.' && m_kind == ScannerKind::Yul))
|
||||
addLiteralCharAndAdvance();
|
||||
literal.complete();
|
||||
|
||||
auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal);
|
||||
if (m_kind == ScannerKind::Yul)
|
||||
switch (m_kind)
|
||||
{
|
||||
case ScannerKind::Solidity:
|
||||
// Turn experimental Solidity keywords that are not keywords in legacy Solidity into identifiers.
|
||||
if (TokenTraits::isExperimentalSolidityOnlyKeyword(std::get<0>(token)))
|
||||
return std::make_tuple(Token::Identifier, 0, 0);
|
||||
break;
|
||||
case ScannerKind::Yul:
|
||||
// Turn Solidity identifier into a Yul keyword
|
||||
if (m_tokens[NextNext].literal == "leave")
|
||||
return std::make_tuple(Token::Leave, 0, 0);
|
||||
// Turn non-Yul keywords into identifiers.
|
||||
if (!TokenTraits::isYulKeyword(std::get<0>(token)))
|
||||
return std::make_tuple(Token::Identifier, 0, 0);
|
||||
break;
|
||||
case ScannerKind::ExperimentalSolidity:
|
||||
// Turn legacy Solidity keywords that are not keywords in experimental Solidity into identifiers.
|
||||
if (!TokenTraits::isExperimentalSolidityKeyword(std::get<0>(token)))
|
||||
return std::make_tuple(Token::Identifier, 0, 0);
|
||||
break;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
@ -69,7 +69,8 @@ class ParserRecorder;
|
||||
enum class ScannerKind
|
||||
{
|
||||
Solidity,
|
||||
Yul
|
||||
Yul,
|
||||
ExperimentalSolidity
|
||||
};
|
||||
|
||||
enum class ScannerError
|
||||
|
||||
@ -46,9 +46,16 @@ public:
|
||||
bool _colored,
|
||||
bool _withErrorIds
|
||||
):
|
||||
m_stream(_stream), m_charStreamProvider(_charStreamProvider), m_colored(_colored), m_withErrorIds(_withErrorIds)
|
||||
m_stream(_stream),
|
||||
m_charStreamProvider(_charStreamProvider),
|
||||
m_colored(_colored),
|
||||
m_withErrorIds(_withErrorIds)
|
||||
{}
|
||||
|
||||
// WARNING: Use the xyzErrorInformation() variants over xyzExceptionInformation() when you
|
||||
// do have access to an Error instance. Error is implicitly convertible to util::Exception
|
||||
// but the conversion loses the error ID.
|
||||
|
||||
/// Prints source location if it is given.
|
||||
void printSourceLocation(SourceReference const& _ref);
|
||||
void printExceptionInformation(SourceReferenceExtractor::Message const& _msg);
|
||||
@ -61,12 +68,11 @@ public:
|
||||
util::Exception const& _exception,
|
||||
Error::Type _type,
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
bool _colored = false,
|
||||
bool _withErrorIds = false
|
||||
bool _colored = false
|
||||
)
|
||||
{
|
||||
std::ostringstream errorOutput;
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, false /* _withErrorIds */);
|
||||
formatter.printExceptionInformation(_exception, _type);
|
||||
return errorOutput.str();
|
||||
}
|
||||
@ -75,26 +81,39 @@ public:
|
||||
util::Exception const& _exception,
|
||||
Error::Severity _severity,
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
bool _colored = false,
|
||||
bool _withErrorIds = false
|
||||
bool _colored = false
|
||||
)
|
||||
{
|
||||
std::ostringstream errorOutput;
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, false /* _withErrorIds */);
|
||||
formatter.printExceptionInformation(_exception, _severity);
|
||||
return errorOutput.str();
|
||||
}
|
||||
|
||||
static std::string formatErrorInformation(
|
||||
Error const& _error,
|
||||
CharStreamProvider const& _charStreamProvider
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
bool _colored = false,
|
||||
bool _withErrorIds = false
|
||||
)
|
||||
{
|
||||
return formatExceptionInformation(
|
||||
_error,
|
||||
Error::errorSeverity(_error.type()),
|
||||
_charStreamProvider
|
||||
);
|
||||
std::ostringstream errorOutput;
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
|
||||
formatter.printErrorInformation(_error);
|
||||
return errorOutput.str();
|
||||
}
|
||||
|
||||
static std::string formatErrorInformation(
|
||||
langutil::ErrorList const& _errors,
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
bool _colored = false,
|
||||
bool _withErrorIds = false
|
||||
)
|
||||
{
|
||||
std::ostringstream errorOutput;
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
|
||||
formatter.printErrorInformation(_errors);
|
||||
return errorOutput.str();
|
||||
}
|
||||
|
||||
static std::string formatErrorInformation(Error const& _error, CharStream const& _charStream);
|
||||
|
||||
@ -268,6 +268,8 @@ namespace solidity::langutil
|
||||
/* Yul-specific tokens, but not keywords. */ \
|
||||
T(Leave, "leave", 0) \
|
||||
\
|
||||
T(NonExperimentalEnd, nullptr, 0) /* used as non-experimental enum end marker */ \
|
||||
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
|
||||
/* Illegal token - not able to scan. */ \
|
||||
T(Illegal, "ILLEGAL", 0) \
|
||||
\
|
||||
@ -323,6 +325,39 @@ namespace TokenTraits
|
||||
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex;
|
||||
}
|
||||
|
||||
constexpr bool isExperimentalSolidityKeyword(Token token)
|
||||
{
|
||||
return
|
||||
token == Token::Assembly ||
|
||||
token == Token::Contract ||
|
||||
token == Token::External ||
|
||||
token == Token::Fallback ||
|
||||
token == Token::Pragma ||
|
||||
token == Token::Import ||
|
||||
token == Token::As ||
|
||||
token == Token::Function ||
|
||||
token == Token::Let ||
|
||||
token == Token::Return ||
|
||||
token == Token::Type ||
|
||||
token == Token::If ||
|
||||
token == Token::Else ||
|
||||
token == Token::Do ||
|
||||
token == Token::While ||
|
||||
token == Token::For ||
|
||||
token == Token::Continue ||
|
||||
token == Token::Break;
|
||||
// TODO: see isExperimentalSolidityKeyword below
|
||||
// || (token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd);
|
||||
}
|
||||
|
||||
constexpr bool isExperimentalSolidityOnlyKeyword(Token)
|
||||
{
|
||||
// TODO: use token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd
|
||||
// as soon as other experimental tokens are added. For now the comparison generates
|
||||
// a warning from clang because it is always false.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isYulKeyword(std::string const& _literal);
|
||||
|
||||
Token AssignmentToBinaryOp(Token op);
|
||||
|
||||
@ -101,6 +101,8 @@ set(sources
|
||||
codegen/ir/IRLValue.h
|
||||
codegen/ir/IRVariable.cpp
|
||||
codegen/ir/IRVariable.h
|
||||
experimental/analysis/Analysis.cpp
|
||||
experimental/analysis/Analysis.h
|
||||
formal/ArraySlicePredicate.cpp
|
||||
formal/ArraySlicePredicate.h
|
||||
formal/BMC.cpp
|
||||
@ -186,4 +188,3 @@ set(sources
|
||||
|
||||
add_library(solidity ${sources})
|
||||
target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only Threads::Threads)
|
||||
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
@ -47,9 +46,9 @@ bool fitsPrecisionExp(bigint const& _base, bigint const& _exp)
|
||||
|
||||
solAssert(_base > 0, "");
|
||||
|
||||
size_t const bitsMax = 4096;
|
||||
std::size_t const bitsMax = 4096;
|
||||
|
||||
size_t mostSignificantBaseBit = static_cast<size_t>(boost::multiprecision::msb(_base));
|
||||
std::size_t mostSignificantBaseBit = static_cast<std::size_t>(boost::multiprecision::msb(_base));
|
||||
if (mostSignificantBaseBit == 0) // _base == 1
|
||||
return true;
|
||||
if (mostSignificantBaseBit > bitsMax) // _base >= 2 ^ 4096
|
||||
@ -68,7 +67,7 @@ bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2)
|
||||
|
||||
}
|
||||
|
||||
optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right)
|
||||
std::optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, rational const& _left, rational const& _right)
|
||||
{
|
||||
bool fractional = _left.denominator() != 1 || _right.denominator() != 1;
|
||||
switch (_operator)
|
||||
@ -76,17 +75,17 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
//bit operations will only be enabled for integers and fixed types that resemble integers
|
||||
case Token::BitOr:
|
||||
if (fractional)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else
|
||||
return _left.numerator() | _right.numerator();
|
||||
case Token::BitXor:
|
||||
if (fractional)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else
|
||||
return _left.numerator() ^ _right.numerator();
|
||||
case Token::BitAnd:
|
||||
if (fractional)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else
|
||||
return _left.numerator() & _right.numerator();
|
||||
case Token::Add: return _left + _right;
|
||||
@ -94,12 +93,12 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
case Token::Mul: return _left * _right;
|
||||
case Token::Div:
|
||||
if (_right == rational(0))
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else
|
||||
return _left / _right;
|
||||
case Token::Mod:
|
||||
if (_right == rational(0))
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else if (fractional)
|
||||
{
|
||||
rational tempValue = _left / _right;
|
||||
@ -111,7 +110,7 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
case Token::Exp:
|
||||
{
|
||||
if (_right.denominator() != 1)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
bigint const& exp = _right.numerator();
|
||||
|
||||
// x ** 0 = 1
|
||||
@ -127,13 +126,13 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
}
|
||||
else
|
||||
{
|
||||
if (abs(exp) > numeric_limits<uint32_t>::max())
|
||||
return nullopt; // This will need too much memory to represent.
|
||||
if (abs(exp) > std::numeric_limits<uint32_t>::max())
|
||||
return std::nullopt; // This will need too much memory to represent.
|
||||
|
||||
uint32_t absExp = bigint(abs(exp)).convert_to<uint32_t>();
|
||||
|
||||
if (!fitsPrecisionExp(abs(_left.numerator()), absExp) || !fitsPrecisionExp(abs(_left.denominator()), absExp))
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
|
||||
static auto const optimizedPow = [](bigint const& _base, uint32_t _exponent) -> bigint {
|
||||
if (_base == 1)
|
||||
@ -158,18 +157,18 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
case Token::SHL:
|
||||
{
|
||||
if (fractional)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else if (_right < 0)
|
||||
return nullopt;
|
||||
else if (_right > numeric_limits<uint32_t>::max())
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else if (_right > std::numeric_limits<uint32_t>::max())
|
||||
return std::nullopt;
|
||||
if (_left.numerator() == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
uint32_t exponent = _right.numerator().convert_to<uint32_t>();
|
||||
if (!fitsPrecisionBase2(abs(_left.numerator()), exponent))
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
return _left.numerator() * boost::multiprecision::pow(bigint(2), exponent);
|
||||
}
|
||||
break;
|
||||
@ -179,11 +178,11 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
case Token::SAR:
|
||||
{
|
||||
if (fractional)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else if (_right < 0)
|
||||
return nullopt;
|
||||
else if (_right > numeric_limits<uint32_t>::max())
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else if (_right > std::numeric_limits<uint32_t>::max())
|
||||
return std::nullopt;
|
||||
if (_left.numerator() == 0)
|
||||
return 0;
|
||||
else
|
||||
@ -209,60 +208,60 @@ optional<rational> ConstantEvaluator::evaluateBinaryOperator(Token _operator, ra
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
optional<rational> ConstantEvaluator::evaluateUnaryOperator(Token _operator, rational const& _input)
|
||||
std::optional<rational> ConstantEvaluator::evaluateUnaryOperator(Token _operator, rational const& _input)
|
||||
{
|
||||
switch (_operator)
|
||||
{
|
||||
case Token::BitNot:
|
||||
if (_input.denominator() != 1)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else
|
||||
return ~_input.numerator();
|
||||
case Token::Sub:
|
||||
return -_input;
|
||||
default:
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
optional<TypedRational> convertType(rational const& _value, Type const& _type)
|
||||
std::optional<TypedRational> convertType(rational const& _value, Type const& _type)
|
||||
{
|
||||
if (_type.category() == Type::Category::RationalNumber)
|
||||
return TypedRational{TypeProvider::rationalNumber(_value), _value};
|
||||
else if (auto const* integerType = dynamic_cast<IntegerType const*>(&_type))
|
||||
{
|
||||
if (_value > integerType->maxValue() || _value < integerType->minValue())
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
else
|
||||
return TypedRational{&_type, _value.numerator() / _value.denominator()};
|
||||
}
|
||||
else
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
optional<TypedRational> convertType(optional<TypedRational> const& _value, Type const& _type)
|
||||
std::optional<TypedRational> convertType(std::optional<TypedRational> const& _value, Type const& _type)
|
||||
{
|
||||
return _value ? convertType(_value->value, _type) : nullopt;
|
||||
return _value ? convertType(_value->value, _type) : std::nullopt;
|
||||
}
|
||||
|
||||
optional<TypedRational> constantToTypedValue(Type const& _type)
|
||||
std::optional<TypedRational> constantToTypedValue(Type const& _type)
|
||||
{
|
||||
if (_type.category() == Type::Category::RationalNumber)
|
||||
return TypedRational{&_type, dynamic_cast<RationalNumberType const&>(_type).value()};
|
||||
else
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
optional<TypedRational> ConstantEvaluator::evaluate(
|
||||
std::optional<TypedRational> ConstantEvaluator::evaluate(
|
||||
langutil::ErrorReporter& _errorReporter,
|
||||
Expression const& _expr
|
||||
)
|
||||
@ -271,7 +270,7 @@ optional<TypedRational> ConstantEvaluator::evaluate(
|
||||
}
|
||||
|
||||
|
||||
optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
|
||||
std::optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
|
||||
{
|
||||
if (!m_values.count(&_node))
|
||||
{
|
||||
@ -280,7 +279,7 @@ optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
|
||||
solAssert(varDecl->isConstant(), "");
|
||||
// In some circumstances, we do not yet have a type for the variable.
|
||||
if (!varDecl->value() || !varDecl->type())
|
||||
m_values[&_node] = nullopt;
|
||||
m_values[&_node] = std::nullopt;
|
||||
else
|
||||
{
|
||||
m_depth++;
|
||||
@ -298,7 +297,7 @@ optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
|
||||
{
|
||||
expression->accept(*this);
|
||||
if (!m_values.count(&_node))
|
||||
m_values[&_node] = nullopt;
|
||||
m_values[&_node] = std::nullopt;
|
||||
}
|
||||
}
|
||||
return m_values.at(&_node);
|
||||
@ -306,7 +305,7 @@ optional<TypedRational> ConstantEvaluator::evaluate(ASTNode const& _node)
|
||||
|
||||
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
||||
{
|
||||
optional<TypedRational> value = evaluate(_operation.subExpression());
|
||||
std::optional<TypedRational> value = evaluate(_operation.subExpression());
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
@ -317,9 +316,9 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
||||
if (!value)
|
||||
return;
|
||||
|
||||
if (optional<rational> result = evaluateUnaryOperator(_operation.getOperator(), value->value))
|
||||
if (std::optional<rational> result = evaluateUnaryOperator(_operation.getOperator(), value->value))
|
||||
{
|
||||
optional<TypedRational> convertedValue = convertType(*result, *resultType);
|
||||
std::optional<TypedRational> convertedValue = convertType(*result, *resultType);
|
||||
if (!convertedValue)
|
||||
m_errorReporter.fatalTypeError(
|
||||
3667_error,
|
||||
@ -332,8 +331,8 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
||||
|
||||
void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
|
||||
{
|
||||
optional<TypedRational> left = evaluate(_operation.leftExpression());
|
||||
optional<TypedRational> right = evaluate(_operation.rightExpression());
|
||||
std::optional<TypedRational> left = evaluate(_operation.leftExpression());
|
||||
std::optional<TypedRational> right = evaluate(_operation.rightExpression());
|
||||
if (!left || !right)
|
||||
return;
|
||||
|
||||
@ -349,7 +348,7 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
|
||||
6020_error,
|
||||
_operation.location(),
|
||||
"Operator " +
|
||||
string(TokenTraits::toString(_operation.getOperator())) +
|
||||
std::string(TokenTraits::toString(_operation.getOperator())) +
|
||||
" not compatible with types " +
|
||||
left->type->toString() +
|
||||
" and " +
|
||||
@ -363,9 +362,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
|
||||
if (!left || !right)
|
||||
return;
|
||||
|
||||
if (optional<rational> value = evaluateBinaryOperator(_operation.getOperator(), left->value, right->value))
|
||||
if (std::optional<rational> value = evaluateBinaryOperator(_operation.getOperator(), left->value, right->value))
|
||||
{
|
||||
optional<TypedRational> convertedValue = convertType(*value, *resultType);
|
||||
std::optional<TypedRational> convertedValue = convertType(*value, *resultType);
|
||||
if (!convertedValue)
|
||||
m_errorReporter.fatalTypeError(
|
||||
2643_error,
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
|
||||
#include <range/v3/view/reverse.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -49,10 +48,10 @@ bool hasEqualExternalCallableParameters(T const& _a, B const& _b)
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
map<ASTString, vector<T const*>> filterDeclarations(
|
||||
map<ASTString, vector<Declaration const*>> const& _declarations)
|
||||
std::map<ASTString, std::vector<T const*>> filterDeclarations(
|
||||
std::map<ASTString, std::vector<Declaration const*>> const& _declarations)
|
||||
{
|
||||
map<ASTString, vector<T const*>> filteredDeclarations;
|
||||
std::map<ASTString, std::vector<T const*>> filteredDeclarations;
|
||||
for (auto const& [name, overloads]: _declarations)
|
||||
for (auto const* declaration: overloads)
|
||||
if (auto typedDeclaration = dynamic_cast<T const*>(declaration))
|
||||
@ -106,7 +105,7 @@ void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _co
|
||||
{
|
||||
/// Checks that two functions with the same name defined in this contract have different
|
||||
/// argument types and that there is at most one constructor.
|
||||
map<string, vector<FunctionDefinition const*>> functions;
|
||||
std::map<std::string, std::vector<FunctionDefinition const*>> functions;
|
||||
FunctionDefinition const* constructor = nullptr;
|
||||
FunctionDefinition const* fallback = nullptr;
|
||||
FunctionDefinition const* receive = nullptr;
|
||||
@ -157,7 +156,7 @@ void ContractLevelChecker::checkDuplicateEvents(ContractDefinition const& _contr
|
||||
{
|
||||
/// Checks that two events with the same name defined in this contract have different
|
||||
/// argument types
|
||||
map<string, vector<EventDefinition const*>> events;
|
||||
std::map<std::string, std::vector<EventDefinition const*>> events;
|
||||
for (auto const* contract: _contract.annotation().linearizedBaseContracts)
|
||||
for (EventDefinition const* event: contract->events())
|
||||
events[event->name()].push_back(event);
|
||||
@ -195,12 +194,12 @@ void ContractLevelChecker::checkReceiveFunction(ContractDefinition const& _contr
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions)
|
||||
void ContractLevelChecker::findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions)
|
||||
{
|
||||
for (auto const& it: _definitions)
|
||||
{
|
||||
vector<T> const& overloads = it.second;
|
||||
set<size_t> reported;
|
||||
std::vector<T> const& overloads = it.second;
|
||||
std::set<size_t> reported;
|
||||
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
|
||||
{
|
||||
SecondarySourceLocation ssl;
|
||||
@ -228,15 +227,15 @@ void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const
|
||||
if (ssl.infos.size() > 0)
|
||||
{
|
||||
ErrorId error;
|
||||
string message;
|
||||
if constexpr (is_same_v<T, FunctionDefinition const*>)
|
||||
std::string message;
|
||||
if constexpr (std::is_same_v<T, FunctionDefinition const*>)
|
||||
{
|
||||
error = 1686_error;
|
||||
message = "Function with same name and parameter types defined twice.";
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(is_same_v<T, EventDefinition const*>, "Expected \"FunctionDefinition const*\" or \"EventDefinition const*\"");
|
||||
static_assert(std::is_same_v<T, EventDefinition const*>, "Expected \"FunctionDefinition const*\" or \"EventDefinition const*\"");
|
||||
error = 5883_error;
|
||||
message = "Event with same name and parameter types defined twice.";
|
||||
}
|
||||
@ -258,7 +257,7 @@ void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _c
|
||||
{
|
||||
// Collects functions, static variable getters and modifiers. If they
|
||||
// override (unimplemented) base class ones, they are replaced.
|
||||
set<OverrideProxy, OverrideProxy::CompareBySignature> proxies;
|
||||
std::set<OverrideProxy, OverrideProxy::CompareBySignature> proxies;
|
||||
|
||||
auto registerProxy = [&proxies](OverrideProxy const& _overrideProxy)
|
||||
{
|
||||
@ -323,7 +322,7 @@ void ContractLevelChecker::checkAbstractDefinitions(ContractDefinition const& _c
|
||||
|
||||
void ContractLevelChecker::checkBaseConstructorArguments(ContractDefinition const& _contract)
|
||||
{
|
||||
vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
|
||||
std::vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
|
||||
|
||||
// Determine the arguments that are used for the base constructors.
|
||||
for (ContractDefinition const* contract: bases)
|
||||
@ -430,7 +429,7 @@ void ContractLevelChecker::annotateBaseConstructorArguments(
|
||||
|
||||
void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _contract)
|
||||
{
|
||||
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
|
||||
std::map<std::string, std::vector<std::pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
|
||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||
{
|
||||
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||
@ -467,7 +466,7 @@ void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _c
|
||||
|
||||
void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contract)
|
||||
{
|
||||
set<util::FixedHash<4>> hashes;
|
||||
std::set<util::FixedHash<4>> hashes;
|
||||
for (auto const& it: _contract.interfaceFunctionList())
|
||||
{
|
||||
util::FixedHash<4> const& hash = it.first;
|
||||
@ -475,7 +474,7 @@ void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contra
|
||||
m_errorReporter.fatalTypeError(
|
||||
1860_error,
|
||||
_contract.location(),
|
||||
string("Function signature hash collision for ") + it.second->externalSignature()
|
||||
std::string("Function signature hash collision for ") + it.second->externalSignature()
|
||||
);
|
||||
hashes.insert(hash);
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::placeholders;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -44,7 +43,7 @@ void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractD
|
||||
if (!_function.isImplemented())
|
||||
return;
|
||||
|
||||
optional<string> mostDerivedContractName;
|
||||
std::optional<std::string> mostDerivedContractName;
|
||||
|
||||
// The name of the most derived contract only required if it differs from
|
||||
// the functions contract
|
||||
@ -61,13 +60,13 @@ void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractD
|
||||
}
|
||||
|
||||
|
||||
void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNode const* _exit, bool _emptyBody, optional<string> _contractName)
|
||||
void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNode const* _exit, bool _emptyBody, std::optional<std::string> _contractName)
|
||||
{
|
||||
struct NodeInfo
|
||||
{
|
||||
set<VariableDeclaration const*> unassignedVariablesAtEntry;
|
||||
set<VariableDeclaration const*> unassignedVariablesAtExit;
|
||||
set<VariableOccurrence const*> uninitializedVariableAccesses;
|
||||
std::set<VariableDeclaration const*> unassignedVariablesAtEntry;
|
||||
std::set<VariableDeclaration const*> unassignedVariablesAtExit;
|
||||
std::set<VariableOccurrence const*> uninitializedVariableAccesses;
|
||||
/// Propagate the information from another node to this node.
|
||||
/// To be used to propagate information from a node to its exit nodes.
|
||||
/// Returns true, if new variables were added and thus the current node has
|
||||
@ -84,8 +83,8 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
|
||||
;
|
||||
}
|
||||
};
|
||||
map<CFGNode const*, NodeInfo> nodeInfos;
|
||||
set<CFGNode const*> nodesToTraverse;
|
||||
std::map<CFGNode const*, NodeInfo> nodeInfos;
|
||||
std::set<CFGNode const*> nodesToTraverse;
|
||||
nodesToTraverse.insert(_entry);
|
||||
|
||||
// Walk all paths starting from the nodes in ``nodesToTraverse`` until ``NodeInfo::propagateFrom``
|
||||
@ -138,7 +137,7 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
|
||||
auto const& exitInfo = nodeInfos[_exit];
|
||||
if (!exitInfo.uninitializedVariableAccesses.empty())
|
||||
{
|
||||
vector<VariableOccurrence const*> uninitializedAccessesOrdered(
|
||||
std::vector<VariableOccurrence const*> uninitializedAccessesOrdered(
|
||||
exitInfo.uninitializedVariableAccesses.begin(),
|
||||
exitInfo.uninitializedVariableAccesses.end()
|
||||
);
|
||||
@ -168,7 +167,7 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
|
||||
varDecl.location(),
|
||||
ssl,
|
||||
"This variable is of " +
|
||||
string(isStorage ? "storage" : "calldata") +
|
||||
std::string(isStorage ? "storage" : "calldata") +
|
||||
" pointer type and can be " +
|
||||
(variableOccurrence->kind() == VariableOccurrence::Kind::Return ? "returned" : "accessed") +
|
||||
" without prior assignment, which would lead to undefined behaviour."
|
||||
|
||||
@ -21,10 +21,8 @@
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
using namespace std;
|
||||
|
||||
ControlFlowBuilder::ControlFlowBuilder(CFG::NodeContainer& _nodeContainer, FunctionFlow const& _functionFlow, ContractDefinition const* _contract):
|
||||
m_nodeContainer(_nodeContainer),
|
||||
@ -37,13 +35,13 @@ ControlFlowBuilder::ControlFlowBuilder(CFG::NodeContainer& _nodeContainer, Funct
|
||||
}
|
||||
|
||||
|
||||
unique_ptr<FunctionFlow> ControlFlowBuilder::createFunctionFlow(
|
||||
std::unique_ptr<FunctionFlow> ControlFlowBuilder::createFunctionFlow(
|
||||
CFG::NodeContainer& _nodeContainer,
|
||||
FunctionDefinition const& _function,
|
||||
ContractDefinition const* _contract
|
||||
)
|
||||
{
|
||||
auto functionFlow = make_unique<FunctionFlow>();
|
||||
auto functionFlow = std::make_unique<FunctionFlow>();
|
||||
functionFlow->entry = _nodeContainer.newNode();
|
||||
functionFlow->exit = _nodeContainer.newNode();
|
||||
functionFlow->revert = _nodeContainer.newNode();
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
#include <libsolidity/analysis/ControlFlowBuilder.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
#include <range/v3/view/filter.hpp>
|
||||
#include <range/v3/range/conversion.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
@ -41,7 +40,7 @@ Declaration const* DeclarationContainer::conflictingDeclaration(
|
||||
if (!_name)
|
||||
_name = &_declaration.name();
|
||||
solAssert(!_name->empty(), "");
|
||||
vector<Declaration const*> declarations;
|
||||
std::vector<Declaration const*> declarations;
|
||||
if (m_declarations.count(*_name))
|
||||
declarations += m_declarations.at(*_name);
|
||||
if (m_invisibleDeclarations.count(*_name))
|
||||
@ -127,7 +126,7 @@ bool DeclarationContainer::registerDeclaration(
|
||||
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))
|
||||
decls.push_back(&_declaration);
|
||||
return true;
|
||||
@ -142,13 +141,13 @@ bool DeclarationContainer::registerDeclaration(
|
||||
return registerDeclaration(_declaration, nullptr, nullptr, _invisible, _update);
|
||||
}
|
||||
|
||||
vector<Declaration const*> DeclarationContainer::resolveName(
|
||||
std::vector<Declaration const*> DeclarationContainer::resolveName(
|
||||
ASTString const& _name,
|
||||
ResolvingSettings _settings
|
||||
) const
|
||||
{
|
||||
solAssert(!_name.empty(), "Attempt to resolve empty name.");
|
||||
vector<Declaration const*> result;
|
||||
std::vector<Declaration const*> result;
|
||||
|
||||
if (m_declarations.count(_name))
|
||||
{
|
||||
@ -172,24 +171,24 @@ vector<Declaration const*> DeclarationContainer::resolveName(
|
||||
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 ;)
|
||||
// since 80 is the suggested line length limit, we use 80^2 as length threshold
|
||||
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;
|
||||
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))
|
||||
similar.push_back(declarationName);
|
||||
}
|
||||
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))
|
||||
similar.push_back(declarationName);
|
||||
}
|
||||
@ -200,7 +199,7 @@ vector<ASTString> DeclarationContainer::similarNames(ASTString const& _name) con
|
||||
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)
|
||||
innerContainer->populateHomonyms(_it);
|
||||
@ -210,7 +209,7 @@ void DeclarationContainer::populateHomonyms(back_insert_iterator<Homonyms> _it)
|
||||
ResolvingSettings settings;
|
||||
settings.recursive = 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())
|
||||
_it = make_pair(location, declarations);
|
||||
}
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
|
||||
#include <range/v3/view/transform.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
@ -336,10 +335,10 @@ void DeclarationTypeChecker::endVisit(ArrayTypeName const& _typeName)
|
||||
|
||||
if (Expression const* length = _typeName.length())
|
||||
{
|
||||
optional<rational> lengthValue;
|
||||
std::optional<rational> lengthValue;
|
||||
if (length->annotation().type && length->annotation().type->category() == Type::Category::RationalNumber)
|
||||
lengthValue = dynamic_cast<RationalNumberType const&>(*length->annotation().type).value();
|
||||
else if (optional<ConstantEvaluator::TypedRational> value = ConstantEvaluator::evaluate(m_errorReporter, *length))
|
||||
else if (std::optional<ConstantEvaluator::TypedRational> value = ConstantEvaluator::evaluate(m_errorReporter, *length))
|
||||
lengthValue = value->value;
|
||||
|
||||
if (!lengthValue)
|
||||
@ -399,10 +398,10 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
Location varLoc = _variable.referenceLocation();
|
||||
DataLocation typeLoc = DataLocation::Memory;
|
||||
|
||||
set<Location> allowedDataLocations = _variable.allowedDataLocations();
|
||||
std::set<Location> allowedDataLocations = _variable.allowedDataLocations();
|
||||
if (!allowedDataLocations.count(varLoc))
|
||||
{
|
||||
auto locationToString = [](VariableDeclaration::Location _location) -> string
|
||||
auto locationToString = [](VariableDeclaration::Location _location) -> std::string
|
||||
{
|
||||
switch (_location)
|
||||
{
|
||||
@ -414,7 +413,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
return {};
|
||||
};
|
||||
|
||||
string errorString;
|
||||
std::string errorString;
|
||||
if (!_variable.hasReferenceOrMappingType())
|
||||
errorString = "Data location can only be specified for array, struct or mapping types";
|
||||
else
|
||||
@ -430,9 +429,9 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
else if (_variable.isCallableOrCatchParameter())
|
||||
errorString +=
|
||||
" for " +
|
||||
string(_variable.isReturnParameter() ? "return " : "") +
|
||||
std::string(_variable.isReturnParameter() ? "return " : "") +
|
||||
"parameter in" +
|
||||
string(_variable.isExternalCallableParameter() ? " external" : "") +
|
||||
std::string(_variable.isExternalCallableParameter() ? " external" : "") +
|
||||
" function";
|
||||
else
|
||||
errorString += " for variable";
|
||||
|
||||
@ -30,7 +30,6 @@
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -38,7 +37,7 @@ using namespace solidity::frontend;
|
||||
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.
|
||||
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();)
|
||||
{
|
||||
string const& tag = it->first;
|
||||
std::string const& tag = it->first;
|
||||
// Don't copy tag "inheritdoc", custom tags or already existing tags
|
||||
if (tag == "inheritdoc" || _target.docTags.count(tag) || boost::starts_with(tag, "custom"))
|
||||
{
|
||||
@ -68,7 +67,7 @@ void copyMissingTags(set<CallableDeclaration const*> const& _baseFunctions, Stru
|
||||
if (_functionType && tag == "return")
|
||||
{
|
||||
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 (
|
||||
_functionType->returnParameterNames().size() > n &&
|
||||
@ -80,10 +79,10 @@ void copyMissingTags(set<CallableDeclaration const*> const& _baseFunctions, Stru
|
||||
baseFunction.returnParameters().size() > n &&
|
||||
baseFunction.returnParameters().at(n)->name().empty();
|
||||
|
||||
string paramName = _functionType->returnParameterNames().at(n);
|
||||
std::string paramName = _functionType->returnParameterNames().at(n);
|
||||
content.content =
|
||||
(paramName.empty() ? "" : std::move(paramName) + " ") + (
|
||||
string::npos == docParaNameEndPos || baseHasNoName ?
|
||||
std::string::npos == docParaNameEndPos || baseHasNoName ?
|
||||
content.content :
|
||||
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)
|
||||
if (baseFuncCandidate->annotation().contract->id() == _contractId)
|
||||
@ -181,7 +180,7 @@ void DocStringAnalyser::handleCallable(
|
||||
}
|
||||
|
||||
CallableDeclaration const* DocStringAnalyser::resolveInheritDoc(
|
||||
set<CallableDeclaration const*> const& _baseFuncs,
|
||||
std::set<CallableDeclaration const*> const& _baseFuncs,
|
||||
StructurallyDocumented const& _node,
|
||||
StructurallyDocumentedAnnotation& _annotation
|
||||
)
|
||||
|
||||
@ -37,7 +37,6 @@
|
||||
#include <regex>
|
||||
#include <string_view>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -67,7 +66,7 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
|
||||
if (tagName == "return")
|
||||
{
|
||||
returnTagsVisited++;
|
||||
vector<string> returnParameterNames;
|
||||
std::vector<std::string> returnParameterNames;
|
||||
|
||||
if (auto const* varDecl = dynamic_cast<VariableDeclaration const*>(&_node))
|
||||
{
|
||||
@ -82,8 +81,8 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
|
||||
else
|
||||
continue;
|
||||
|
||||
string content = tagValue.content;
|
||||
string firstWord = content.substr(0, content.find_first_of(" \t"));
|
||||
std::string content = tagValue.content;
|
||||
std::string firstWord = content.substr(0, content.find_first_of(" \t"));
|
||||
|
||||
if (returnTagsVisited > returnParameterNames.size())
|
||||
m_errorReporter.docstringParsingError(
|
||||
@ -94,7 +93,7 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
|
||||
);
|
||||
else
|
||||
{
|
||||
string const& parameter = returnParameterNames.at(returnTagsVisited - 1);
|
||||
std::string const& parameter = returnParameterNames.at(returnTagsVisited - 1);
|
||||
if (!parameter.empty() && parameter != firstWord)
|
||||
m_errorReporter.docstringParsingError(
|
||||
5856_error,
|
||||
@ -113,7 +112,7 @@ bool DocStringTagParser::validateDocStringsUsingTypes(SourceUnit const& _sourceU
|
||||
|
||||
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");
|
||||
|
||||
return true;
|
||||
@ -193,12 +192,12 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly)
|
||||
{
|
||||
if (tagName == "solidity")
|
||||
{
|
||||
vector<string> values;
|
||||
std::vector<std::string> values;
|
||||
boost::split(values, tagValue.content, isWhiteSpace);
|
||||
|
||||
set<string> valuesSeen;
|
||||
set<string> duplicates;
|
||||
for (auto const& value: values | ranges::views::filter(not_fn(&string::empty)))
|
||||
std::set<std::string> valuesSeen;
|
||||
std::set<std::string> duplicates;
|
||||
for (auto const& value: values | ranges::views::filter(not_fn(&std::string::empty)))
|
||||
if (valuesSeen.insert(value).second)
|
||||
{
|
||||
if (value == "memory-safe-assembly")
|
||||
@ -244,7 +243,7 @@ void DocStringTagParser::checkParameters(
|
||||
StructurallyDocumentedAnnotation& _annotation
|
||||
)
|
||||
{
|
||||
set<string> validParams;
|
||||
std::set<std::string> validParams;
|
||||
for (auto const& p: _callable.parameters())
|
||||
validParams.insert(p->name());
|
||||
if (_callable.returnParameterList())
|
||||
@ -268,7 +267,7 @@ void DocStringTagParser::handleConstructor(
|
||||
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");
|
||||
checkParameters(_callable, _node, _annotation);
|
||||
}
|
||||
@ -279,10 +278,10 @@ void DocStringTagParser::handleCallable(
|
||||
StructurallyDocumentedAnnotation& _annotation
|
||||
)
|
||||
{
|
||||
static set<string> const validEventTags = set<string>{"dev", "notice", "return", "param"};
|
||||
static set<string> const validErrorTags = set<string>{"dev", "notice", "param"};
|
||||
static set<string> const validModifierTags = set<string>{"dev", "notice", "param", "inheritdoc"};
|
||||
static set<string> const validTags = set<string>{"dev", "notice", "return", "param", "inheritdoc"};
|
||||
static std::set<std::string> const validEventTags = std::set<std::string>{"dev", "notice", "return", "param"};
|
||||
static std::set<std::string> const validErrorTags = std::set<std::string>{"dev", "notice", "param"};
|
||||
static std::set<std::string> const validModifierTags = std::set<std::string>{"dev", "notice", "param", "inheritdoc"};
|
||||
static std::set<std::string> const validTags = std::set<std::string>{"dev", "notice", "return", "param", "inheritdoc"};
|
||||
|
||||
if (dynamic_cast<EventDefinition const*>(&_callable))
|
||||
parseDocStrings(_node, _annotation, validEventTags, "events");
|
||||
@ -299,8 +298,8 @@ void DocStringTagParser::handleCallable(
|
||||
void DocStringTagParser::parseDocStrings(
|
||||
StructurallyDocumented const& _node,
|
||||
StructurallyDocumentedAnnotation& _annotation,
|
||||
set<string> const& _validTags,
|
||||
string const& _nodeName
|
||||
std::set<std::string> const& _validTags,
|
||||
std::string const& _nodeName
|
||||
)
|
||||
{
|
||||
if (!_node.documentation())
|
||||
@ -310,7 +309,7 @@ void DocStringTagParser::parseDocStrings(
|
||||
|
||||
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:")
|
||||
m_errorReporter.docstringParsingError(
|
||||
6564_error,
|
||||
@ -319,7 +318,7 @@ void DocStringTagParser::parseDocStrings(
|
||||
);
|
||||
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))
|
||||
m_errorReporter.docstringParsingError(
|
||||
2968_error,
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
#include <range/v3/view/reverse.hpp>
|
||||
#include <range/v3/view/transform.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::util;
|
||||
|
||||
@ -72,7 +71,7 @@ CallGraph FunctionCallGraphBuilder::buildDeployedGraph(
|
||||
FunctionCallGraphBuilder builder(_contract);
|
||||
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
|
||||
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
|
||||
// assigned to state variables and as such may be reachable after deployment as well.
|
||||
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))
|
||||
{
|
||||
solAssert(!holds_alternative<CallGraph::SpecialNode>(dispatchTarget), "");
|
||||
solAssert(get<CallableDeclaration const*>(dispatchTarget) != nullptr, "");
|
||||
solAssert(!std::holds_alternative<CallGraph::SpecialNode>(dispatchTarget), "");
|
||||
solAssert(std::get<CallableDeclaration const*>(dispatchTarget) != nullptr, "");
|
||||
|
||||
// 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;
|
||||
@ -262,10 +261,10 @@ void FunctionCallGraphBuilder::processQueue()
|
||||
while (!m_visitQueue.empty())
|
||||
{
|
||||
m_currentNode = m_visitQueue.front();
|
||||
solAssert(holds_alternative<CallableDeclaration const*>(m_currentNode), "");
|
||||
solAssert(std::holds_alternative<CallableDeclaration const*>(m_currentNode), "");
|
||||
|
||||
m_visitQueue.pop_front();
|
||||
get<CallableDeclaration const*>(m_currentNode)->accept(*this);
|
||||
std::get<CallableDeclaration const*>(m_currentNode)->accept(*this);
|
||||
}
|
||||
|
||||
m_currentNode = CallGraph::SpecialNode::Entry;
|
||||
@ -281,7 +280,7 @@ void FunctionCallGraphBuilder::functionReferenced(CallableDeclaration const& _ca
|
||||
if (_calledDirectly)
|
||||
{
|
||||
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."
|
||||
);
|
||||
|
||||
@ -293,10 +292,10 @@ void FunctionCallGraphBuilder::functionReferenced(CallableDeclaration const& _ca
|
||||
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))
|
||||
switch (get<CallGraph::SpecialNode>(_node))
|
||||
if (std::holds_alternative<CallGraph::SpecialNode>(_node))
|
||||
switch (std::get<CallGraph::SpecialNode>(_node))
|
||||
{
|
||||
case CallGraph::SpecialNode::InternalDispatch:
|
||||
_out << "InternalDispatch";
|
||||
@ -309,19 +308,19 @@ ostream& solidity::frontend::operator<<(ostream& _out, CallGraph::Node const& _n
|
||||
}
|
||||
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, "");
|
||||
|
||||
auto const* function = dynamic_cast<FunctionDefinition const *>(callableDeclaration);
|
||||
auto const* event = dynamic_cast<EventDefinition const *>(callableDeclaration);
|
||||
auto const* modifier = dynamic_cast<ModifierDefinition const *>(callableDeclaration);
|
||||
|
||||
auto typeToString = [](auto const& _var) -> string { return _var->type()->toString(true); };
|
||||
vector<string> parameters = callableDeclaration->parameters() | ranges::views::transform(typeToString) | ranges::to<vector<string>>();
|
||||
auto typeToString = [](auto const& _var) -> std::string { return _var->type()->toString(true); };
|
||||
std::vector<std::string> parameters = callableDeclaration->parameters() | ranges::views::transform(typeToString) | ranges::to<std::vector<std::string>>();
|
||||
|
||||
string scopeName;
|
||||
std::string scopeName;
|
||||
if (!function || !function->isFree())
|
||||
{
|
||||
solAssert(callableDeclaration->annotation().scope, "");
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
#include <libsolidity/ast/Types.h>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
@ -65,10 +63,10 @@ int magicVariableToID(std::string const& _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) {
|
||||
return make_shared<MagicVariableDeclaration>(magicVariableToID(_name), _name, _type);
|
||||
static auto const magicVarDecl = [](std::string const& _name, Type const* _type) {
|
||||
return std::make_shared<MagicVariableDeclaration>(magicVariableToID(_name), _name, _type);
|
||||
};
|
||||
|
||||
return {
|
||||
@ -116,9 +114,9 @@ void GlobalContext::setCurrentContract(ContractDefinition const& _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());
|
||||
for (ASTPointer<MagicVariableDeclaration const> const& variable: m_magicVariables)
|
||||
declarations.push_back(variable.get());
|
||||
@ -133,7 +131,7 @@ MagicVariableDeclaration const* GlobalContext::currentThis() const
|
||||
if (m_currentContract)
|
||||
type = TypeProvider::contract(*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();
|
||||
}
|
||||
@ -146,7 +144,7 @@ MagicVariableDeclaration const* GlobalContext::currentSuper() const
|
||||
if (m_currentContract)
|
||||
type = TypeProvider::typeType(TypeProvider::contract(*m_currentContract, true));
|
||||
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();
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
|
||||
namespace solidity::frontend
|
||||
@ -45,7 +44,7 @@ NameAndTypeResolver::NameAndTypeResolver(
|
||||
m_errorReporter(_errorReporter),
|
||||
m_globalContext(_globalContext)
|
||||
{
|
||||
m_scopes[nullptr] = make_shared<DeclarationContainer>();
|
||||
m_scopes[nullptr] = std::make_shared<DeclarationContainer>();
|
||||
for (Declaration const* declaration: _globalContext.declarations())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
bool error = false;
|
||||
for (auto const& node: _sourceUnit.nodes())
|
||||
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.
|
||||
solAssert(_sourceUnits.count(path), "");
|
||||
auto scope = m_scopes.find(_sourceUnits.at(path));
|
||||
@ -127,7 +126,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(SourceUnit& _source)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (shared_ptr<ASTNode> const& node: _source.nodes())
|
||||
for (std::shared_ptr<ASTNode> const& node: _source.nodes())
|
||||
{
|
||||
setScope(&_source);
|
||||
if (!resolveNamesAndTypesInternal(*node, true))
|
||||
@ -159,7 +158,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
|
||||
return true;
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::activateVariable(string const& _name)
|
||||
void NameAndTypeResolver::activateVariable(std::string const& _name)
|
||||
{
|
||||
solAssert(m_currentScope, "");
|
||||
// Scoped local variables are invisible before activation.
|
||||
@ -171,15 +170,15 @@ void NameAndTypeResolver::activateVariable(string const& _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);
|
||||
if (iterator == end(m_scopes))
|
||||
return vector<Declaration const*>({});
|
||||
return std::vector<Declaration const*>({});
|
||||
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;
|
||||
settings.recursive = true;
|
||||
@ -187,7 +186,7 @@ vector<Declaration const*> NameAndTypeResolver::nameFromCurrentScope(ASTString c
|
||||
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())
|
||||
return declarations.back();
|
||||
@ -201,13 +200,13 @@ std::vector<Declaration const*> NameAndTypeResolver::pathFromCurrentScopeWithAll
|
||||
) const
|
||||
{
|
||||
solAssert(!_path.empty(), "");
|
||||
vector<Declaration const*> pathDeclarations;
|
||||
std::vector<Declaration const*> pathDeclarations;
|
||||
|
||||
ResolvingSettings settings;
|
||||
settings.recursive = true;
|
||||
settings.alsoInvisible = _includeInvisibles;
|
||||
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
|
||||
settings.recursive = false;
|
||||
@ -305,7 +304,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
|
||||
if (success)
|
||||
{
|
||||
linearizeBaseContracts(*contract);
|
||||
vector<ContractDefinition const*> properBases(
|
||||
std::vector<ContractDefinition const*> properBases(
|
||||
++contract->annotation().linearizedBaseContracts.begin(),
|
||||
contract->annotation().linearizedBaseContracts.end()
|
||||
);
|
||||
@ -405,7 +404,7 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
|
||||
{
|
||||
// order in the lists is from derived to base
|
||||
// list of lists to linearize, the last element is the list of direct bases
|
||||
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())
|
||||
{
|
||||
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
|
||||
// mentioned earlier
|
||||
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())
|
||||
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);
|
||||
vector<ContractDefinition const*> result = cThreeMerge(input);
|
||||
std::vector<ContractDefinition const*> result = cThreeMerge(input);
|
||||
if (result.empty())
|
||||
m_errorReporter.fatalTypeError(5005_error, _contract.location(), "Linearization of inheritance graph impossible");
|
||||
_contract.annotation().linearizedBaseContracts = result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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
|
||||
auto appearsOnlyAtHead = [&](T const* _candidate) -> bool
|
||||
{
|
||||
for (list<T const*> const& bases: _toMerge)
|
||||
for (std::list<T const*> const& bases: _toMerge)
|
||||
{
|
||||
solAssert(!bases.empty(), "");
|
||||
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
|
||||
auto nextCandidate = [&]() -> T const*
|
||||
{
|
||||
for (list<T const*> const& bases: _toMerge)
|
||||
for (std::list<T const*> const& bases: _toMerge)
|
||||
{
|
||||
solAssert(!bases.empty(), "");
|
||||
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(); });
|
||||
vector<T const*> result;
|
||||
_toMerge.remove_if([](std::list<T const*> const& _bases) { return _bases.empty(); });
|
||||
std::vector<T const*> result;
|
||||
while (!_toMerge.empty())
|
||||
{
|
||||
T const* candidate = nextCandidate();
|
||||
if (!candidate)
|
||||
return vector<T const*>();
|
||||
return std::vector<T const*>();
|
||||
result.push_back(candidate);
|
||||
removeCandidate(candidate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const
|
||||
std::string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const
|
||||
{
|
||||
return util::quotedAlternativesList(m_currentScope->similarNames(_name));
|
||||
}
|
||||
|
||||
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
|
||||
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
|
||||
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
|
||||
ASTNode& _astRoot,
|
||||
ErrorReporter& _errorReporter,
|
||||
GlobalContext& _globalContext,
|
||||
@ -502,7 +501,7 @@ DeclarationRegistrationHelper::DeclarationRegistrationHelper(
|
||||
bool DeclarationRegistrationHelper::registerDeclaration(
|
||||
DeclarationContainer& _container,
|
||||
Declaration const& _declaration,
|
||||
string const* _name,
|
||||
std::string const* _name,
|
||||
SourceLocation const* _errorLocation,
|
||||
bool _inactive,
|
||||
ErrorReporter& _errorReporter
|
||||
@ -511,13 +510,13 @@ bool DeclarationRegistrationHelper::registerDeclaration(
|
||||
if (!_errorLocation)
|
||||
_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.
|
||||
// They cannot both be true at the same time.
|
||||
solAssert(!(_inactive && !_declaration.isVisibleInContract()), "");
|
||||
|
||||
static set<string> illegalNames{"_", "super", "this"};
|
||||
static std::set<std::string> illegalNames{"_", "super", "this"};
|
||||
|
||||
if (illegalNames.count(name))
|
||||
{
|
||||
@ -580,7 +579,7 @@ bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit)
|
||||
{
|
||||
if (!m_scopes[&_sourceUnit])
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -594,7 +593,7 @@ bool DeclarationRegistrationHelper::visit(ImportDirective& _import)
|
||||
SourceUnit const* importee = _import.annotation().sourceUnit;
|
||||
solAssert(!!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];
|
||||
ASTVisitor::visit(_import);
|
||||
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()))
|
||||
{
|
||||
string canonicalName = dynamic_cast<Declaration const&>(_node).name();
|
||||
std::string canonicalName = dynamic_cast<Declaration const&>(_node).name();
|
||||
solAssert(!canonicalName.empty(), "");
|
||||
|
||||
for (
|
||||
@ -684,7 +683,7 @@ void DeclarationRegistrationHelper::enterNewSubScope(ASTNode& _subScope)
|
||||
{
|
||||
bool newlyAdded = m_scopes.emplace(
|
||||
&_subScope,
|
||||
make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get())
|
||||
std::make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get())
|
||||
).second;
|
||||
solAssert(newlyAdded, "Unable to add new scope.");
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
@ -46,7 +45,7 @@ namespace
|
||||
// Helper struct to do a search by name
|
||||
struct MatchByName
|
||||
{
|
||||
string const& m_name;
|
||||
std::string const& m_name;
|
||||
bool operator()(OverrideProxy const& _item)
|
||||
{
|
||||
return _item.name() == m_name;
|
||||
@ -61,7 +60,7 @@ struct MatchByName
|
||||
*/
|
||||
struct OverrideGraph
|
||||
{
|
||||
OverrideGraph(set<OverrideProxy> const& _baseCallables)
|
||||
OverrideGraph(std::set<OverrideProxy> const& _baseCallables)
|
||||
{
|
||||
for (auto const& baseFunction: _baseCallables)
|
||||
addEdge(0, visit(baseFunction));
|
||||
@ -131,17 +130,17 @@ private:
|
||||
run(vInd, _depth + 1);
|
||||
if (m_low[vInd] >= m_depths[_u] && m_parent[_u] != -1)
|
||||
m_cutVertices.insert(m_graph.nodeInv.at(static_cast<int>(_u)));
|
||||
m_low[_u] = min(m_low[_u], m_low[vInd]);
|
||||
m_low[_u] = std::min(m_low[_u], m_low[vInd]);
|
||||
}
|
||||
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())
|
||||
{
|
||||
@ -155,7 +154,7 @@ vector<ContractDefinition const*> resolveDirectBaseContracts(ContractDefinition
|
||||
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;
|
||||
|
||||
@ -197,17 +196,17 @@ bool OverrideProxy::operator<(OverrideProxy const& _other) const
|
||||
|
||||
bool OverrideProxy::isVariable() const
|
||||
{
|
||||
return holds_alternative<VariableDeclaration const*>(m_item);
|
||||
return std::holds_alternative<VariableDeclaration const*>(m_item);
|
||||
}
|
||||
|
||||
bool OverrideProxy::isFunction() const
|
||||
{
|
||||
return holds_alternative<FunctionDefinition const*>(m_item);
|
||||
return std::holds_alternative<FunctionDefinition const*>(m_item);
|
||||
}
|
||||
|
||||
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
|
||||
@ -222,18 +221,18 @@ size_t OverrideProxy::id() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
shared_ptr<OverrideSpecifier> OverrideProxy::overrides() const
|
||||
std::shared_ptr<OverrideSpecifier> OverrideProxy::overrides() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](auto const* _item) { return _item->overrides(); }
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
set<OverrideProxy> OverrideProxy::baseFunctions() const
|
||||
std::set<OverrideProxy> OverrideProxy::baseFunctions() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](auto const* _item) -> set<OverrideProxy> {
|
||||
set<OverrideProxy> ret;
|
||||
[&](auto const* _item) -> std::set<OverrideProxy> {
|
||||
std::set<OverrideProxy> ret;
|
||||
for (auto const* f: _item->annotation().baseFunctions)
|
||||
ret.insert(makeOverrideProxy(*f));
|
||||
return ret;
|
||||
@ -256,10 +255,10 @@ void OverrideProxy::storeBaseFunction(OverrideProxy const& _base) const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
string const& OverrideProxy::name() const
|
||||
std::string const& OverrideProxy::name() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](auto const* _item) -> string const& { return _item->name(); }
|
||||
[&](auto const* _item) -> std::string const& { return _item->name(); }
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
@ -272,7 +271,7 @@ ContractDefinition const& OverrideProxy::contract() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
string const& OverrideProxy::contractName() const
|
||||
std::string const& OverrideProxy::contractName() const
|
||||
{
|
||||
return contract().name();
|
||||
}
|
||||
@ -357,7 +356,7 @@ SourceLocation const& OverrideProxy::location() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
string OverrideProxy::astNodeName() const
|
||||
std::string OverrideProxy::astNodeName() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](FunctionDefinition const*) { return "function"; },
|
||||
@ -366,7 +365,7 @@ string OverrideProxy::astNodeName() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
string OverrideProxy::astNodeNameCapitalized() const
|
||||
std::string OverrideProxy::astNodeNameCapitalized() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](FunctionDefinition const*) { return "Function"; },
|
||||
@ -375,7 +374,7 @@ string OverrideProxy::astNodeNameCapitalized() const
|
||||
}, m_item);
|
||||
}
|
||||
|
||||
string OverrideProxy::distinguishingProperty() const
|
||||
std::string OverrideProxy::distinguishingProperty() const
|
||||
{
|
||||
return std::visit(GenericVisitor{
|
||||
[&](FunctionDefinition const*) { return "name and parameter types"; },
|
||||
@ -418,10 +417,10 @@ OverrideProxy::OverrideComparator const& OverrideProxy::overrideComparator() con
|
||||
{
|
||||
if (!m_comparator)
|
||||
{
|
||||
m_comparator = make_shared<OverrideComparator>(std::visit(GenericVisitor{
|
||||
m_comparator = std::make_shared<OverrideComparator>(std::visit(GenericVisitor{
|
||||
[&](FunctionDefinition const* _function)
|
||||
{
|
||||
vector<string> paramTypes;
|
||||
std::vector<std::string> paramTypes;
|
||||
for (Type const* t: externalFunctionType()->parameterTypes())
|
||||
paramTypes.emplace_back(t->richIdentifier());
|
||||
return OverrideComparator{
|
||||
@ -432,7 +431,7 @@ OverrideProxy::OverrideComparator const& OverrideProxy::overrideComparator() con
|
||||
},
|
||||
[&](VariableDeclaration const* _var)
|
||||
{
|
||||
vector<string> paramTypes;
|
||||
std::vector<std::string> paramTypes;
|
||||
for (Type const* t: externalFunctionType()->parameterTypes())
|
||||
paramTypes.emplace_back(t->richIdentifier());
|
||||
return OverrideComparator{
|
||||
@ -674,21 +673,21 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
|
||||
|
||||
void OverrideChecker::overrideListError(
|
||||
OverrideProxy const& _item,
|
||||
set<ContractDefinition const*, CompareByID> _secondary,
|
||||
std::set<ContractDefinition const*, CompareByID> _secondary,
|
||||
ErrorId _error,
|
||||
string const& _message1,
|
||||
string const& _message2
|
||||
std::string const& _message1,
|
||||
std::string const& _message2
|
||||
)
|
||||
{
|
||||
// Using a set rather than a vector so the order is always the same
|
||||
set<string> names;
|
||||
std::set<std::string> names;
|
||||
SecondarySourceLocation ssl;
|
||||
for (Declaration const* c: _secondary)
|
||||
{
|
||||
ssl.append("This contract: ", c->location());
|
||||
names.insert("\"" + c->name() + "\"");
|
||||
}
|
||||
string contractSingularPlural = "contract ";
|
||||
std::string contractSingularPlural = "contract ";
|
||||
if (_secondary.size() > 1)
|
||||
contractSingularPlural = "contracts ";
|
||||
|
||||
@ -708,8 +707,8 @@ void OverrideChecker::overrideError(
|
||||
OverrideProxy const& _overriding,
|
||||
OverrideProxy const& _super,
|
||||
ErrorId _error,
|
||||
string const& _message,
|
||||
optional<string> const& _secondaryMsg
|
||||
std::string const& _message,
|
||||
std::optional<std::string> const& _secondaryMsg
|
||||
)
|
||||
{
|
||||
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)
|
||||
return;
|
||||
@ -799,17 +798,17 @@ void OverrideChecker::checkAmbiguousOverridesInternal(set<OverrideProxy> _baseCa
|
||||
for (OverrideProxy const& baseFunction: _baseCallables)
|
||||
ssl.append("Definition in \"" + baseFunction.contractName() + "\": ", baseFunction.location());
|
||||
|
||||
string callableName = _baseCallables.begin()->astNodeName();
|
||||
std::string callableName = _baseCallables.begin()->astNodeName();
|
||||
if (_baseCallables.begin()->isVariable())
|
||||
callableName = "function";
|
||||
string distinguishigProperty = _baseCallables.begin()->distinguishingProperty();
|
||||
std::string distinguishigProperty = _baseCallables.begin()->distinguishingProperty();
|
||||
|
||||
bool foundVariable = false;
|
||||
for (auto const& base: _baseCallables)
|
||||
if (base.isVariable())
|
||||
foundVariable = true;
|
||||
|
||||
string message =
|
||||
std::string message =
|
||||
"Derived contract must override " + callableName + " \"" +
|
||||
_baseCallables.begin()->name() +
|
||||
"\". 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);
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
@ -842,7 +841,7 @@ set<ContractDefinition const*, OverrideChecker::CompareByID> OverrideChecker::re
|
||||
|
||||
void OverrideChecker::checkOverrideList(OverrideProxy _item, OverrideProxyBySignatureMultiSet const& _inherited)
|
||||
{
|
||||
set<ContractDefinition const*, CompareByID> specifiedContracts =
|
||||
std::set<ContractDefinition const*, CompareByID> specifiedContracts =
|
||||
_item.overrides() ?
|
||||
resolveOverrideList(*_item.overrides()) :
|
||||
decltype(specifiedContracts){};
|
||||
@ -851,7 +850,7 @@ void OverrideChecker::checkOverrideList(OverrideProxy _item, OverrideProxyBySign
|
||||
if (_item.overrides() && specifiedContracts.size() != _item.overrides()->overrides().size())
|
||||
{
|
||||
// Sort by contract id to find duplicate for error reporting
|
||||
vector<ASTPointer<IdentifierPath>> list =
|
||||
std::vector<ASTPointer<IdentifierPath>> list =
|
||||
sortByContract(_item.overrides()->overrides());
|
||||
|
||||
// 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
|
||||
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."
|
||||
);
|
||||
|
||||
set<ContractDefinition const*, CompareByID> missingContracts;
|
||||
std::set<ContractDefinition const*, CompareByID> missingContracts;
|
||||
// If we expect only one contract, no contract needs to be specified
|
||||
if (expectedContracts.size() > 1)
|
||||
missingContracts = expectedContracts - specifiedContracts;
|
||||
@ -931,7 +930,7 @@ OverrideChecker::OverrideProxyBySignatureMultiSet const& OverrideChecker::inheri
|
||||
|
||||
for (auto const* base: resolveDirectBaseContracts(_contract))
|
||||
{
|
||||
set<OverrideProxy, OverrideProxy::CompareBySignature> functionsInBase;
|
||||
std::set<OverrideProxy, OverrideProxy::CompareBySignature> functionsInBase;
|
||||
for (FunctionDefinition const* fun: base->definedFunctions())
|
||||
if (!fun->isConstructor())
|
||||
functionsInBase.emplace(OverrideProxy{fun});
|
||||
@ -960,7 +959,7 @@ OverrideChecker::OverrideProxyBySignatureMultiSet const& OverrideChecker::inheri
|
||||
|
||||
for (auto const* base: resolveDirectBaseContracts(_contract))
|
||||
{
|
||||
set<OverrideProxy, OverrideProxy::CompareBySignature> modifiersInBase;
|
||||
std::set<OverrideProxy, OverrideProxy::CompareBySignature> modifiersInBase;
|
||||
for (ModifierDefinition const* mod: base->functionModifiers())
|
||||
modifiersInBase.emplace(OverrideProxy{mod});
|
||||
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -204,7 +203,7 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker
|
||||
// Iterating through the dependencies needs to be deterministic and thus cannot
|
||||
// depend on the memory layout.
|
||||
// Because of that, we sort by AST node id.
|
||||
vector<VariableDeclaration const*> dependencies(
|
||||
std::vector<VariableDeclaration const*> dependencies(
|
||||
m_constVariableDependencies[&_variable].begin(),
|
||||
m_constVariableDependencies[&_variable].end()
|
||||
);
|
||||
@ -427,10 +426,10 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker
|
||||
|
||||
PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter)
|
||||
{
|
||||
m_checkers.push_back(make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
|
||||
m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter));
|
||||
m_checkers.push_back(make_shared<ModifierContextChecker>(_errorReporter));
|
||||
m_checkers.push_back(make_shared<EventOutsideEmitErrorOutsideRevertChecker>(_errorReporter));
|
||||
m_checkers.push_back(make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
|
||||
m_checkers.push_back(make_shared<ReservedErrorSelector>(_errorReporter));
|
||||
m_checkers.push_back(std::make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
|
||||
m_checkers.push_back(std::make_shared<OverrideSpecifierChecker>(_errorReporter));
|
||||
m_checkers.push_back(std::make_shared<ModifierContextChecker>(_errorReporter));
|
||||
m_checkers.push_back(std::make_shared<EventOutsideEmitErrorOutsideRevertChecker>(_errorReporter));
|
||||
m_checkers.push_back(std::make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
|
||||
m_checkers.push_back(std::make_shared<ReservedErrorSelector>(_errorReporter));
|
||||
}
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <libsolutil/FunctionSelector.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
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())
|
||||
{
|
||||
string signature = error->functionType(true)->externalSignature();
|
||||
std::string signature = error->functionType(true)->externalSignature();
|
||||
uint32_t hash = util::selectorFromSignatureU32(signature);
|
||||
// Fail if there is a different signature for the same hash.
|
||||
if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature))
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -121,8 +120,8 @@ bool ReferencesResolver::visit(Identifier const& _identifier)
|
||||
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name());
|
||||
if (declarations.empty())
|
||||
{
|
||||
string suggestions = m_resolver.similarNameSuggestions(_identifier.name());
|
||||
string errorMessage = "Undeclared identifier.";
|
||||
std::string suggestions = m_resolver.similarNameSuggestions(_identifier.name());
|
||||
std::string errorMessage = "Undeclared identifier.";
|
||||
if (!suggestions.empty())
|
||||
{
|
||||
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.
|
||||
// As unintended side-effects other invisible names (eg.: super, this) may be returned as well.
|
||||
// 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())
|
||||
{
|
||||
string libraryOrFunctionNameErrorMessage =
|
||||
std::string libraryOrFunctionNameErrorMessage =
|
||||
_usingFor.usesBraces() ?
|
||||
"Identifier is not a function name or not unique." :
|
||||
"Identifier is not a library name.";
|
||||
@ -253,9 +252,9 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
{
|
||||
solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), "");
|
||||
|
||||
static set<string> suffixes{"slot", "offset", "length", "address", "selector"};
|
||||
string suffix;
|
||||
for (string const& s: suffixes)
|
||||
static std::set<std::string> suffixes{"slot", "offset", "length", "address", "selector"};
|
||||
std::string suffix;
|
||||
for (std::string const& s: suffixes)
|
||||
if (boost::algorithm::ends_with(_identifier.name.str(), "." + s))
|
||||
suffix = s;
|
||||
|
||||
@ -269,7 +268,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
if (!declarations.empty())
|
||||
// the special identifier exists itself, we should not allow that.
|
||||
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.");
|
||||
declarations = m_resolver.nameFromCurrentScope(realName);
|
||||
if (!declarations.empty())
|
||||
@ -350,7 +349,7 @@ void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _docum
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
string const& name = _annotation.docTags.find("inheritdoc")->second.content;
|
||||
std::string const& name = _annotation.docTags.find("inheritdoc")->second.content;
|
||||
if (name.empty())
|
||||
{
|
||||
m_errorReporter.docstringParsingError(
|
||||
@ -361,7 +360,7 @@ void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _docum
|
||||
return;
|
||||
}
|
||||
|
||||
vector<string> path;
|
||||
std::vector<std::string> path;
|
||||
boost::split(path, name, boost::is_any_of("."));
|
||||
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 '.'."
|
||||
);
|
||||
|
||||
if (set<string>{"this", "super", "_"}.count(_name.str()))
|
||||
if (std::set<std::string>{"this", "super", "_"}.count(_name.str()))
|
||||
m_errorReporter.declarationError(
|
||||
4113_error,
|
||||
_location,
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -71,7 +70,7 @@ private:
|
||||
return m_usesAssembly[&_contract];
|
||||
}
|
||||
|
||||
map<ContractDefinition const*, bool> m_usesAssembly;
|
||||
std::map<ContractDefinition const*, bool> m_usesAssembly;
|
||||
};
|
||||
|
||||
StaticAnalyzer::StaticAnalyzer(ErrorReporter& _errorReporter):
|
||||
@ -124,7 +123,7 @@ void StaticAnalyzer::endVisit(FunctionDefinition const&)
|
||||
5667_error,
|
||||
var.first.second->location(),
|
||||
"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."
|
||||
);
|
||||
else
|
||||
@ -142,7 +141,7 @@ bool StaticAnalyzer::visit(Identifier const& _identifier)
|
||||
{
|
||||
solAssert(!var->name().empty(), "");
|
||||
if (var->isLocalVariable())
|
||||
m_localVarUseCount[make_pair(var->id(), var)] += 1;
|
||||
m_localVarUseCount[std::make_pair(var->id(), var)] += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -154,7 +153,7 @@ bool StaticAnalyzer::visit(VariableDeclaration const& _variable)
|
||||
solAssert(_variable.isLocalVariable(), "");
|
||||
if (_variable.name() != "")
|
||||
// This is not a no-op, the entry might pre-exist.
|
||||
m_localVarUseCount[make_pair(_variable.id(), &_variable)] += 0;
|
||||
m_localVarUseCount[std::make_pair(_variable.id(), &_variable)] += 0;
|
||||
}
|
||||
|
||||
if (_variable.isStateVariable() || _variable.referenceLocation() == VariableDeclaration::Location::Storage)
|
||||
@ -162,7 +161,7 @@ bool StaticAnalyzer::visit(VariableDeclaration const& _variable)
|
||||
for (Type const* type: varType->fullDecomposition())
|
||||
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."
|
||||
" Either use mappings or dynamic arrays and allow their size to be increased only"
|
||||
" in small quantities per transaction.";
|
||||
@ -179,7 +178,7 @@ bool StaticAnalyzer::visit(Return const& _return)
|
||||
if (m_currentFunction && _return.expression())
|
||||
for (auto const& var: m_currentFunction->returnParameters())
|
||||
if (!var->name().empty())
|
||||
m_localVarUseCount[make_pair(var->id(), var.get())] += 1;
|
||||
m_localVarUseCount[std::make_pair(var->id(), var.get())] += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -214,7 +213,7 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
|
||||
else if (type->kind() == MagicType::Kind::MetaType && _memberAccess.memberName() == "runtimeCode")
|
||||
{
|
||||
if (!m_constructorUsesAssembly)
|
||||
m_constructorUsesAssembly = make_unique<ConstructorUsesAssembly>();
|
||||
m_constructorUsesAssembly = std::make_unique<ConstructorUsesAssembly>();
|
||||
ContractType const& contract = dynamic_cast<ContractType const&>(*type->typeArgument());
|
||||
if (m_constructorUsesAssembly->check(contract.contractDefinition()))
|
||||
m_errorReporter.warning(
|
||||
@ -288,7 +287,7 @@ bool StaticAnalyzer::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
solAssert(!var->name().empty(), "");
|
||||
if (var->isLocalVariable())
|
||||
m_localVarUseCount[make_pair(var->id(), var)] += 1;
|
||||
m_localVarUseCount[std::make_pair(var->id(), var)] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -55,17 +54,17 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
|
||||
{
|
||||
if (!m_versionPragmaFound)
|
||||
{
|
||||
string errorString("Source file does not specify required compiler version!");
|
||||
SemVerVersion recommendedVersion{string(VersionString)};
|
||||
std::string errorString("Source file does not specify required compiler version!");
|
||||
SemVerVersion recommendedVersion{std::string(VersionString)};
|
||||
if (!recommendedVersion.isPrerelease())
|
||||
errorString +=
|
||||
" Consider adding \"pragma solidity ^" +
|
||||
to_string(recommendedVersion.major()) +
|
||||
string(".") +
|
||||
to_string(recommendedVersion.minor()) +
|
||||
string(".") +
|
||||
to_string(recommendedVersion.patch()) +
|
||||
string(";\"");
|
||||
std::to_string(recommendedVersion.major()) +
|
||||
std::string(".") +
|
||||
std::to_string(recommendedVersion.minor()) +
|
||||
std::string(".") +
|
||||
std::to_string(recommendedVersion.patch()) +
|
||||
std::string(";\"");
|
||||
|
||||
// when reporting the warning, print the source name only
|
||||
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")
|
||||
{
|
||||
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())
|
||||
m_errorReporter.syntaxError(
|
||||
9679_error,
|
||||
@ -99,7 +98,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
|
||||
);
|
||||
else
|
||||
{
|
||||
string const literal = literals[0];
|
||||
std::string const literal = literals[0];
|
||||
if (literal.empty())
|
||||
m_errorReporter.syntaxError(3250_error, _pragma.location(), "Empty experimental feature name is invalid.");
|
||||
else if (!ExperimentalFeatureNames.count(literal))
|
||||
@ -135,7 +134,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
|
||||
solAssert(m_sourceUnit, "");
|
||||
if (
|
||||
_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(
|
||||
2745_error,
|
||||
@ -155,19 +154,12 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
|
||||
{
|
||||
try
|
||||
{
|
||||
vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
|
||||
vector<string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
|
||||
std::vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
|
||||
std::vector<std::string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
|
||||
SemVerMatchExpressionParser parser(tokens, literals);
|
||||
SemVerMatchExpression matchExpression = parser.parse();
|
||||
static SemVerVersion const currentVersion{string(VersionString)};
|
||||
if (!matchExpression.matches(currentVersion))
|
||||
m_errorReporter.syntaxError(
|
||||
3997_error,
|
||||
_pragma.location(),
|
||||
"Source file requires different compiler version (current compiler is " +
|
||||
string(VersionString) + ") - note that nightly builds are considered to be "
|
||||
"strictly less than the released version"
|
||||
);
|
||||
static SemVerVersion const currentVersion{std::string(VersionString)};
|
||||
solAssert(matchExpression.matches(currentVersion));
|
||||
m_versionPragmaFound = true;
|
||||
}
|
||||
catch (SemVerError const&)
|
||||
@ -412,7 +404,7 @@ bool SyntaxChecker::visit(UsingForDirective const& _usingFor)
|
||||
if (!_usingFor.usesBraces())
|
||||
solAssert(
|
||||
_usingFor.functionsAndOperators().size() == 1 &&
|
||||
!get<1>(_usingFor.functionsAndOperators().front())
|
||||
!std::get<1>(_usingFor.functionsAndOperators().front())
|
||||
);
|
||||
|
||||
if (!m_currentContractKind && !_usingFor.typeName())
|
||||
@ -455,7 +447,7 @@ bool SyntaxChecker::visit(FunctionDefinition const& _function)
|
||||
|
||||
if (!_function.isFree() && !_function.isConstructor() && _function.noVisibilitySpecified())
|
||||
{
|
||||
string suggestedVisibility =
|
||||
std::string suggestedVisibility =
|
||||
_function.isFallback() ||
|
||||
_function.isReceive() ||
|
||||
m_currentContractKind == ContractKind::Interface
|
||||
|
||||
@ -51,7 +51,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
@ -205,7 +204,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
|
||||
|
||||
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)
|
||||
m_errorReporter.typeError(
|
||||
5782_error,
|
||||
@ -296,7 +295,7 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c
|
||||
|
||||
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)
|
||||
m_errorReporter.fatalTypeError(
|
||||
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.");
|
||||
}
|
||||
|
||||
vector<VariableDeclaration const*> internalParametersInConstructor;
|
||||
std::vector<VariableDeclaration const*> internalParametersInConstructor;
|
||||
|
||||
auto checkArgumentAndReturnParameter = [&](VariableDeclaration const& _var) {
|
||||
if (type(_var)->containsNestedMapping())
|
||||
@ -472,7 +471,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
|
||||
if (!iType)
|
||||
{
|
||||
string message = iType.message();
|
||||
std::string message = iType.message();
|
||||
solAssert(!message.empty(), "Expected detailed error message!");
|
||||
if (_function.isConstructor())
|
||||
message += " You can make the contract abstract to avoid this problem.";
|
||||
@ -483,7 +482,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
!typeSupportedByOldABIEncoder(*type(_var), _function.libraryFunction())
|
||||
)
|
||||
{
|
||||
string message =
|
||||
std::string message =
|
||||
"This type is only supported in ABI coder v2. "
|
||||
"Use \"pragma abicoder v2;\" to enable the feature.";
|
||||
if (_function.isConstructor())
|
||||
@ -509,10 +508,10 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
var->accept(*this);
|
||||
}
|
||||
|
||||
set<Declaration const*> modifiers;
|
||||
std::set<Declaration const*> 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()))
|
||||
{
|
||||
baseContracts = contract->annotation().linearizedBaseContracts;
|
||||
@ -522,7 +521,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
|
||||
visitManually(
|
||||
*modifier,
|
||||
_function.isConstructor() ? baseContracts : vector<ContractDefinition const*>()
|
||||
_function.isConstructor() ? baseContracts : std::vector<ContractDefinition const*>()
|
||||
);
|
||||
Declaration const* decl = &dereference(modifier->name());
|
||||
if (modifiers.count(decl))
|
||||
@ -642,7 +641,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
||||
FunctionType getter(_variable);
|
||||
if (!useABICoderV2())
|
||||
{
|
||||
vector<string> unsupportedTypes;
|
||||
std::vector<std::string> unsupportedTypes;
|
||||
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
|
||||
if (!typeSupportedByOldABIEncoder(*param, false /* isLibrary */))
|
||||
unsupportedTypes.emplace_back(param->humanReadableName());
|
||||
@ -713,7 +712,7 @@ void TypeChecker::endVisit(StructDefinition const& _struct)
|
||||
|
||||
void TypeChecker::visitManually(
|
||||
ModifierInvocation const& _modifier,
|
||||
vector<ContractDefinition const*> const& _bases
|
||||
std::vector<ContractDefinition const*> const& _bases
|
||||
)
|
||||
{
|
||||
std::vector<ASTPointer<Expression>> const& arguments =
|
||||
@ -724,8 +723,8 @@ void TypeChecker::visitManually(
|
||||
_modifier.name().accept(*this);
|
||||
|
||||
auto const* declaration = &dereference(_modifier.name());
|
||||
vector<ASTPointer<VariableDeclaration>> emptyParameterList;
|
||||
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
||||
std::vector<ASTPointer<VariableDeclaration>> emptyParameterList;
|
||||
std::vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
||||
if (auto modifierDecl = dynamic_cast<ModifierDefinition const*>(declaration))
|
||||
{
|
||||
parameters = &modifierDecl->parameters();
|
||||
@ -920,8 +919,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
|
||||
if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
string const& suffix = identifierInfo.suffix;
|
||||
solAssert((set<string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
|
||||
std::string const& suffix = identifierInfo.suffix;
|
||||
solAssert((std::set<std::string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
|
||||
if (!var->isConstant() && (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage)))
|
||||
{
|
||||
if (suffix != "slot" && suffix != "offset")
|
||||
@ -1042,7 +1041,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
return true;
|
||||
};
|
||||
solAssert(!_inlineAssembly.annotation().analysisInfo, "");
|
||||
_inlineAssembly.annotation().analysisInfo = make_shared<yul::AsmAnalysisInfo>();
|
||||
_inlineAssembly.annotation().analysisInfo = std::make_shared<yul::AsmAnalysisInfo>();
|
||||
yul::AsmAnalyzer analyzer(
|
||||
*_inlineAssembly.annotation().analysisInfo,
|
||||
m_errorReporter,
|
||||
@ -1113,9 +1112,9 @@ void TypeChecker::endVisit(TryStatement const& _tryStatement)
|
||||
2800_error,
|
||||
successClause.location(),
|
||||
"Function returns " +
|
||||
to_string(functionType.returnParameterTypes().size()) +
|
||||
std::to_string(functionType.returnParameterTypes().size()) +
|
||||
" values, but returns clause has " +
|
||||
to_string(parameters.size()) +
|
||||
std::to_string(parameters.size()) +
|
||||
" variables."
|
||||
);
|
||||
for (auto&& [parameter, returnType]: ranges::views::zip(parameters, returnTypes))
|
||||
@ -1363,7 +1362,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
else
|
||||
valueTypes = TypePointers{type(*_statement.initialValue())};
|
||||
|
||||
vector<ASTPointer<VariableDeclaration>> const& variables = _statement.declarations();
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& variables = _statement.declarations();
|
||||
if (variables.empty())
|
||||
// We already have an error for this in the SyntaxChecker.
|
||||
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])
|
||||
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.");
|
||||
|
||||
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(
|
||||
tupleExpression->components().size() == types.size() || m_errorReporter.hasErrors(),
|
||||
"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])
|
||||
{
|
||||
solAssert(!!tupleExpression->components()[i], "");
|
||||
@ -1607,7 +1606,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
|
||||
7366_error,
|
||||
_assignment.location(),
|
||||
"Operator " +
|
||||
string(TokenTraits::friendlyName(_assignment.assignmentOperator())) +
|
||||
std::string(TokenTraits::friendlyName(_assignment.assignmentOperator())) +
|
||||
" not compatible with types " +
|
||||
t->humanReadableName() +
|
||||
" and " +
|
||||
@ -1621,7 +1620,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
|
||||
bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
{
|
||||
_tuple.annotation().isConstant = false;
|
||||
vector<ASTPointer<Expression>> const& components = _tuple.components();
|
||||
std::vector<ASTPointer<Expression>> const& components = _tuple.components();
|
||||
TypePointers types;
|
||||
|
||||
if (_tuple.annotation().willBeWrittenTo)
|
||||
@ -1734,7 +1733,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
|
||||
|
||||
// Check if the operator is built-in or user-defined.
|
||||
TypeResult builtinResult = operandType->unaryOperatorResult(op);
|
||||
set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = operandType->operatorDefinitions(
|
||||
std::set<FunctionDefinition const*, ASTNode::CompareByID> matchingDefinitions = operandType->operatorDefinitions(
|
||||
op,
|
||||
*currentDefinitionScope(),
|
||||
true // _unary
|
||||
@ -1760,7 +1759,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
|
||||
}
|
||||
else
|
||||
{
|
||||
string description = fmt::format(
|
||||
std::string description = fmt::format(
|
||||
"Built-in unary operator {} cannot be applied to type {}.",
|
||||
TokenTraits::friendlyName(op),
|
||||
operandType->humanReadableName()
|
||||
@ -1802,7 +1801,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
||||
|
||||
// Check if the operator is built-in or user-defined.
|
||||
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(),
|
||||
*currentDefinitionScope(),
|
||||
false // _unary
|
||||
@ -1828,7 +1827,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
||||
}
|
||||
else
|
||||
{
|
||||
string description = fmt::format(
|
||||
std::string description = fmt::format(
|
||||
"Built-in binary operator {} cannot be applied to types {} and {}.",
|
||||
TokenTraits::friendlyName(_operation.getOperator()),
|
||||
leftType->humanReadableName(),
|
||||
@ -1893,7 +1892,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
||||
|
||||
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 (
|
||||
leftType->category() == Type::Category::RationalNumber &&
|
||||
rightType->category() != Type::Category::RationalNumber
|
||||
@ -1933,7 +1932,7 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
|
||||
solAssert(*_functionCall.annotation().kind == FunctionCallKind::TypeConversion, "");
|
||||
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();
|
||||
|
||||
Type const* resultType = dynamic_cast<TypeType const&>(*expressionType).actualType();
|
||||
@ -2215,7 +2214,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
auto const& argType = type(*arguments[i]);
|
||||
@ -2274,7 +2273,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
|
||||
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.
|
||||
if (arguments.size() != 2)
|
||||
@ -2311,7 +2310,7 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
|
||||
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())
|
||||
{
|
||||
@ -2360,7 +2359,7 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
|
||||
}
|
||||
solAssert(!externalFunctionType->takesArbitraryParameters(), "Function must have fixed parameters.");
|
||||
// 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]));
|
||||
if (tupleType)
|
||||
@ -2387,9 +2386,9 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
|
||||
7788_error,
|
||||
_functionCall.location(),
|
||||
"Expected " +
|
||||
to_string(externalFunctionType->parameterTypes().size()) +
|
||||
std::to_string(externalFunctionType->parameterTypes().size()) +
|
||||
" instead of " +
|
||||
to_string(callArguments.size()) +
|
||||
std::to_string(callArguments.size()) +
|
||||
" components for the tuple parameter."
|
||||
);
|
||||
else
|
||||
@ -2397,13 +2396,13 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
|
||||
7515_error,
|
||||
_functionCall.location(),
|
||||
"Expected a tuple with " +
|
||||
to_string(externalFunctionType->parameterTypes().size()) +
|
||||
std::to_string(externalFunctionType->parameterTypes().size()) +
|
||||
" components instead of a single non-tuple parameter."
|
||||
);
|
||||
}
|
||||
|
||||
// Use min() to check as much as we can before failing fatally
|
||||
size_t const numParameters = 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++)
|
||||
{
|
||||
@ -2414,7 +2413,7 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
|
||||
5407_error,
|
||||
callArguments[i]->location(),
|
||||
"Cannot implicitly convert component at position " +
|
||||
to_string(i) +
|
||||
std::to_string(i) +
|
||||
" from \"" +
|
||||
argType.humanReadableName() +
|
||||
"\" to \"" +
|
||||
@ -2437,7 +2436,7 @@ void TypeChecker::typeCheckStringConcatFunction(
|
||||
|
||||
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);
|
||||
bool notConvertibleToString = !argumentType->isImplicitlyConvertibleTo(*TypeProvider::stringMemory());
|
||||
@ -2464,7 +2463,7 @@ void TypeChecker::typeCheckBytesConcatFunction(
|
||||
|
||||
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);
|
||||
bool notConvertibleToBytes =
|
||||
@ -2504,8 +2503,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
);
|
||||
|
||||
TypePointers const& parameterTypes = _functionType->parameterTypes();
|
||||
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
|
||||
vector<ASTPointer<ASTString>> const& argumentNames = _functionCall.names();
|
||||
std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
|
||||
std::vector<ASTPointer<ASTString>> const& argumentNames = _functionCall.names();
|
||||
|
||||
// Check number of passed in arguments
|
||||
if (
|
||||
@ -2516,22 +2515,22 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
bool const isStructConstructorCall =
|
||||
functionCallKind == FunctionCallKind::StructConstructorCall;
|
||||
|
||||
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
|
||||
string msg = isVariadic ?
|
||||
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
|
||||
std::string msg = isVariadic ?
|
||||
"Need at least " +
|
||||
toString(parameterTypes.size()) +
|
||||
" arguments for " +
|
||||
string(isStructConstructorCall ? "struct constructor" : "function call") +
|
||||
std::string(isStructConstructorCall ? "struct constructor" : "function call") +
|
||||
", but provided only " +
|
||||
toString(arguments.size()) +
|
||||
"."
|
||||
:
|
||||
"Wrong argument count for " +
|
||||
string(isStructConstructorCall ? "struct constructor" : "function call") +
|
||||
std::string(isStructConstructorCall ? "struct constructor" : "function call") +
|
||||
": " +
|
||||
toString(arguments.size()) +
|
||||
" arguments given but " +
|
||||
string(isVariadic ? "need at least " : "expected ") +
|
||||
std::string(isVariadic ? "need at least " : "expected ") +
|
||||
toString(parameterTypes.size()) +
|
||||
".";
|
||||
|
||||
@ -2659,8 +2658,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
BoolResult result = type(*paramArgMap[i])->isImplicitlyConvertibleTo(*parameterTypes[i]);
|
||||
if (!result)
|
||||
{
|
||||
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
|
||||
string msg =
|
||||
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
|
||||
std::string msg =
|
||||
"Invalid type for argument in function call. "
|
||||
"Invalid implicit conversion from " +
|
||||
type(*paramArgMap[i])->humanReadableName() +
|
||||
@ -2751,7 +2750,7 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
|
||||
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;
|
||||
|
||||
// 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."
|
||||
);
|
||||
|
||||
auto setCheckOption = [&](bool& _option, string const& _name)
|
||||
auto setCheckOption = [&](bool& _option, std::string const& _name)
|
||||
{
|
||||
if (_option)
|
||||
m_errorReporter.typeError(
|
||||
@ -3005,7 +3004,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
|
||||
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 (kind == FunctionType::Kind::Creation)
|
||||
@ -3185,8 +3184,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
||||
);
|
||||
}
|
||||
|
||||
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
|
||||
string errorMsg = "Member \"" + memberName + "\" not found or not visible "
|
||||
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
|
||||
std::string errorMsg = "Member \"" + memberName + "\" not found or not visible "
|
||||
"after argument-dependent lookup in " + exprType->humanReadableName() + ".";
|
||||
|
||||
if (auto const* funType = dynamic_cast<FunctionType const*>(exprType))
|
||||
@ -3222,7 +3221,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
||||
if (addressMember.name == memberName)
|
||||
{
|
||||
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.";
|
||||
return { 3125_error, errorMsg };
|
||||
}
|
||||
@ -3606,13 +3605,13 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
|
||||
std::vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
|
||||
Identifier const& _identifier,
|
||||
vector<Declaration const*> const& _candidates
|
||||
std::vector<Declaration const*> const& _candidates
|
||||
)
|
||||
{
|
||||
solAssert(_candidates.size() > 1, "");
|
||||
vector<Declaration const*> uniqueDeclarations;
|
||||
std::vector<Declaration const*> uniqueDeclarations;
|
||||
|
||||
for (Declaration const* declaration: _candidates)
|
||||
{
|
||||
@ -3665,7 +3664,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
|
||||
else if (!annotation.arguments)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
@ -3681,7 +3680,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<Declaration const*> candidates;
|
||||
std::vector<Declaration const*> candidates;
|
||||
|
||||
for (Declaration const* declaration: annotation.overloadedDeclarations)
|
||||
{
|
||||
@ -3700,7 +3699,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
|
||||
if (!declaration->location().isValid())
|
||||
{
|
||||
// Try to re-construct function definition
|
||||
string description;
|
||||
std::string description;
|
||||
for (auto const& param: declaration->functionType(true)->parameterTypes())
|
||||
description += (description.empty() ? "" : ", ") + param->humanReadableName();
|
||||
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
|
||||
_literal.annotation().type = TypeProvider::address();
|
||||
|
||||
string msg;
|
||||
std::string msg;
|
||||
if (_literal.valueWithoutUnderscores().length() != 42) // "0x" + 40 hex digits
|
||||
// looksLikeAddress enforces that it is a hex literal starting with "0x"
|
||||
msg =
|
||||
"This looks like an address but is not exactly 40 hex digits. It is " +
|
||||
to_string(_literal.valueWithoutUnderscores().length() - 2) +
|
||||
std::to_string(_literal.valueWithoutUnderscores().length() - 2) +
|
||||
" hex digits.";
|
||||
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 firstParameterMatchesUsingFor = parameterCount == 0 || *usingForType == *parameterTypes.front();
|
||||
|
||||
optional<string> wrongParametersMessage;
|
||||
std::optional<std::string> wrongParametersMessage;
|
||||
if (isBinaryOnlyOperator && (parameterCount != 2 || !identicalFirstTwoParameters))
|
||||
wrongParametersMessage = fmt::format("two parameters of type {} and the same data location", usingForType->canonicalName());
|
||||
else if (isUnaryOnlyOperator && (parameterCount != 1 || !firstParameterMatchesUsingFor))
|
||||
@ -4065,7 +4064,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
|
||||
TypePointers const& returnParameterTypes = functionType->returnParameterTypes();
|
||||
size_t const returnParameterCount = returnParameterTypes.size();
|
||||
|
||||
optional<string> wrongReturnParametersMessage;
|
||||
std::optional<std::string> wrongReturnParametersMessage;
|
||||
if (!TokenTraits::isCompareOp(operator_.value()) && operator_.value() != Token::Not)
|
||||
{
|
||||
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
|
||||
// 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(),
|
||||
*currentDefinitionScope(),
|
||||
parameterCount == 1 // _unary
|
||||
@ -4133,7 +4132,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
|
||||
|
||||
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())
|
||||
{
|
||||
if (type(*var)->containsNestedMapping())
|
||||
@ -4223,7 +4222,7 @@ void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAss
|
||||
if (*_expression.annotation().isLValue)
|
||||
return;
|
||||
|
||||
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
|
||||
auto [errorId, description] = [&]() -> std::tuple<ErrorId, std::string> {
|
||||
if (*_expression.annotation().isConstant)
|
||||
return { 6520_error, "Cannot assign to a constant variable." };
|
||||
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -312,13 +311,13 @@ ViewPureChecker::MutabilityAndLocation const& ViewPureChecker::modifierMutabilit
|
||||
{
|
||||
MutabilityAndLocation bestMutabilityAndLocation{};
|
||||
FunctionDefinition const* currentFunction = nullptr;
|
||||
swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
|
||||
swap(currentFunction, m_currentFunction);
|
||||
std::swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
|
||||
std::swap(currentFunction, m_currentFunction);
|
||||
|
||||
_modifier.accept(*this);
|
||||
|
||||
swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
|
||||
swap(currentFunction, m_currentFunction);
|
||||
std::swap(bestMutabilityAndLocation, m_bestMutabilityAndLocation);
|
||||
std::swap(currentFunction, m_currentFunction);
|
||||
}
|
||||
return m_inferredMutability.at(&_modifier);
|
||||
}
|
||||
@ -384,8 +383,8 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
|
||||
break;
|
||||
case Type::Category::Magic:
|
||||
{
|
||||
using MagicMember = pair<MagicType::Kind, string>;
|
||||
set<MagicMember> static const pureMembers{
|
||||
using MagicMember = std::pair<MagicType::Kind, std::string>;
|
||||
std::set<MagicMember> static const pureMembers{
|
||||
{MagicType::Kind::ABI, "decode"},
|
||||
{MagicType::Kind::ABI, "encode"},
|
||||
{MagicType::Kind::ABI, "encodePacked"},
|
||||
@ -401,7 +400,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
|
||||
{MagicType::Kind::MetaType, "min"},
|
||||
{MagicType::Kind::MetaType, "max"},
|
||||
};
|
||||
set<MagicMember> static const payableMembers{
|
||||
std::set<MagicMember> static const payableMembers{
|
||||
{MagicType::Kind::Message, "value"}
|
||||
};
|
||||
|
||||
|
||||
@ -39,13 +39,12 @@
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
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))
|
||||
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
|
||||
{
|
||||
if (!m_annotation)
|
||||
m_annotation = make_unique<ASTAnnotation>();
|
||||
m_annotation = std::make_unique<ASTAnnotation>();
|
||||
return *m_annotation;
|
||||
}
|
||||
|
||||
@ -128,9 +127,9 @@ SourceUnitAnnotation& SourceUnit::annotation() const
|
||||
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()))
|
||||
{
|
||||
auto const& sourceUnit = importDirective->annotation().sourceUnit;
|
||||
@ -161,11 +160,11 @@ bool ContractDefinition::derivesFrom(ContractDefinition const& _base) const
|
||||
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);
|
||||
|
||||
map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions;
|
||||
std::map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions;
|
||||
for (auto const& it: exportedFunctionList)
|
||||
exportedFunctions.insert(it);
|
||||
|
||||
@ -208,11 +207,11 @@ FunctionDefinition const* ContractDefinition::receiveFunction() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
|
||||
std::vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
|
||||
{
|
||||
return m_interfaceEvents.init([&]{
|
||||
set<string> eventsSeen;
|
||||
vector<EventDefinition const*> interfaceEvents;
|
||||
std::set<std::string> eventsSeen;
|
||||
std::vector<EventDefinition const*> interfaceEvents;
|
||||
|
||||
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
||||
for (EventDefinition const* e: contract->events())
|
||||
@ -222,7 +221,7 @@ vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents
|
||||
/// and not to function encoding (jump vs. call)
|
||||
FunctionType const* functionType = e->functionType(true);
|
||||
solAssert(functionType, "");
|
||||
string eventSignature = functionType->externalSignature();
|
||||
std::string eventSignature = functionType->externalSignature();
|
||||
if (eventsSeen.count(eventSignature) == 0)
|
||||
{
|
||||
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(), "");
|
||||
|
||||
@ -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)
|
||||
result += contract->events();
|
||||
solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set());
|
||||
@ -255,12 +254,12 @@ vector<EventDefinition const*> ContractDefinition::interfaceEvents(bool _require
|
||||
result += usedInterfaceEvents();
|
||||
// We could filter out all events that do not have an external interface
|
||||
// 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)
|
||||
result += filteredNodes<ErrorDefinition>(contract->m_subNodes);
|
||||
solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set(), "");
|
||||
@ -270,20 +269,20 @@ vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _require
|
||||
result +=
|
||||
(*annotation().creationCallGraph)->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([&]{
|
||||
set<string> signaturesSeen;
|
||||
vector<pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList;
|
||||
std::set<std::string> signaturesSeen;
|
||||
std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList;
|
||||
|
||||
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
||||
{
|
||||
if (_includeInheritedFunctions == false && contract != this)
|
||||
continue;
|
||||
vector<FunctionTypePointer> functions;
|
||||
std::vector<FunctionTypePointer> functions;
|
||||
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||
if (f->isPartOfExternalInterface())
|
||||
functions.push_back(TypeProvider::function(*f, FunctionType::Kind::External));
|
||||
@ -295,7 +294,7 @@ vector<pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition:
|
||||
if (!fun->interfaceFunctionType())
|
||||
// Fails hopefully because we already registered the error
|
||||
continue;
|
||||
string functionSignature = fun->externalSignature();
|
||||
std::string functionSignature = fun->externalSignature();
|
||||
if (signaturesSeen.count(functionSignature) == 0)
|
||||
{
|
||||
signaturesSeen.insert(functionSignature);
|
||||
@ -357,7 +356,7 @@ FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition
|
||||
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([&]{
|
||||
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
|
||||
{
|
||||
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
|
||||
@ -484,12 +483,12 @@ Type const* FunctionDefinition::typeViaContractName() const
|
||||
return TypeProvider::function(*this, FunctionType::Kind::Declaration);
|
||||
}
|
||||
|
||||
string FunctionDefinition::externalSignature() const
|
||||
std::string FunctionDefinition::externalSignature() const
|
||||
{
|
||||
return TypeProvider::function(*this)->externalSignature();
|
||||
}
|
||||
|
||||
string FunctionDefinition::externalIdentifierHex() const
|
||||
std::string FunctionDefinition::externalIdentifierHex() const
|
||||
{
|
||||
return TypeProvider::function(*this)->externalIdentifierHex();
|
||||
}
|
||||
@ -639,7 +638,7 @@ CallableDeclaration const* Scopable::functionOrModifierDefinition() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
string Scopable::sourceUnitName() const
|
||||
std::string Scopable::sourceUnitName() const
|
||||
{
|
||||
return *sourceUnit().annotation().path;
|
||||
}
|
||||
@ -701,7 +700,7 @@ bool VariableDeclaration::isCallableOrCatchParameter() const
|
||||
if (isReturnParameter() || isTryCatchParameter())
|
||||
return true;
|
||||
|
||||
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
||||
std::vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
||||
|
||||
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
||||
parameters = &funTypeName->parameterTypes();
|
||||
@ -722,7 +721,7 @@ bool VariableDeclaration::isLocalOrReturn() 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()))
|
||||
returnParameters = &funTypeName->returnParameterTypes();
|
||||
@ -813,15 +812,15 @@ bool VariableDeclaration::isFileLevelVariable() const
|
||||
return dynamic_cast<SourceUnit const*>(scope());
|
||||
}
|
||||
|
||||
set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
|
||||
std::set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
|
||||
{
|
||||
using Location = VariableDeclaration::Location;
|
||||
|
||||
if (!hasReferenceOrMappingType() || isStateVariable() || isEventOrErrorParameter())
|
||||
return set<Location>{ Location::Unspecified };
|
||||
return std::set<Location>{ Location::Unspecified };
|
||||
else if (isCallableOrCatchParameter())
|
||||
{
|
||||
set<Location> locations{ Location::Memory };
|
||||
std::set<Location> locations{ Location::Memory };
|
||||
if (
|
||||
isConstructorParameter() ||
|
||||
isInternalCallableParameter() ||
|
||||
@ -835,13 +834,13 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c
|
||||
}
|
||||
else if (isLocalVariable())
|
||||
// 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
|
||||
// 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");
|
||||
return TypeProvider::function(*this)->externalIdentifierHex();
|
||||
@ -958,7 +957,7 @@ FunctionCallAnnotation& FunctionCall::annotation() const
|
||||
return initAnnotation<FunctionCallAnnotation>();
|
||||
}
|
||||
|
||||
vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
|
||||
std::vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
|
||||
{
|
||||
// normal arguments
|
||||
if (m_names.empty())
|
||||
@ -975,7 +974,7 @@ vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
|
||||
else
|
||||
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())
|
||||
{
|
||||
bool found = false;
|
||||
@ -1030,13 +1029,13 @@ bool Literal::passesAddressChecksum() const
|
||||
return util::passesAddressChecksum(valueWithoutUnderscores(), true);
|
||||
}
|
||||
|
||||
string Literal::getChecksummedAddress() const
|
||||
std::string Literal::getChecksummedAddress() const
|
||||
{
|
||||
solAssert(isHexNumber(), "Expected hex number");
|
||||
/// Pad literal to be a proper hex address.
|
||||
string address = valueWithoutUnderscores().substr(2);
|
||||
std::string address = valueWithoutUnderscores().substr(2);
|
||||
if (address.length() > 40)
|
||||
return string();
|
||||
return std::string();
|
||||
address.insert(address.begin(), 40 - address.size(), '0');
|
||||
return util::getChecksummedAddress(address);
|
||||
}
|
||||
|
||||
@ -87,15 +87,19 @@ public:
|
||||
static void listAccept(std::vector<T> const& _list, ASTVisitor& _visitor)
|
||||
{
|
||||
for (T const& element: _list)
|
||||
if (element)
|
||||
element->accept(_visitor);
|
||||
{
|
||||
solAssert(element);
|
||||
element->accept(_visitor);
|
||||
}
|
||||
}
|
||||
template <class T>
|
||||
static void listAccept(std::vector<T> const& _list, ASTConstVisitor& _visitor)
|
||||
{
|
||||
for (T const& element: _list)
|
||||
if (element)
|
||||
element->accept(_visitor);
|
||||
{
|
||||
solAssert(element);
|
||||
element->accept(_visitor);
|
||||
}
|
||||
}
|
||||
|
||||
/// @returns a copy of the vector containing only the nodes which derive from T.
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
|
||||
#include <libsolidity/ast/ASTAnnotations.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
|
||||
@ -44,7 +44,6 @@
|
||||
#include <type_traits>
|
||||
#include <range/v3/view/map.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::string_literals;
|
||||
using namespace solidity::langutil;
|
||||
|
||||
@ -52,14 +51,14 @@ namespace
|
||||
{
|
||||
|
||||
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 (!_value.set())
|
||||
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())
|
||||
return;
|
||||
@ -73,7 +72,7 @@ void addIfSet(std::vector<pair<string, Json::Value>>& _attributes, string const&
|
||||
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_sourceIndices(std::move(_sourceIndices))
|
||||
{
|
||||
@ -82,21 +81,21 @@ ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, map<string, u
|
||||
|
||||
void ASTJsonExporter::setJsonNode(
|
||||
ASTNode const& _node,
|
||||
string const& _nodeName,
|
||||
initializer_list<pair<string, Json::Value>>&& _attributes
|
||||
std::string const& _nodeName,
|
||||
std::initializer_list<std::pair<std::string, Json::Value>>&& _attributes
|
||||
)
|
||||
{
|
||||
ASTJsonExporter::setJsonNode(
|
||||
_node,
|
||||
_nodeName,
|
||||
std::vector<pair<string, Json::Value>>(std::move(_attributes))
|
||||
std::vector<std::pair<std::string, Json::Value>>(std::move(_attributes))
|
||||
);
|
||||
}
|
||||
|
||||
void ASTJsonExporter::setJsonNode(
|
||||
ASTNode const& _node,
|
||||
string const& _nodeType,
|
||||
std::vector<pair<string, Json::Value>>&& _attributes
|
||||
std::string const& _nodeType,
|
||||
std::vector<std::pair<std::string, Json::Value>>&& _attributes
|
||||
)
|
||||
{
|
||||
m_currentValue = Json::objectValue;
|
||||
@ -110,24 +109,24 @@ void ASTJsonExporter::setJsonNode(
|
||||
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))
|
||||
return m_sourceIndices.at(*_location.sourceName);
|
||||
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;
|
||||
if (_location.start >= 0 && _location.end >= 0)
|
||||
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;
|
||||
|
||||
@ -137,7 +136,7 @@ Json::Value ASTJsonExporter::sourceLocationsToJson(vector<SourceLocation> const&
|
||||
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);
|
||||
}
|
||||
@ -164,13 +163,13 @@ Json::Value ASTJsonExporter::typePointerToJson(std::optional<FuncCallArguments>
|
||||
}
|
||||
|
||||
void ASTJsonExporter::appendExpressionAttributes(
|
||||
std::vector<pair<string, Json::Value>>& _attributes,
|
||||
std::vector<std::pair<std::string, Json::Value>>& _attributes,
|
||||
ExpressionAnnotation const& _annotation
|
||||
)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> exprAttributes = {
|
||||
make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
|
||||
make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
|
||||
std::vector<std::pair<std::string, Json::Value>> exprAttributes = {
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
|
||||
std::make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
|
||||
};
|
||||
|
||||
addIfSet(exprAttributes, "isLValue", _annotation.isLValue);
|
||||
@ -183,7 +182,7 @@ void ASTJsonExporter::appendExpressionAttributes(
|
||||
_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);
|
||||
tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first));
|
||||
@ -199,7 +198,7 @@ Json::Value ASTJsonExporter::inlineAssemblyIdentifierToJson(pair<yul::Identifier
|
||||
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);
|
||||
}
|
||||
@ -212,9 +211,9 @@ Json::Value ASTJsonExporter::toJson(ASTNode const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(SourceUnit const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
|
||||
make_pair("nodes", toJson(_node.nodes())),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("license", _node.licenseString() ? Json::Value(*_node.licenseString()) : Json::nullValue),
|
||||
std::make_pair("nodes", toJson(_node.nodes())),
|
||||
};
|
||||
|
||||
if (_node.experimentalSolidity())
|
||||
@ -246,17 +245,17 @@ bool ASTJsonExporter::visit(PragmaDirective const& _node)
|
||||
for (auto const& literal: _node.literals())
|
||||
literals.append(literal);
|
||||
setJsonNode(_node, "PragmaDirective", {
|
||||
make_pair("literals", std::move(literals))
|
||||
std::make_pair("literals", std::move(literals))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(ImportDirective const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("file", _node.path()),
|
||||
make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("file", _node.path()),
|
||||
std::make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
|
||||
std::make_pair("scope", idOrNull(_node.scope()))
|
||||
};
|
||||
|
||||
addIfSet(attributes, "absolutePath", _node.annotation().absolutePath);
|
||||
@ -281,19 +280,19 @@ bool ASTJsonExporter::visit(ImportDirective const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(ContractDefinition const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("contractKind", contractKind(_node.contractKind())),
|
||||
make_pair("abstract", _node.abstract()),
|
||||
make_pair("baseContracts", toJson(_node.baseContracts())),
|
||||
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies | ranges::views::keys)),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("contractKind", contractKind(_node.contractKind())),
|
||||
std::make_pair("abstract", _node.abstract()),
|
||||
std::make_pair("baseContracts", toJson(_node.baseContracts())),
|
||||
std::make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies | ranges::views::keys)),
|
||||
// Do not require call graph because the AST is also created for incorrect sources.
|
||||
make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))),
|
||||
make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))),
|
||||
make_pair("nodes", toJson(_node.subNodes())),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
std::make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))),
|
||||
std::make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))),
|
||||
std::make_pair("nodes", toJson(_node.subNodes())),
|
||||
std::make_pair("scope", idOrNull(_node.scope()))
|
||||
};
|
||||
addIfSet(attributes, "canonicalName", _node.annotation().canonicalName);
|
||||
|
||||
@ -306,7 +305,7 @@ bool ASTJsonExporter::visit(ContractDefinition const& _node)
|
||||
{
|
||||
Json::Value internalFunctionIDs(Json::objectValue);
|
||||
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));
|
||||
}
|
||||
|
||||
@ -322,9 +321,9 @@ bool ASTJsonExporter::visit(IdentifierPath const& _node)
|
||||
nameLocations.append(sourceLocationToString(location));
|
||||
|
||||
setJsonNode(_node, "IdentifierPath", {
|
||||
make_pair("name", namePathToString(_node.path())),
|
||||
make_pair("nameLocations", nameLocations),
|
||||
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration))
|
||||
std::make_pair("name", namePathToString(_node.path())),
|
||||
std::make_pair("nameLocations", nameLocations),
|
||||
std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -332,16 +331,16 @@ bool ASTJsonExporter::visit(IdentifierPath const& _node)
|
||||
bool ASTJsonExporter::visit(InheritanceSpecifier const& _node)
|
||||
{
|
||||
setJsonNode(_node, "InheritanceSpecifier", {
|
||||
make_pair("baseName", toJson(_node.name())),
|
||||
make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
|
||||
std::make_pair("baseName", toJson(_node.name())),
|
||||
std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(UsingForDirective const& _node)
|
||||
{
|
||||
vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue)
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json::nullValue)
|
||||
};
|
||||
|
||||
if (_node.usesBraces())
|
||||
@ -355,7 +354,7 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node)
|
||||
else
|
||||
{
|
||||
functionNode["definition"] = toJson(*function);
|
||||
functionNode["operator"] = string(TokenTraits::toString(*op));
|
||||
functionNode["operator"] = std::string(TokenTraits::toString(*op));
|
||||
}
|
||||
functionList.append(std::move(functionNode));
|
||||
}
|
||||
@ -377,13 +376,13 @@ bool ASTJsonExporter::visit(UsingForDirective const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(StructDefinition const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("members", toJson(_node.members())),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
std::make_pair("members", toJson(_node.members())),
|
||||
std::make_pair("scope", idOrNull(_node.scope()))
|
||||
};
|
||||
|
||||
addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
|
||||
@ -395,11 +394,11 @@ bool ASTJsonExporter::visit(StructDefinition const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(EnumDefinition const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("members", toJson(_node.members()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("members", toJson(_node.members()))
|
||||
};
|
||||
|
||||
addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
|
||||
@ -412,8 +411,8 @@ bool ASTJsonExporter::visit(EnumDefinition const& _node)
|
||||
bool ASTJsonExporter::visit(EnumValue const& _node)
|
||||
{
|
||||
setJsonNode(_node, "EnumValue", {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -421,10 +420,10 @@ bool ASTJsonExporter::visit(EnumValue const& _node)
|
||||
bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node)
|
||||
{
|
||||
solAssert(_node.underlyingType(), "");
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("underlyingType", toJson(*_node.underlyingType()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("underlyingType", toJson(*_node.underlyingType()))
|
||||
};
|
||||
addIfSet(attributes, "canonicalName", _node.annotation().canonicalName);
|
||||
|
||||
@ -436,7 +435,7 @@ bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node)
|
||||
bool ASTJsonExporter::visit(ParameterList const& _node)
|
||||
{
|
||||
setJsonNode(_node, "ParameterList", {
|
||||
make_pair("parameters", toJson(_node.parameters()))
|
||||
std::make_pair("parameters", toJson(_node.parameters()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -444,30 +443,30 @@ bool ASTJsonExporter::visit(ParameterList const& _node)
|
||||
bool ASTJsonExporter::visit(OverrideSpecifier const& _node)
|
||||
{
|
||||
setJsonNode(_node, "OverrideSpecifier", {
|
||||
make_pair("overrides", toJson(_node.overrides()))
|
||||
std::make_pair("overrides", toJson(_node.overrides()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(FunctionDefinition const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())),
|
||||
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||
make_pair("virtual", _node.markedVirtual()),
|
||||
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
make_pair("parameters", toJson(_node.parameterList())),
|
||||
make_pair("returnParameters", toJson(*_node.returnParameterList())),
|
||||
make_pair("modifiers", toJson(_node.modifiers())),
|
||||
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue),
|
||||
make_pair("implemented", _node.isImplemented()),
|
||||
make_pair("scope", idOrNull(_node.scope()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())),
|
||||
std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||
std::make_pair("virtual", _node.markedVirtual()),
|
||||
std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
std::make_pair("parameters", toJson(_node.parameterList())),
|
||||
std::make_pair("returnParameters", toJson(*_node.returnParameterList())),
|
||||
std::make_pair("modifiers", toJson(_node.modifiers())),
|
||||
std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue),
|
||||
std::make_pair("implemented", _node.isImplemented()),
|
||||
std::make_pair("scope", idOrNull(_node.scope()))
|
||||
};
|
||||
|
||||
optional<Visibility> visibility;
|
||||
std::optional<Visibility> visibility;
|
||||
if (_node.isConstructor())
|
||||
{
|
||||
if (_node.annotation().contract)
|
||||
@ -482,7 +481,7 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node)
|
||||
if (_node.isPartOfExternalInterface() && m_stackState > CompilerStack::State::ParsedAndImported)
|
||||
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
|
||||
if (!_node.annotation().baseFunctions.empty())
|
||||
attributes.emplace_back(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));
|
||||
return false;
|
||||
@ -490,19 +489,19 @@ bool ASTJsonExporter::visit(FunctionDefinition const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(VariableDeclaration const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("typeName", toJson(_node.typeName())),
|
||||
make_pair("constant", _node.isConstant()),
|
||||
make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
|
||||
make_pair("stateVariable", _node.isStateVariable()),
|
||||
make_pair("storageLocation", location(_node.referenceLocation())),
|
||||
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue),
|
||||
make_pair("scope", idOrNull(_node.scope())),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("typeName", toJson(_node.typeName())),
|
||||
std::make_pair("constant", _node.isConstant()),
|
||||
std::make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
|
||||
std::make_pair("stateVariable", _node.isStateVariable()),
|
||||
std::make_pair("storageLocation", location(_node.referenceLocation())),
|
||||
std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue),
|
||||
std::make_pair("scope", idOrNull(_node.scope())),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
};
|
||||
if (_node.isStateVariable() && _node.isPublic())
|
||||
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
|
||||
@ -511,34 +510,34 @@ bool ASTJsonExporter::visit(VariableDeclaration const& _node)
|
||||
if (m_inEvent)
|
||||
attributes.emplace_back("indexed", _node.isIndexed());
|
||||
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));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(ModifierDefinition const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("parameters", toJson(_node.parameterList())),
|
||||
make_pair("virtual", _node.markedVirtual()),
|
||||
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue)
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
std::make_pair("parameters", toJson(_node.parameterList())),
|
||||
std::make_pair("virtual", _node.markedVirtual()),
|
||||
std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||
std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue)
|
||||
};
|
||||
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));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(ModifierInvocation const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes{
|
||||
make_pair("modifierName", toJson(_node.name())),
|
||||
make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes{
|
||||
std::make_pair("modifierName", toJson(_node.name())),
|
||||
std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json::nullValue)
|
||||
};
|
||||
if (Declaration const* declaration = _node.name().annotation().referencedDeclaration)
|
||||
{
|
||||
@ -554,16 +553,16 @@ bool ASTJsonExporter::visit(ModifierInvocation const& _node)
|
||||
bool ASTJsonExporter::visit(EventDefinition const& _node)
|
||||
{
|
||||
m_inEvent = true;
|
||||
std::vector<pair<string, Json::Value>> _attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("parameters", toJson(_node.parameterList())),
|
||||
make_pair("anonymous", _node.isAnonymous())
|
||||
std::vector<std::pair<std::string, Json::Value>> _attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("parameters", toJson(_node.parameterList())),
|
||||
std::make_pair("anonymous", _node.isAnonymous())
|
||||
};
|
||||
if (m_stackState >= CompilerStack::State::AnalysisPerformed)
|
||||
if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
|
||||
_attributes.emplace_back(
|
||||
make_pair(
|
||||
std::make_pair(
|
||||
"eventSelector",
|
||||
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)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> _attributes = {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
make_pair("parameters", toJson(_node.parameterList()))
|
||||
std::vector<std::pair<std::string, Json::Value>> _attributes = {
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
|
||||
std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||
std::make_pair("parameters", toJson(_node.parameterList()))
|
||||
};
|
||||
if (m_stackState >= CompilerStack::State::AnalysisPerformed)
|
||||
_attributes.emplace_back(make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
|
||||
if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
|
||||
_attributes.emplace_back(std::make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
|
||||
|
||||
setJsonNode(_node, "ErrorDefinition", std::move(_attributes));
|
||||
return false;
|
||||
@ -589,13 +588,13 @@ bool ASTJsonExporter::visit(ErrorDefinition const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(ElementaryTypeName const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("name", _node.typeName().toString()),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("name", _node.typeName().toString()),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
};
|
||||
|
||||
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));
|
||||
return false;
|
||||
@ -604,9 +603,9 @@ bool ASTJsonExporter::visit(ElementaryTypeName const& _node)
|
||||
bool ASTJsonExporter::visit(UserDefinedTypeName const& _node)
|
||||
{
|
||||
setJsonNode(_node, "UserDefinedTypeName", {
|
||||
make_pair("pathNode", toJson(_node.pathNode())),
|
||||
make_pair("referencedDeclaration", idOrNull(_node.pathNode().annotation().referencedDeclaration)),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
std::make_pair("pathNode", toJson(_node.pathNode())),
|
||||
std::make_pair("referencedDeclaration", idOrNull(_node.pathNode().annotation().referencedDeclaration)),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -614,11 +613,11 @@ bool ASTJsonExporter::visit(UserDefinedTypeName const& _node)
|
||||
bool ASTJsonExporter::visit(FunctionTypeName const& _node)
|
||||
{
|
||||
setJsonNode(_node, "FunctionTypeName", {
|
||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||
make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
|
||||
make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
||||
std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||
std::make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
|
||||
std::make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -626,13 +625,13 @@ bool ASTJsonExporter::visit(FunctionTypeName const& _node)
|
||||
bool ASTJsonExporter::visit(Mapping const& _node)
|
||||
{
|
||||
setJsonNode(_node, "Mapping", {
|
||||
make_pair("keyType", toJson(_node.keyType())),
|
||||
make_pair("keyName", _node.keyName()),
|
||||
make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())),
|
||||
make_pair("valueType", toJson(_node.valueType())),
|
||||
make_pair("valueName", _node.valueName()),
|
||||
make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
std::make_pair("keyType", toJson(_node.keyType())),
|
||||
std::make_pair("keyName", _node.keyName()),
|
||||
std::make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())),
|
||||
std::make_pair("valueType", toJson(_node.valueType())),
|
||||
std::make_pair("valueName", _node.valueName()),
|
||||
std::make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -640,20 +639,20 @@ bool ASTJsonExporter::visit(Mapping const& _node)
|
||||
bool ASTJsonExporter::visit(ArrayTypeName const& _node)
|
||||
{
|
||||
setJsonNode(_node, "ArrayTypeName", {
|
||||
make_pair("baseType", toJson(_node.baseType())),
|
||||
make_pair("length", toJsonOrNull(_node.length())),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
std::make_pair("baseType", toJson(_node.baseType())),
|
||||
std::make_pair("length", toJsonOrNull(_node.length())),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
if (it.first)
|
||||
externalReferences.emplace_back(make_pair(
|
||||
externalReferences.emplace_back(std::make_pair(
|
||||
it.first->name.str(),
|
||||
inlineAssemblyIdentifierToJson(it)
|
||||
));
|
||||
@ -664,10 +663,10 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
|
||||
for (Json::Value& it: externalReferences | ranges::views::values)
|
||||
externalReferencesJson.append(std::move(it));
|
||||
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
|
||||
make_pair("externalReferences", std::move(externalReferencesJson)),
|
||||
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
|
||||
std::make_pair("externalReferences", std::move(externalReferencesJson)),
|
||||
std::make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
|
||||
};
|
||||
|
||||
if (_node.flags())
|
||||
@ -678,7 +677,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
|
||||
flags.append(*flag);
|
||||
else
|
||||
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));
|
||||
|
||||
@ -688,7 +687,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
|
||||
bool ASTJsonExporter::visit(Block const& _node)
|
||||
{
|
||||
setJsonNode(_node, _node.unchecked() ? "UncheckedBlock" : "Block", {
|
||||
make_pair("statements", toJson(_node.statements()))
|
||||
std::make_pair("statements", toJson(_node.statements()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -702,9 +701,9 @@ bool ASTJsonExporter::visit(PlaceholderStatement const& _node)
|
||||
bool ASTJsonExporter::visit(IfStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "IfStatement", {
|
||||
make_pair("condition", toJson(_node.condition())),
|
||||
make_pair("trueBody", toJson(_node.trueStatement())),
|
||||
make_pair("falseBody", toJsonOrNull(_node.falseStatement()))
|
||||
std::make_pair("condition", toJson(_node.condition())),
|
||||
std::make_pair("trueBody", toJson(_node.trueStatement())),
|
||||
std::make_pair("falseBody", toJsonOrNull(_node.falseStatement()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -712,9 +711,9 @@ bool ASTJsonExporter::visit(IfStatement const& _node)
|
||||
bool ASTJsonExporter::visit(TryCatchClause const& _node)
|
||||
{
|
||||
setJsonNode(_node, "TryCatchClause", {
|
||||
make_pair("errorName", _node.errorName()),
|
||||
make_pair("parameters", toJsonOrNull(_node.parameters())),
|
||||
make_pair("block", toJson(_node.block()))
|
||||
std::make_pair("errorName", _node.errorName()),
|
||||
std::make_pair("parameters", toJsonOrNull(_node.parameters())),
|
||||
std::make_pair("block", toJson(_node.block()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -722,8 +721,8 @@ bool ASTJsonExporter::visit(TryCatchClause const& _node)
|
||||
bool ASTJsonExporter::visit(TryStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "TryStatement", {
|
||||
make_pair("externalCall", toJson(_node.externalCall())),
|
||||
make_pair("clauses", toJson(_node.clauses()))
|
||||
std::make_pair("externalCall", toJson(_node.externalCall())),
|
||||
std::make_pair("clauses", toJson(_node.clauses()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -734,8 +733,8 @@ bool ASTJsonExporter::visit(WhileStatement const& _node)
|
||||
_node,
|
||||
_node.isDoWhile() ? "DoWhileStatement" : "WhileStatement",
|
||||
{
|
||||
make_pair("condition", toJson(_node.condition())),
|
||||
make_pair("body", toJson(_node.body()))
|
||||
std::make_pair("condition", toJson(_node.condition())),
|
||||
std::make_pair("body", toJson(_node.body()))
|
||||
}
|
||||
);
|
||||
return false;
|
||||
@ -744,10 +743,10 @@ bool ASTJsonExporter::visit(WhileStatement const& _node)
|
||||
bool ASTJsonExporter::visit(ForStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "ForStatement", {
|
||||
make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())),
|
||||
make_pair("condition", toJsonOrNull(_node.condition())),
|
||||
make_pair("loopExpression", toJsonOrNull(_node.loopExpression())),
|
||||
make_pair("body", toJson(_node.body()))
|
||||
std::make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())),
|
||||
std::make_pair("condition", toJsonOrNull(_node.condition())),
|
||||
std::make_pair("loopExpression", toJsonOrNull(_node.loopExpression())),
|
||||
std::make_pair("body", toJson(_node.body()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -767,8 +766,8 @@ bool ASTJsonExporter::visit(Break const& _node)
|
||||
bool ASTJsonExporter::visit(Return const& _node)
|
||||
{
|
||||
setJsonNode(_node, "Return", {
|
||||
make_pair("expression", toJsonOrNull(_node.expression())),
|
||||
make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters))
|
||||
std::make_pair("expression", toJsonOrNull(_node.expression())),
|
||||
std::make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -782,7 +781,7 @@ bool ASTJsonExporter::visit(Throw const& _node)
|
||||
bool ASTJsonExporter::visit(EmitStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "EmitStatement", {
|
||||
make_pair("eventCall", toJson(_node.eventCall()))
|
||||
std::make_pair("eventCall", toJson(_node.eventCall()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -790,7 +789,7 @@ bool ASTJsonExporter::visit(EmitStatement const& _node)
|
||||
bool ASTJsonExporter::visit(RevertStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "RevertStatement", {
|
||||
make_pair("errorCall", toJson(_node.errorCall()))
|
||||
std::make_pair("errorCall", toJson(_node.errorCall()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -801,9 +800,9 @@ bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node)
|
||||
for (auto const& v: _node.declarations())
|
||||
appendMove(varDecs, idOrNull(v.get()));
|
||||
setJsonNode(_node, "VariableDeclarationStatement", {
|
||||
make_pair("assignments", std::move(varDecs)),
|
||||
make_pair("declarations", toJson(_node.declarations())),
|
||||
make_pair("initialValue", toJsonOrNull(_node.initialValue()))
|
||||
std::make_pair("assignments", std::move(varDecs)),
|
||||
std::make_pair("declarations", toJson(_node.declarations())),
|
||||
std::make_pair("initialValue", toJsonOrNull(_node.initialValue()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -811,17 +810,17 @@ bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node)
|
||||
bool ASTJsonExporter::visit(ExpressionStatement const& _node)
|
||||
{
|
||||
setJsonNode(_node, "ExpressionStatement", {
|
||||
make_pair("expression", toJson(_node.expression()))
|
||||
std::make_pair("expression", toJson(_node.expression()))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(Conditional const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("condition", toJson(_node.condition())),
|
||||
make_pair("trueExpression", toJson(_node.trueExpression())),
|
||||
make_pair("falseExpression", toJson(_node.falseExpression()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("condition", toJson(_node.condition())),
|
||||
std::make_pair("trueExpression", toJson(_node.trueExpression())),
|
||||
std::make_pair("falseExpression", toJson(_node.falseExpression()))
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "Conditional", std::move(attributes));
|
||||
@ -830,10 +829,10 @@ bool ASTJsonExporter::visit(Conditional const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(Assignment const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("operator", TokenTraits::toString(_node.assignmentOperator())),
|
||||
make_pair("leftHandSide", toJson(_node.leftHandSide())),
|
||||
make_pair("rightHandSide", toJson(_node.rightHandSide()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("operator", TokenTraits::toString(_node.assignmentOperator())),
|
||||
std::make_pair("leftHandSide", toJson(_node.leftHandSide())),
|
||||
std::make_pair("rightHandSide", toJson(_node.rightHandSide()))
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "Assignment", std::move(attributes));
|
||||
@ -842,9 +841,9 @@ bool ASTJsonExporter::visit(Assignment const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(TupleExpression const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("isInlineArray", Json::Value(_node.isInlineArray())),
|
||||
make_pair("components", toJson(_node.components())),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("isInlineArray", Json::Value(_node.isInlineArray())),
|
||||
std::make_pair("components", toJson(_node.components())),
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "TupleExpression", std::move(attributes));
|
||||
@ -853,10 +852,10 @@ bool ASTJsonExporter::visit(TupleExpression const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(UnaryOperation const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("prefix", _node.isPrefixOperation()),
|
||||
make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
||||
make_pair("subExpression", toJson(_node.subExpression()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("prefix", _node.isPrefixOperation()),
|
||||
std::make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
||||
std::make_pair("subExpression", toJson(_node.subExpression()))
|
||||
};
|
||||
// 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)
|
||||
@ -868,11 +867,11 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(BinaryOperation const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
||||
make_pair("leftExpression", toJson(_node.leftExpression())),
|
||||
make_pair("rightExpression", toJson(_node.rightExpression())),
|
||||
make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
||||
std::make_pair("leftExpression", toJson(_node.leftExpression())),
|
||||
std::make_pair("rightExpression", toJson(_node.rightExpression())),
|
||||
std::make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
|
||||
};
|
||||
// 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)
|
||||
@ -887,12 +886,12 @@ bool ASTJsonExporter::visit(FunctionCall const& _node)
|
||||
Json::Value names(Json::arrayValue);
|
||||
for (auto const& name: _node.names())
|
||||
names.append(Json::Value(*name));
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("expression", toJson(_node.expression())),
|
||||
make_pair("names", std::move(names)),
|
||||
make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
|
||||
make_pair("arguments", toJson(_node.arguments())),
|
||||
make_pair("tryCall", _node.annotation().tryCall)
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("expression", toJson(_node.expression())),
|
||||
std::make_pair("names", std::move(names)),
|
||||
std::make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
|
||||
std::make_pair("arguments", toJson(_node.arguments())),
|
||||
std::make_pair("tryCall", _node.annotation().tryCall)
|
||||
};
|
||||
|
||||
if (_node.annotation().kind.set())
|
||||
@ -912,10 +911,10 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
|
||||
for (auto const& name: _node.names())
|
||||
names.append(Json::Value(*name));
|
||||
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("expression", toJson(_node.expression())),
|
||||
make_pair("names", std::move(names)),
|
||||
make_pair("options", toJson(_node.options())),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("expression", toJson(_node.expression())),
|
||||
std::make_pair("names", std::move(names)),
|
||||
std::make_pair("options", toJson(_node.options())),
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
|
||||
@ -925,8 +924,8 @@ bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(NewExpression const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("typeName", toJson(_node.typeName()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("typeName", toJson(_node.typeName()))
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "NewExpression", std::move(attributes));
|
||||
@ -935,11 +934,11 @@ bool ASTJsonExporter::visit(NewExpression const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(MemberAccess const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("memberName", _node.memberName()),
|
||||
make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))),
|
||||
make_pair("expression", toJson(_node.expression())),
|
||||
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("memberName", _node.memberName()),
|
||||
std::make_pair("memberLocation", Json::Value(sourceLocationToString(_node.memberLocation()))),
|
||||
std::make_pair("expression", toJson(_node.expression())),
|
||||
std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "MemberAccess", std::move(attributes));
|
||||
@ -948,9 +947,9 @@ bool ASTJsonExporter::visit(MemberAccess const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(IndexAccess const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("baseExpression", toJson(_node.baseExpression())),
|
||||
make_pair("indexExpression", toJsonOrNull(_node.indexExpression())),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("baseExpression", toJson(_node.baseExpression())),
|
||||
std::make_pair("indexExpression", toJsonOrNull(_node.indexExpression())),
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "IndexAccess", std::move(attributes));
|
||||
@ -959,10 +958,10 @@ bool ASTJsonExporter::visit(IndexAccess const& _node)
|
||||
|
||||
bool ASTJsonExporter::visit(IndexRangeAccess const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("baseExpression", toJson(_node.baseExpression())),
|
||||
make_pair("startExpression", toJsonOrNull(_node.startExpression())),
|
||||
make_pair("endExpression", toJsonOrNull(_node.endExpression())),
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("baseExpression", toJson(_node.baseExpression())),
|
||||
std::make_pair("startExpression", toJsonOrNull(_node.startExpression())),
|
||||
std::make_pair("endExpression", toJsonOrNull(_node.endExpression())),
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "IndexRangeAccess", std::move(attributes));
|
||||
@ -975,19 +974,19 @@ bool ASTJsonExporter::visit(Identifier const& _node)
|
||||
for (auto const& dec: _node.annotation().overloadedDeclarations)
|
||||
overloads.append(nodeId(*dec));
|
||||
setJsonNode(_node, "Identifier", {
|
||||
make_pair("name", _node.name()),
|
||||
make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
|
||||
make_pair("overloadedDeclarations", overloads),
|
||||
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
|
||||
make_pair("argumentTypes", typePointerToJson(_node.annotation().arguments))
|
||||
std::make_pair("name", _node.name()),
|
||||
std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
|
||||
std::make_pair("overloadedDeclarations", overloads),
|
||||
std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
|
||||
std::make_pair("argumentTypes", typePointerToJson(_node.annotation().arguments))
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node)
|
||||
{
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("typeName", toJson(_node.type()))
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("typeName", toJson(_node.type()))
|
||||
};
|
||||
appendExpressionAttributes(attributes, _node.annotation());
|
||||
setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes));
|
||||
@ -1000,11 +999,11 @@ bool ASTJsonExporter::visit(Literal const& _node)
|
||||
if (!util::validateUTF8(_node.value()))
|
||||
value = Json::nullValue;
|
||||
Token subdenomination = Token(_node.subDenomination());
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("kind", literalTokenKind(_node.token())),
|
||||
make_pair("value", value),
|
||||
make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
|
||||
make_pair(
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("kind", literalTokenKind(_node.token())),
|
||||
std::make_pair("value", value),
|
||||
std::make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
|
||||
std::make_pair(
|
||||
"subdenomination",
|
||||
subdenomination == Token::Illegal ?
|
||||
Json::nullValue :
|
||||
@ -1019,8 +1018,8 @@ bool ASTJsonExporter::visit(Literal const& _node)
|
||||
bool ASTJsonExporter::visit(StructuredDocumentation const& _node)
|
||||
{
|
||||
Json::Value text{*_node.text()};
|
||||
std::vector<pair<string, Json::Value>> attributes = {
|
||||
make_pair("text", text)
|
||||
std::vector<std::pair<std::string, Json::Value>> attributes = {
|
||||
std::make_pair("text", text)
|
||||
};
|
||||
setJsonNode(_node, "StructuredDocumentation", std::move(attributes));
|
||||
return false;
|
||||
@ -1033,7 +1032,7 @@ void ASTJsonExporter::endVisit(EventDefinition const&)
|
||||
m_inEvent = false;
|
||||
}
|
||||
|
||||
string ASTJsonExporter::location(VariableDeclaration::Location _location)
|
||||
std::string ASTJsonExporter::location(VariableDeclaration::Location _location)
|
||||
{
|
||||
switch (_location)
|
||||
{
|
||||
@ -1050,7 +1049,7 @@ string ASTJsonExporter::location(VariableDeclaration::Location _location)
|
||||
return {};
|
||||
}
|
||||
|
||||
string ASTJsonExporter::contractKind(ContractKind _kind)
|
||||
std::string ASTJsonExporter::contractKind(ContractKind _kind)
|
||||
{
|
||||
switch (_kind)
|
||||
{
|
||||
@ -1066,7 +1065,7 @@ string ASTJsonExporter::contractKind(ContractKind _kind)
|
||||
return {};
|
||||
}
|
||||
|
||||
string ASTJsonExporter::functionCallKind(FunctionCallKind _kind)
|
||||
std::string ASTJsonExporter::functionCallKind(FunctionCallKind _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)
|
||||
{
|
||||
@ -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";
|
||||
}
|
||||
|
||||
string ASTJsonExporter::type(VariableDeclaration const& _varDecl)
|
||||
std::string ASTJsonExporter::type(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
return _varDecl.annotation().type ? _varDecl.annotation().type->toString() : "Unknown";
|
||||
}
|
||||
|
||||
@ -37,8 +37,6 @@
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
@ -50,16 +48,16 @@ ASTPointer<T> ASTJsonImporter::nullOrCast(Json::Value const& _json)
|
||||
if (_json.isNull())
|
||||
return nullptr;
|
||||
else
|
||||
return dynamic_pointer_cast<T>(convertJsonToASTNode(_json));
|
||||
return std::dynamic_pointer_cast<T>(convertJsonToASTNode(_json));
|
||||
}
|
||||
|
||||
|
||||
// ============ 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)
|
||||
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)
|
||||
{
|
||||
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!");
|
||||
|
||||
auto n = make_shared<T>(
|
||||
auto n = std::make_shared<T>(
|
||||
id,
|
||||
createSourceLocation(_node),
|
||||
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);
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
@ -107,7 +105,7 @@ optional<vector<SourceLocation>> ASTJsonImporter::createSourceLocations(Json::Va
|
||||
return locations;
|
||||
}
|
||||
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _node)
|
||||
@ -134,7 +132,7 @@ SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json::Value const&
|
||||
template<class T>
|
||||
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");
|
||||
return ret;
|
||||
}
|
||||
@ -143,7 +141,7 @@ ASTPointer<T> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node)
|
||||
ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _json)
|
||||
{
|
||||
astAssert(_json["nodeType"].isString() && _json.isMember("id"), "JSON-Node needs to have 'nodeType' and 'id' fields.");
|
||||
string nodeType = _json["nodeType"].asString();
|
||||
std::string nodeType = _json["nodeType"].asString();
|
||||
if (nodeType == "PragmaDirective")
|
||||
return createPragmaDirective(_json);
|
||||
if (nodeType == "ImportDirective")
|
||||
@ -265,9 +263,9 @@ ASTPointer<ASTNode> ASTJsonImporter::convertJsonToASTNode(Json::Value const& _js
|
||||
|
||||
// ============ functions to instantiate the AST-Nodes from Json-Nodes ==============
|
||||
|
||||
ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _node, 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())
|
||||
license = _node["license"].asString();
|
||||
|
||||
@ -275,7 +273,7 @@ ASTPointer<SourceUnit> ASTJsonImporter::createSourceUnit(Json::Value const& _nod
|
||||
if (_node.isMember("experimentalSolidity") && !_node["experimentalSolidity"].isNull())
|
||||
experimentalSolidity = _node["experimentalSolidity"].asBool();
|
||||
|
||||
vector<ASTPointer<ASTNode>> nodes;
|
||||
std::vector<ASTPointer<ASTNode>> nodes;
|
||||
for (auto& child: member(_node, "nodes"))
|
||||
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)
|
||||
{
|
||||
vector<Token> tokens;
|
||||
vector<ASTString> literals;
|
||||
std::vector<Token> tokens;
|
||||
std::vector<ASTString> literals;
|
||||
for (auto const& lit: member(_node, "literals"))
|
||||
{
|
||||
string l = lit.asString();
|
||||
std::string l = lit.asString();
|
||||
literals.push_back(l);
|
||||
tokens.push_back(scanSingleToken(l));
|
||||
}
|
||||
@ -309,7 +307,7 @@ ASTPointer<ImportDirective> ASTJsonImporter::createImportDirective(Json::Value c
|
||||
|
||||
symbolAliases.push_back({
|
||||
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"])}
|
||||
);
|
||||
}
|
||||
@ -343,7 +341,7 @@ ASTPointer<ContractDefinition> ASTJsonImporter::createContractDefinition(Json::V
|
||||
|
||||
return createASTNode<ContractDefinition>(
|
||||
_node,
|
||||
make_shared<ASTString>(_node["name"].asString()),
|
||||
std::make_shared<ASTString>(_node["name"].asString()),
|
||||
createNameSourceLocation(_node),
|
||||
_node["documentation"].isNull() ? nullptr : createDocumentation(member(_node, "documentation")),
|
||||
baseContracts,
|
||||
@ -357,13 +355,13 @@ ASTPointer<IdentifierPath> ASTJsonImporter::createIdentifierPath(Json::Value con
|
||||
{
|
||||
astAssert(_node["name"].isString(), "Expected 'name' to be a string!");
|
||||
|
||||
vector<ASTString> namePath;
|
||||
vector<SourceLocation> namePathLocations;
|
||||
vector<string> strs;
|
||||
string nameString = member(_node, "name").asString();
|
||||
std::vector<ASTString> namePath;
|
||||
std::vector<SourceLocation> namePathLocations;
|
||||
std::vector<std::string> strs;
|
||||
std::string nameString = member(_node, "name").asString();
|
||||
boost::algorithm::split(strs, nameString, boost::is_any_of("."));
|
||||
astAssert(!strs.empty(), "Expected at least one element in IdentifierPath.");
|
||||
for (string s: strs)
|
||||
for (std::string s: strs)
|
||||
{
|
||||
astAssert(!s.empty(), "Expected non-empty string for IdentifierPath element.");
|
||||
namePath.emplace_back(s);
|
||||
@ -395,20 +393,20 @@ ASTPointer<InheritanceSpecifier> ASTJsonImporter::createInheritanceSpecifier(Jso
|
||||
return createASTNode<InheritanceSpecifier>(
|
||||
_node,
|
||||
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)
|
||||
{
|
||||
vector<ASTPointer<IdentifierPath>> functions;
|
||||
vector<optional<Token>> operators;
|
||||
std::vector<ASTPointer<IdentifierPath>> functions;
|
||||
std::vector<std::optional<Token>> operators;
|
||||
if (_node.isMember("libraryName"))
|
||||
{
|
||||
astAssert(!_node["libraryName"].isArray());
|
||||
astAssert(!_node["libraryName"]["operator"]);
|
||||
functions.emplace_back(createIdentifierPath(_node["libraryName"]));
|
||||
operators.emplace_back(nullopt);
|
||||
operators.emplace_back(std::nullopt);
|
||||
}
|
||||
else if (_node.isMember("functionList"))
|
||||
for (Json::Value const& function: _node["functionList"])
|
||||
@ -419,7 +417,7 @@ ASTPointer<UsingForDirective> ASTJsonImporter::createUsingForDirective(Json::Val
|
||||
astAssert(!function.isMember("definition"));
|
||||
|
||||
functions.emplace_back(createIdentifierPath(function["function"]));
|
||||
operators.emplace_back(nullopt);
|
||||
operators.emplace_back(std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -520,7 +518,7 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
|
||||
|
||||
Token kind;
|
||||
bool freeFunction = false;
|
||||
string kindStr = member(_node, "kind").asString();
|
||||
std::string kindStr = member(_node, "kind").asString();
|
||||
|
||||
if (kindStr == "constructor")
|
||||
kind = Token::Constructor;
|
||||
@ -572,7 +570,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
|
||||
|
||||
VariableDeclaration::Mutability mutability{};
|
||||
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")
|
||||
{
|
||||
mutability = VariableDeclaration::Mutability::Constant;
|
||||
@ -592,7 +590,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
|
||||
return createASTNode<VariableDeclaration>(
|
||||
_node,
|
||||
nullOrCast<TypeName>(member(_node, "typeName")),
|
||||
make_shared<ASTString>(member(_node, "name").asString()),
|
||||
std::make_shared<ASTString>(member(_node, "name").asString()),
|
||||
createNameSourceLocation(_node),
|
||||
nullOrCast<Expression>(member(_node, "value")),
|
||||
visibility(_node),
|
||||
@ -626,7 +624,7 @@ ASTPointer<ModifierInvocation> ASTJsonImporter::createModifierInvocation(Json::V
|
||||
return createASTNode<ModifierInvocation>(
|
||||
_node,
|
||||
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!");
|
||||
|
||||
string name = member(_node, "name").asString();
|
||||
std::string name = member(_node, "name").asString();
|
||||
Token token;
|
||||
tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name);
|
||||
std::tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(name);
|
||||
ElementaryTypeNameToken elem(token, firstNum, secondNum);
|
||||
|
||||
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!");
|
||||
|
||||
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
|
||||
ASTPointer<vector<ASTPointer<ASTString>>> flags;
|
||||
ASTPointer<std::vector<ASTPointer<ASTString>>> 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"];
|
||||
astAssert(flagsNode.isArray(), "Assembly flags must be an array.");
|
||||
for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i)
|
||||
{
|
||||
astAssert(flagsNode[i].isString(), "Assembly flag must be a string.");
|
||||
flags->emplace_back(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>(
|
||||
_node,
|
||||
nullOrASTString(_node, "documentation"),
|
||||
@ -787,7 +785,7 @@ ASTPointer<TryCatchClause> ASTJsonImporter::createTryCatchClause(Json::Value con
|
||||
|
||||
ASTPointer<TryStatement> ASTJsonImporter::createTryStatement(Json::Value const& _node)
|
||||
{
|
||||
vector<ASTPointer<TryCatchClause>> clauses;
|
||||
std::vector<ASTPointer<TryCatchClause>> clauses;
|
||||
|
||||
for (auto& param: _node["clauses"])
|
||||
clauses.emplace_back(createTryCatchClause(param));
|
||||
@ -957,10 +955,10 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
|
||||
for (auto& name: member(_node, "names"))
|
||||
{
|
||||
astAssert(name.isString(), "Expected 'names' members to be strings!");
|
||||
names.push_back(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>(
|
||||
_node,
|
||||
@ -969,7 +967,7 @@ ASTPointer<FunctionCall> ASTJsonImporter::createFunctionCall(Json::Value const&
|
||||
names,
|
||||
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"))
|
||||
{
|
||||
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>(
|
||||
@ -1049,14 +1047,14 @@ ASTPointer<ElementaryTypeNameExpression> ASTJsonImporter::createElementaryTypeNa
|
||||
|
||||
ASTPointer<ASTNode> ASTJsonImporter::createLiteral(Json::Value const& _node)
|
||||
{
|
||||
static string const valStr = "value";
|
||||
static string const hexValStr = "hexValue";
|
||||
static std::string const valStr = "value";
|
||||
static std::string const hexValStr = "hexValue";
|
||||
|
||||
astAssert(member(_node, valStr).isString() || member(_node, hexValStr).isString(), "Literal-value is unset.");
|
||||
|
||||
ASTPointer<ASTString> value = _node.isMember(hexValStr) ?
|
||||
make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].asString()))) :
|
||||
make_shared<ASTString>(_node[valStr].asString());
|
||||
std::make_shared<ASTString>(util::asString(util::fromHex(_node[hexValStr].asString()))) :
|
||||
std::make_shared<ASTString>(_node[valStr].asString());
|
||||
|
||||
return createASTNode<Literal>(
|
||||
_node,
|
||||
@ -1068,19 +1066,19 @@ ASTPointer<ASTNode> ASTJsonImporter::createLiteral(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");
|
||||
|
||||
return createASTNode<StructuredDocumentation>(
|
||||
_node,
|
||||
make_shared<ASTString>(_node[textString].asString())
|
||||
std::make_shared<ASTString>(_node[textString].asString())
|
||||
);
|
||||
}
|
||||
|
||||
// ===== 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))
|
||||
return Json::nullValue;
|
||||
@ -1095,19 +1093,19 @@ Token ASTJsonImporter::scanSingleToken(Json::Value const& _node)
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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");
|
||||
astAssert(visibility.isString(), "'visibility' expected to be a string.");
|
||||
|
||||
string const visibilityStr = visibility.asString();
|
||||
std::string const visibilityStr = visibility.asString();
|
||||
|
||||
if (visibilityStr == "default")
|
||||
return Visibility::Default;
|
||||
@ -1180,7 +1178,7 @@ VariableDeclaration::Location ASTJsonImporter::location(Json::Value const& _node
|
||||
Json::Value storageLoc = member(_node, "storageLocation");
|
||||
astAssert(storageLoc.isString(), "'storageLocation' expected to be a string.");
|
||||
|
||||
string const storageLocStr = storageLoc.asString();
|
||||
std::string const storageLocStr = storageLoc.asString();
|
||||
|
||||
if (storageLocStr == "default")
|
||||
return VariableDeclaration::Location::Unspecified;
|
||||
@ -1206,7 +1204,7 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
|
||||
|
||||
astAssert(subDen.isString(), "'subDenomination' expected to be string.");
|
||||
|
||||
string const subDenStr = subDen.asString();
|
||||
std::string const subDenStr = subDen.asString();
|
||||
|
||||
if (subDenStr == "wei")
|
||||
return Literal::SubDenomination::Wei;
|
||||
@ -1236,7 +1234,7 @@ Literal::SubDenomination ASTJsonImporter::subdenomination(Json::Value const& _no
|
||||
StateMutability ASTJsonImporter::stateMutability(Json::Value const& _node)
|
||||
{
|
||||
astAssert(member(_node, "stateMutability").isString(), "StateMutability' expected to be string.");
|
||||
string const mutabilityStr = member(_node, "stateMutability").asString();
|
||||
std::string const mutabilityStr = member(_node, "stateMutability").asString();
|
||||
|
||||
if (mutabilityStr == "pure")
|
||||
return StateMutability::Pure;
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
|
||||
#include <libsolidity/ast/CallGraph.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
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())
|
||||
return _lhs.index() < _rhs.index();
|
||||
|
||||
if (holds_alternative<SpecialNode>(_lhs))
|
||||
return get<SpecialNode>(_lhs) < get<SpecialNode>(_rhs);
|
||||
return get<CallableDeclaration const*>(_lhs)->id() < get<CallableDeclaration const*>(_rhs)->id();
|
||||
if (std::holds_alternative<SpecialNode>(_lhs))
|
||||
return std::get<SpecialNode>(_lhs) < std::get<SpecialNode>(_rhs);
|
||||
return std::get<CallableDeclaration const*>(_lhs)->id() < std::get<CallableDeclaration const*>(_rhs)->id();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::util;
|
||||
@ -31,126 +30,126 @@ InaccessibleDynamicType const TypeProvider::m_inaccessibleDynamic{};
|
||||
|
||||
/// The string and bytes unique_ptrs are initialized when they are first used because
|
||||
/// they rely on `byte` being available which we cannot guarantee in the static init context.
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesStorage;
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesMemory;
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesCalldata;
|
||||
unique_ptr<ArrayType> TypeProvider::m_stringStorage;
|
||||
unique_ptr<ArrayType> TypeProvider::m_stringMemory;
|
||||
std::unique_ptr<ArrayType> TypeProvider::m_bytesStorage;
|
||||
std::unique_ptr<ArrayType> TypeProvider::m_bytesMemory;
|
||||
std::unique_ptr<ArrayType> TypeProvider::m_bytesCalldata;
|
||||
std::unique_ptr<ArrayType> TypeProvider::m_stringStorage;
|
||||
std::unique_ptr<ArrayType> TypeProvider::m_stringMemory;
|
||||
|
||||
TupleType const TypeProvider::m_emptyTuple{};
|
||||
AddressType const TypeProvider::m_payableAddress{StateMutability::Payable};
|
||||
AddressType const TypeProvider::m_address{StateMutability::NonPayable};
|
||||
|
||||
array<unique_ptr<IntegerType>, 32> const TypeProvider::m_intM{{
|
||||
{make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Signed)},
|
||||
{make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Signed)}
|
||||
std::array<std::unique_ptr<IntegerType>, 32> const TypeProvider::m_intM{{
|
||||
{std::make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Signed)},
|
||||
{std::make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Signed)}
|
||||
}};
|
||||
|
||||
array<unique_ptr<IntegerType>, 32> const TypeProvider::m_uintM{{
|
||||
{make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Unsigned)},
|
||||
{make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Unsigned)}
|
||||
std::array<std::unique_ptr<IntegerType>, 32> const TypeProvider::m_uintM{{
|
||||
{std::make_unique<IntegerType>(8 * 1, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 2, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 3, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 4, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 5, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 6, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 7, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 8, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 9, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 10, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 11, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 12, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 13, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 14, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 15, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 16, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 17, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 18, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 19, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 20, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 21, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 22, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 23, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 24, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 25, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 26, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 27, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 28, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 29, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 30, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 31, IntegerType::Modifier::Unsigned)},
|
||||
{std::make_unique<IntegerType>(8 * 32, IntegerType::Modifier::Unsigned)}
|
||||
}};
|
||||
|
||||
array<unique_ptr<FixedBytesType>, 32> const TypeProvider::m_bytesM{{
|
||||
{make_unique<FixedBytesType>(1)},
|
||||
{make_unique<FixedBytesType>(2)},
|
||||
{make_unique<FixedBytesType>(3)},
|
||||
{make_unique<FixedBytesType>(4)},
|
||||
{make_unique<FixedBytesType>(5)},
|
||||
{make_unique<FixedBytesType>(6)},
|
||||
{make_unique<FixedBytesType>(7)},
|
||||
{make_unique<FixedBytesType>(8)},
|
||||
{make_unique<FixedBytesType>(9)},
|
||||
{make_unique<FixedBytesType>(10)},
|
||||
{make_unique<FixedBytesType>(11)},
|
||||
{make_unique<FixedBytesType>(12)},
|
||||
{make_unique<FixedBytesType>(13)},
|
||||
{make_unique<FixedBytesType>(14)},
|
||||
{make_unique<FixedBytesType>(15)},
|
||||
{make_unique<FixedBytesType>(16)},
|
||||
{make_unique<FixedBytesType>(17)},
|
||||
{make_unique<FixedBytesType>(18)},
|
||||
{make_unique<FixedBytesType>(19)},
|
||||
{make_unique<FixedBytesType>(20)},
|
||||
{make_unique<FixedBytesType>(21)},
|
||||
{make_unique<FixedBytesType>(22)},
|
||||
{make_unique<FixedBytesType>(23)},
|
||||
{make_unique<FixedBytesType>(24)},
|
||||
{make_unique<FixedBytesType>(25)},
|
||||
{make_unique<FixedBytesType>(26)},
|
||||
{make_unique<FixedBytesType>(27)},
|
||||
{make_unique<FixedBytesType>(28)},
|
||||
{make_unique<FixedBytesType>(29)},
|
||||
{make_unique<FixedBytesType>(30)},
|
||||
{make_unique<FixedBytesType>(31)},
|
||||
{make_unique<FixedBytesType>(32)}
|
||||
std::array<std::unique_ptr<FixedBytesType>, 32> const TypeProvider::m_bytesM{{
|
||||
{std::make_unique<FixedBytesType>(1)},
|
||||
{std::make_unique<FixedBytesType>(2)},
|
||||
{std::make_unique<FixedBytesType>(3)},
|
||||
{std::make_unique<FixedBytesType>(4)},
|
||||
{std::make_unique<FixedBytesType>(5)},
|
||||
{std::make_unique<FixedBytesType>(6)},
|
||||
{std::make_unique<FixedBytesType>(7)},
|
||||
{std::make_unique<FixedBytesType>(8)},
|
||||
{std::make_unique<FixedBytesType>(9)},
|
||||
{std::make_unique<FixedBytesType>(10)},
|
||||
{std::make_unique<FixedBytesType>(11)},
|
||||
{std::make_unique<FixedBytesType>(12)},
|
||||
{std::make_unique<FixedBytesType>(13)},
|
||||
{std::make_unique<FixedBytesType>(14)},
|
||||
{std::make_unique<FixedBytesType>(15)},
|
||||
{std::make_unique<FixedBytesType>(16)},
|
||||
{std::make_unique<FixedBytesType>(17)},
|
||||
{std::make_unique<FixedBytesType>(18)},
|
||||
{std::make_unique<FixedBytesType>(19)},
|
||||
{std::make_unique<FixedBytesType>(20)},
|
||||
{std::make_unique<FixedBytesType>(21)},
|
||||
{std::make_unique<FixedBytesType>(22)},
|
||||
{std::make_unique<FixedBytesType>(23)},
|
||||
{std::make_unique<FixedBytesType>(24)},
|
||||
{std::make_unique<FixedBytesType>(25)},
|
||||
{std::make_unique<FixedBytesType>(26)},
|
||||
{std::make_unique<FixedBytesType>(27)},
|
||||
{std::make_unique<FixedBytesType>(28)},
|
||||
{std::make_unique<FixedBytesType>(29)},
|
||||
{std::make_unique<FixedBytesType>(30)},
|
||||
{std::make_unique<FixedBytesType>(31)},
|
||||
{std::make_unique<FixedBytesType>(32)}
|
||||
}};
|
||||
|
||||
array<unique_ptr<MagicType>, 4> const TypeProvider::m_magics{{
|
||||
{make_unique<MagicType>(MagicType::Kind::Block)},
|
||||
{make_unique<MagicType>(MagicType::Kind::Message)},
|
||||
{make_unique<MagicType>(MagicType::Kind::Transaction)},
|
||||
{make_unique<MagicType>(MagicType::Kind::ABI)}
|
||||
std::array<std::unique_ptr<MagicType>, 4> const TypeProvider::m_magics{{
|
||||
{std::make_unique<MagicType>(MagicType::Kind::Block)},
|
||||
{std::make_unique<MagicType>(MagicType::Kind::Message)},
|
||||
{std::make_unique<MagicType>(MagicType::Kind::Transaction)},
|
||||
{std::make_unique<MagicType>(MagicType::Kind::ABI)}
|
||||
// MetaType is stored separately
|
||||
}};
|
||||
|
||||
@ -160,7 +159,7 @@ inline void clearCache(Type const& type)
|
||||
}
|
||||
|
||||
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.
|
||||
if (type)
|
||||
@ -200,7 +199,7 @@ void TypeProvider::reset()
|
||||
template <typename T, typename... 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());
|
||||
}
|
||||
|
||||
@ -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(" "));
|
||||
solAssert(nameParts.size() == 1 || nameParts.size() == 2, "Cannot parse elementary type: " + _name);
|
||||
|
||||
Token token;
|
||||
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));
|
||||
if (auto* ref = dynamic_cast<ReferenceType const*>(t))
|
||||
@ -307,35 +306,35 @@ Type const* TypeProvider::fromElementaryTypeName(string const& _name)
|
||||
ArrayType const* TypeProvider::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();
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::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();
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::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();
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::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();
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::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();
|
||||
}
|
||||
|
||||
@ -376,30 +375,30 @@ RationalNumberType const* TypeProvider::rationalNumber(Literal const& _literal)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StringLiteralType const* TypeProvider::stringLiteral(string const& literal)
|
||||
StringLiteralType const* TypeProvider::stringLiteral(std::string const& literal)
|
||||
{
|
||||
auto i = instance().m_stringLiteralTypes.find(literal);
|
||||
if (i != instance().m_stringLiteralTypes.end())
|
||||
return i->second.get();
|
||||
else
|
||||
return instance().m_stringLiteralTypes.emplace(literal, 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)
|
||||
{
|
||||
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())
|
||||
return i->second.get();
|
||||
|
||||
return map.emplace(
|
||||
make_pair(m, n),
|
||||
make_unique<FixedPointType>(m, n, _modifier)
|
||||
std::make_pair(m, n),
|
||||
std::make_unique<FixedPointType>(m, n, _modifier)
|
||||
).first->second.get();
|
||||
}
|
||||
|
||||
TupleType const* TypeProvider::tuple(vector<Type const*> members)
|
||||
TupleType const* TypeProvider::tuple(std::vector<Type const*> members)
|
||||
{
|
||||
if (members.empty())
|
||||
return &m_emptyTuple;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -30,12 +30,11 @@
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
string ABIFunctions::tupleEncoder(
|
||||
std::string ABIFunctions::tupleEncoder(
|
||||
TypePointers const& _givenTypes,
|
||||
TypePointers _targetTypes,
|
||||
bool _encodeAsLibraryTypes,
|
||||
@ -56,7 +55,7 @@ string ABIFunctions::tupleEncoder(
|
||||
solAssert(t, "");
|
||||
}
|
||||
|
||||
string functionName = string("abi_encode_tuple_");
|
||||
std::string functionName = std::string("abi_encode_tuple_");
|
||||
for (auto const& t: _givenTypes)
|
||||
functionName += t->identifier() + "_";
|
||||
functionName += "_to_";
|
||||
@ -76,8 +75,8 @@ string ABIFunctions::tupleEncoder(
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
size_t const headSize_ = headSize(_targetTypes);
|
||||
templ("headSize", to_string(headSize_));
|
||||
string encodeElements;
|
||||
templ("headSize", std::to_string(headSize_));
|
||||
std::string encodeElements;
|
||||
size_t headPos = 0;
|
||||
size_t stackPos = 0;
|
||||
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||
@ -88,24 +87,24 @@ string ABIFunctions::tupleEncoder(
|
||||
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
|
||||
Whiskers elementTempl(
|
||||
dynamic ?
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
mstore(add(headStart, <pos>), sub(tail, headStart))
|
||||
tail := <abiEncode>(<values> tail)
|
||||
)") :
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
<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("pos", to_string(headPos));
|
||||
elementTempl("pos", std::to_string(headPos));
|
||||
elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options));
|
||||
encodeElements += elementTempl.render();
|
||||
headPos += _targetTypes[i]->calldataHeadSize();
|
||||
stackPos += sizeOnStack;
|
||||
}
|
||||
solAssert(headPos == headSize_, "");
|
||||
string valueParams =
|
||||
std::string valueParams =
|
||||
_reversed ?
|
||||
suffixedVariableNameList("value", stackPos, 0) :
|
||||
suffixedVariableNameList("value", 0, stackPos);
|
||||
@ -116,7 +115,7 @@ string ABIFunctions::tupleEncoder(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::tupleEncoderPacked(
|
||||
std::string ABIFunctions::tupleEncoderPacked(
|
||||
TypePointers const& _givenTypes,
|
||||
TypePointers _targetTypes,
|
||||
bool _reversed
|
||||
@ -135,7 +134,7 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
solAssert(t, "");
|
||||
}
|
||||
|
||||
string functionName = string("abi_encode_tuple_packed_");
|
||||
std::string functionName = std::string("abi_encode_tuple_packed_");
|
||||
for (auto const& t: _givenTypes)
|
||||
functionName += t->identifier() + "_";
|
||||
functionName += "_to_";
|
||||
@ -154,7 +153,7 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
string encodeElements;
|
||||
std::string encodeElements;
|
||||
size_t stackPos = 0;
|
||||
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||
{
|
||||
@ -164,23 +163,23 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
|
||||
Whiskers elementTempl(
|
||||
dynamic ?
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
pos := <abiEncode>(<values> pos)
|
||||
)") :
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
<abiEncode>(<values> pos)
|
||||
pos := add(pos, <calldataEncodedSize>)
|
||||
)")
|
||||
);
|
||||
string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
|
||||
std::string values = suffixedVariableNameList("value", stackPos, stackPos + sizeOnStack);
|
||||
elementTempl("values", values.empty() ? "" : values + ", ");
|
||||
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));
|
||||
encodeElements += elementTempl.render();
|
||||
stackPos += sizeOnStack;
|
||||
}
|
||||
string valueParams =
|
||||
std::string valueParams =
|
||||
_reversed ?
|
||||
suffixedVariableNameList("value", stackPos, 0) :
|
||||
suffixedVariableNameList("value", 0, stackPos);
|
||||
@ -190,9 +189,9 @@ string ABIFunctions::tupleEncoderPacked(
|
||||
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)
|
||||
functionName += t->identifier();
|
||||
if (_fromMemory)
|
||||
@ -211,10 +210,10 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short"));
|
||||
templ("minimumSize", to_string(headSize(decodingTypes)));
|
||||
templ("minimumSize", std::to_string(headSize(decodingTypes)));
|
||||
|
||||
string decodeElements;
|
||||
vector<string> valueReturnParams;
|
||||
std::string decodeElements;
|
||||
std::vector<std::string> valueReturnParams;
|
||||
size_t headPos = 0;
|
||||
size_t stackPos = 0;
|
||||
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();
|
||||
solAssert(sizeOnStack == decodingTypes[i]->sizeOnStack(), "");
|
||||
solAssert(sizeOnStack > 0, "");
|
||||
vector<string> valueNamesLocal;
|
||||
std::vector<std::string> valueNamesLocal;
|
||||
for (size_t j = 0; j < sizeOnStack; j++)
|
||||
{
|
||||
valueNamesLocal.emplace_back("value" + to_string(stackPos));
|
||||
valueReturnParams.emplace_back("value" + to_string(stackPos));
|
||||
valueNamesLocal.emplace_back("value" + std::to_string(stackPos));
|
||||
valueReturnParams.emplace_back("value" + std::to_string(stackPos));
|
||||
stackPos++;
|
||||
}
|
||||
Whiskers elementTempl(R"(
|
||||
@ -247,7 +246,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset"));
|
||||
elementTempl("load", _fromMemory ? "mload" : "calldataload");
|
||||
elementTempl("values", boost::algorithm::join(valueNamesLocal, ", "));
|
||||
elementTempl("pos", to_string(headPos));
|
||||
elementTempl("pos", std::to_string(headPos));
|
||||
elementTempl("abiDecode", abiDecodingFunction(*_types[i], _fromMemory, true));
|
||||
decodeElements += elementTempl.render();
|
||||
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)
|
||||
suffix += "_nonPadded";
|
||||
if (dynamicInplace)
|
||||
@ -274,7 +273,7 @@ string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
|
||||
return suffix;
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunction(
|
||||
std::string ABIFunctions::abiEncodingFunction(
|
||||
Type const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -349,7 +348,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
solAssert(_from.sizeOnStack() == 1, "");
|
||||
solAssert(to.isValueType(), "");
|
||||
solAssert(to.calldataEncodedSize() == 32, "");
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -376,7 +375,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
}
|
||||
else
|
||||
{
|
||||
string cleanupConvert;
|
||||
std::string cleanupConvert;
|
||||
if (_from == to)
|
||||
cleanupConvert = m_utils.cleanupFunction(_from) + "(value)";
|
||||
else
|
||||
@ -389,21 +388,21 @@ string ABIFunctions::abiEncodingFunction(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
|
||||
std::string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
|
||||
Type const& _givenType,
|
||||
Type const& _targetType,
|
||||
ABIFunctions::EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encodeUpdatedPos_" +
|
||||
_givenType.identifier() +
|
||||
"_to_" +
|
||||
_targetType.identifier() +
|
||||
_options.toFunctionNameSuffix();
|
||||
return createFunction(functionName, [&]() {
|
||||
string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options));
|
||||
string encoder = abiEncodingFunction(_givenType, _targetType, _options);
|
||||
std::string values = suffixedVariableNameList("value", 0, numVariablesForType(_givenType, _options));
|
||||
std::string encoder = abiEncodingFunction(_givenType, _targetType, _options);
|
||||
Type const* targetEncoding = _targetType.fullEncodingType(_options.encodeAsLibraryTypes, true, false);
|
||||
solAssert(targetEncoding, "");
|
||||
if (targetEncoding->isDynamicallyEncoded())
|
||||
@ -435,7 +434,7 @@ string ABIFunctions::abiEncodeAndReturnUpdatedPosFunction(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
std::string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
Type const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -461,7 +460,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
""
|
||||
);
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -522,13 +521,13 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
std::string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
ArrayType const& _from,
|
||||
ArrayType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -548,7 +547,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
EncodingOptions subOptions(_options);
|
||||
subOptions.encodeFunctionFromStack = false;
|
||||
subOptions.padded = true;
|
||||
string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions));
|
||||
std::string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions));
|
||||
Whiskers templ(
|
||||
usesTail ?
|
||||
R"(
|
||||
@ -632,13 +631,13 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
std::string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
ArrayType const& _from,
|
||||
ArrayType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -669,13 +668,13 @@ string ABIFunctions::abiEncodingFunctionMemoryByteArray(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
std::string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
ArrayType const& _from,
|
||||
ArrayType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -791,13 +790,13 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
templ("useSpill", "1");
|
||||
else
|
||||
templ("useSpill", "0");
|
||||
templ("itemsPerSlot", to_string(itemsPerSlot));
|
||||
templ("itemsPerSlot", std::to_string(itemsPerSlot));
|
||||
templ("stride", toCompactHexWithPrefix(_to.calldataStride()));
|
||||
|
||||
EncodingOptions subOptions(_options);
|
||||
subOptions.encodeFunctionFromStack = false;
|
||||
subOptions.padded = true;
|
||||
string encodeToMemoryFun = abiEncodingFunction(
|
||||
std::string encodeToMemoryFun = abiEncodingFunction(
|
||||
*_from.baseType(),
|
||||
*_to.baseType(),
|
||||
subOptions
|
||||
@ -820,13 +819,13 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionStruct(
|
||||
std::string ABIFunctions::abiEncodingFunctionStruct(
|
||||
StructType const& _from,
|
||||
StructType const& _to,
|
||||
EncodingOptions const& _options
|
||||
)
|
||||
{
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -867,7 +866,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
templ("init", _from.dataStoredIn(DataLocation::Storage) ? "let slotValue := 0" : "");
|
||||
u256 previousSlotOffset(-1);
|
||||
u256 encodingOffset = 0;
|
||||
vector<map<string, string>> members;
|
||||
std::vector<std::map<std::string, std::string>> members;
|
||||
for (auto const& member: _to.members(nullptr))
|
||||
{
|
||||
solAssert(member.type, "");
|
||||
@ -890,7 +889,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), "");
|
||||
u256 storageSlotOffset;
|
||||
size_t intraSlotOffset;
|
||||
tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name);
|
||||
std::tie(storageSlotOffset, intraSlotOffset) = _from.storageOffsetsOfMember(member.name);
|
||||
if (memberTypeFrom->isValueType())
|
||||
{
|
||||
if (storageSlotOffset != previousSlotOffset)
|
||||
@ -910,13 +909,13 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
}
|
||||
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 + "))";
|
||||
break;
|
||||
}
|
||||
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 + "))";
|
||||
break;
|
||||
}
|
||||
@ -929,10 +928,10 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
// Like with arrays, struct members are always padded.
|
||||
subOptions.padded = true;
|
||||
|
||||
string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions));
|
||||
std::string memberValues = suffixedVariableNameList("memberValue", 0, numVariablesForType(*memberTypeFrom, subOptions));
|
||||
members.back()["memberValues"] = memberValues;
|
||||
|
||||
string encode;
|
||||
std::string encode;
|
||||
if (_options.dynamicInplace)
|
||||
encode = Whiskers{"pos := <encode>(<memberValues>, pos)"}
|
||||
("encode", abiEncodeAndReturnUpdatedPosFunction(*memberTypeFrom, *memberTypeTo, subOptions))
|
||||
@ -942,7 +941,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
{
|
||||
Whiskers encodeTempl(
|
||||
dynamicMember ?
|
||||
string(R"(
|
||||
std::string(R"(
|
||||
mstore(add(pos, <encodingOffset>), sub(tail, pos))
|
||||
tail := <abiEncode>(<memberValues>, tail)
|
||||
)") :
|
||||
@ -966,7 +965,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
std::string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
Type const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -974,7 +973,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
{
|
||||
solAssert(_from.category() == Type::Category::StringLiteral, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_to_" +
|
||||
@ -982,7 +981,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
_options.toFunctionNameSuffix();
|
||||
return createFunction(functionName, [&]() {
|
||||
auto const& strType = dynamic_cast<StringLiteralType const&>(_from);
|
||||
string const& value = strType.value();
|
||||
std::string const& value = strType.value();
|
||||
solAssert(_from.sizeOnStack() == 0, "");
|
||||
|
||||
if (_to.isDynamicallySized())
|
||||
@ -998,12 +997,12 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
templ("functionName", functionName);
|
||||
|
||||
// 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));
|
||||
if (_options.padded)
|
||||
templ("overallSize", to_string(((value.size() + 31) / 32) * 32));
|
||||
templ("overallSize", std::to_string(((value.size() + 31) / 32) * 32));
|
||||
else
|
||||
templ("overallSize", to_string(value.size()));
|
||||
templ("overallSize", std::to_string(value.size()));
|
||||
templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value));
|
||||
return templ.render();
|
||||
}
|
||||
@ -1023,7 +1022,7 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
std::string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
FunctionType const& _from,
|
||||
Type const& _to,
|
||||
EncodingOptions const& _options
|
||||
@ -1036,7 +1035,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
|
||||
"Invalid function type conversion requested"
|
||||
);
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_encode_" +
|
||||
_from.identifier() +
|
||||
"_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.
|
||||
// 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);
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromMemory)
|
||||
{
|
||||
Type const* decodingType = _type.decodingType();
|
||||
solAssert(decodingType, "");
|
||||
@ -1113,7 +1112,7 @@ string ABIFunctions::abiDecodingFunctionValueType(Type const& _type, bool _fromM
|
||||
solAssert(!decodingType->isDynamicallyEncoded(), "");
|
||||
solAssert(decodingType->calldataEncodedSize() == 32, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_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), "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
|
||||
return createFunction(functionName, [&]() {
|
||||
string load = _fromMemory ? "mload" : "calldataload";
|
||||
std::string load = _fromMemory ? "mload" : "calldataload";
|
||||
Whiskers templ(
|
||||
R"(
|
||||
// <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), "");
|
||||
if (_type.isByteArrayOrString())
|
||||
return abiDecodingFunctionByteArrayAvailableLength(_type, _fromMemory);
|
||||
solAssert(_type.calldataStride() > 0, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_available_length_" +
|
||||
_type.identifier() +
|
||||
(_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), "");
|
||||
if (!_type.isDynamicallySized())
|
||||
@ -1232,7 +1231,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
|
||||
solAssert(_type.calldataStride() > 0, "");
|
||||
solAssert(_type.calldataStride() < u256("0xffffffffffffffff"), "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier();
|
||||
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.isByteArrayOrString(), "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_available_length_" +
|
||||
_type.identifier() +
|
||||
(_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), "");
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier();
|
||||
|
||||
@ -1321,15 +1320,15 @@ string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
|
||||
w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short"));
|
||||
w("functionName", functionName);
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory)
|
||||
std::string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fromMemory)
|
||||
{
|
||||
solAssert(!_type.dataStoredIn(DataLocation::CallData), "");
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_fromMemory ? "_fromMemory" : "");
|
||||
@ -1356,7 +1355,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
|
||||
solAssert(_type.memoryDataSize() < u256("0xffffffffffffffff"), "");
|
||||
templ("memorySize", toCompactHexWithPrefix(_type.memoryDataSize()));
|
||||
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))
|
||||
{
|
||||
solAssert(member.type, "");
|
||||
@ -1376,7 +1375,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
|
||||
// TODO add test
|
||||
memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset"));
|
||||
memberTempl("load", _fromMemory ? "mload" : "calldataload");
|
||||
memberTempl("pos", to_string(headPos));
|
||||
memberTempl("pos", std::to_string(headPos));
|
||||
memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name)));
|
||||
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, "");
|
||||
|
||||
string functionName =
|
||||
std::string functionName =
|
||||
"abi_decode_" +
|
||||
_type.identifier() +
|
||||
(_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), "");
|
||||
string functionName = "calldata_access_" + _type.identifier();
|
||||
std::string functionName = "calldata_access_" + _type.identifier();
|
||||
return createFunction(functionName, [&]() {
|
||||
if (_type.isDynamicallyEncoded())
|
||||
{
|
||||
@ -1477,7 +1476,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type)
|
||||
}
|
||||
else if (_type.isValueType())
|
||||
{
|
||||
string decodingFunction;
|
||||
std::string decodingFunction;
|
||||
if (auto const* functionType = dynamic_cast<FunctionType const*>(&_type))
|
||||
decodingFunction = abiDecodingFunctionFunctionType(*functionType, false, false);
|
||||
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, [&]() {
|
||||
if (_type.isDynamicallySized() && !_options.dynamicInplace)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
#include <libevmasm/Instruction.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -314,7 +313,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
if (!_sourceType.isByteArrayOrString())
|
||||
convertLengthToSize(_sourceType);
|
||||
|
||||
string routine = "calldatacopy(target, source, len)\n";
|
||||
std::string routine = "calldatacopy(target, source, len)\n";
|
||||
if (_padToWordBoundaries)
|
||||
routine += R"(
|
||||
// Set padding suffix to zero
|
||||
@ -890,7 +889,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
sstore(ref, slot_value)
|
||||
})");
|
||||
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 << Instruction::POP << Instruction::POP << Instruction::POP;
|
||||
}
|
||||
|
||||
@ -26,13 +26,12 @@
|
||||
#include <libsolidity/codegen/ContractCompiler.h>
|
||||
#include <libevmasm/Assembly.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
void Compiler::compileContract(
|
||||
ContractDefinition const& _contract,
|
||||
std::map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers,
|
||||
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> const& _otherCompilers,
|
||||
bytes const& _metadata
|
||||
)
|
||||
{
|
||||
|
||||
@ -55,7 +55,6 @@
|
||||
#undef SOL_OUTPUT_ASM
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::evmasm;
|
||||
@ -68,7 +67,7 @@ void CompilerContext::addStateVariable(
|
||||
unsigned _byteOffset
|
||||
)
|
||||
{
|
||||
m_stateVariables[&_declaration] = make_pair(_storageOffset, _byteOffset);
|
||||
m_stateVariables[&_declaration] = std::make_pair(_storageOffset, _byteOffset);
|
||||
}
|
||||
|
||||
void CompilerContext::addImmutable(VariableDeclaration const& _variable)
|
||||
@ -88,14 +87,14 @@ size_t CompilerContext::immutableMemoryOffset(VariableDeclaration const& _variab
|
||||
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, "");
|
||||
if (_variable.annotation().type->sizeOnStack() == 1)
|
||||
return {baseName};
|
||||
vector<string> names;
|
||||
auto collectSlotNames = [&](string const& _baseName, Type const* type, auto const& _recurse) -> void {
|
||||
std::vector<std::string> names;
|
||||
auto collectSlotNames = [&](std::string const& _baseName, Type const* type, auto const& _recurse) -> void {
|
||||
for (auto const& [slot, type]: type->stackItems())
|
||||
if (type)
|
||||
_recurse(_baseName + " " + slot, type, _recurse);
|
||||
@ -121,10 +120,10 @@ void CompilerContext::startFunction(Declaration const& _function)
|
||||
}
|
||||
|
||||
void CompilerContext::callLowLevelFunction(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs,
|
||||
function<void(CompilerContext&)> const& _generator
|
||||
std::function<void(CompilerContext&)> const& _generator
|
||||
)
|
||||
{
|
||||
evmasm::AssemblyItem retTag = pushNewTag();
|
||||
@ -138,7 +137,7 @@ void CompilerContext::callLowLevelFunction(
|
||||
}
|
||||
|
||||
void CompilerContext::callYulFunction(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs
|
||||
)
|
||||
@ -152,10 +151,10 @@ void CompilerContext::callYulFunction(
|
||||
}
|
||||
|
||||
evmasm::AssemblyItem CompilerContext::lowLevelFunctionTag(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs,
|
||||
function<void(CompilerContext&)> const& _generator
|
||||
std::function<void(CompilerContext&)> const& _generator
|
||||
)
|
||||
{
|
||||
auto it = m_lowLevelFunctions.find(_name);
|
||||
@ -174,10 +173,10 @@ void CompilerContext::appendMissingLowLevelFunctions()
|
||||
{
|
||||
while (!m_lowLevelFunctionGenerationQueue.empty())
|
||||
{
|
||||
string name;
|
||||
std::string name;
|
||||
unsigned inArgs;
|
||||
unsigned outArgs;
|
||||
function<void(CompilerContext&)> generator;
|
||||
std::function<void(CompilerContext&)> generator;
|
||||
tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front();
|
||||
m_lowLevelFunctionGenerationQueue.pop();
|
||||
|
||||
@ -195,7 +194,7 @@ void CompilerContext::appendYulUtilityFunctions(OptimiserSettings const& _optimi
|
||||
solAssert(!m_appendYulUtilityFunctionsRan, "requestedYulFunctions called more than once.");
|
||||
m_appendYulUtilityFunctionsRan = true;
|
||||
|
||||
string code = m_yulFunctionCollector.requestedFunctions();
|
||||
std::string code = m_yulFunctionCollector.requestedFunctions();
|
||||
if (!code.empty())
|
||||
{
|
||||
appendInlineAssembly(
|
||||
@ -233,7 +232,7 @@ void CompilerContext::removeVariable(Declaration const& _declaration)
|
||||
|
||||
void CompilerContext::removeVariablesAboveStackHeight(unsigned _stackHeight)
|
||||
{
|
||||
vector<Declaration const*> toRemove;
|
||||
std::vector<Declaration const*> toRemove;
|
||||
for (auto _var: m_localVariables)
|
||||
{
|
||||
solAssert(!_var.second.empty(), "");
|
||||
@ -250,14 +249,14 @@ unsigned CompilerContext::numberOfLocalVariables() const
|
||||
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);
|
||||
solAssert(ret != m_otherCompilers.end(), "Compiled contract not found.");
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
solAssert(it != m_stateVariables.end(), "Variable not found in storage.");
|
||||
@ -349,13 +348,13 @@ CompilerContext& CompilerContext::appendConditionalPanic(util::PanicCode _code)
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompilerContext& CompilerContext::appendRevert(string const& _message)
|
||||
CompilerContext& CompilerContext::appendRevert(std::string const& _message)
|
||||
{
|
||||
appendInlineAssembly("{ " + revertReasonIfDebug(_message) + " }");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, string const& _message)
|
||||
CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData, std::string const& _message)
|
||||
{
|
||||
if (_forwardReturnData && m_evmVersion.supportsReturndata())
|
||||
appendInlineAssembly(R"({
|
||||
@ -372,24 +371,24 @@ CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnDat
|
||||
|
||||
void CompilerContext::resetVisitedNodes(ASTNode const* _node)
|
||||
{
|
||||
stack<ASTNode const*> newStack;
|
||||
std::stack<ASTNode const*> newStack;
|
||||
newStack.push(_node);
|
||||
std::swap(m_visitedNodes, newStack);
|
||||
updateSourceLocation();
|
||||
}
|
||||
|
||||
void CompilerContext::appendInlineAssembly(
|
||||
string const& _assembly,
|
||||
vector<string> const& _localVariables,
|
||||
set<string> const& _externallyUsedFunctions,
|
||||
std::string const& _assembly,
|
||||
std::vector<std::string> const& _localVariables,
|
||||
std::set<std::string> const& _externallyUsedFunctions,
|
||||
bool _system,
|
||||
OptimiserSettings const& _optimiserSettings,
|
||||
string _sourceName
|
||||
std::string _sourceName
|
||||
)
|
||||
{
|
||||
unsigned startStackHeight = stackHeight();
|
||||
|
||||
set<yul::YulString> externallyUsedIdentifiers;
|
||||
std::set<yul::YulString> externallyUsedIdentifiers;
|
||||
for (auto const& fun: _externallyUsedFunctions)
|
||||
externallyUsedIdentifiers.insert(yul::YulString(fun));
|
||||
for (auto const& var: _localVariables)
|
||||
@ -438,19 +437,19 @@ void CompilerContext::appendInlineAssembly(
|
||||
ErrorReporter errorReporter(errors);
|
||||
langutil::CharStream charStream(_assembly, _sourceName);
|
||||
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
|
||||
optional<langutil::SourceLocation> locationOverride;
|
||||
std::optional<langutil::SourceLocation> locationOverride;
|
||||
if (!_system)
|
||||
locationOverride = m_asm->currentSourceLocation();
|
||||
shared_ptr<yul::Block> parserResult =
|
||||
std::shared_ptr<yul::Block> parserResult =
|
||||
yul::Parser(errorReporter, dialect, std::move(locationOverride))
|
||||
.parse(charStream);
|
||||
#ifdef SOL_OUTPUT_ASM
|
||||
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
|
||||
#endif
|
||||
|
||||
auto reportError = [&](string const& _context)
|
||||
auto reportError = [&](std::string const& _context)
|
||||
{
|
||||
string message =
|
||||
std::string message =
|
||||
"Error parsing/analyzing inline assembly block:\n" +
|
||||
_context + "\n"
|
||||
"------------------ Input: -----------------\n" +
|
||||
@ -483,7 +482,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
{
|
||||
yul::Object obj;
|
||||
obj.code = parserResult;
|
||||
obj.analysisInfo = make_shared<yul::AsmAnalysisInfo>(analysisInfo);
|
||||
obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(analysisInfo);
|
||||
|
||||
solAssert(!dialect.providesObjectAccess());
|
||||
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.
|
||||
solAssert(m_generatedYulUtilityCode.empty(), "");
|
||||
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);
|
||||
obj.code = yul::Parser(errorReporter, dialect).parse(charStream);
|
||||
*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj);
|
||||
@ -548,7 +547,7 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
|
||||
_optimiserSettings.optimizeStackAllocation,
|
||||
_optimiserSettings.yulOptimiserSteps,
|
||||
_optimiserSettings.yulOptimiserCleanupSteps,
|
||||
isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
|
||||
isCreation? std::nullopt : std::make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
|
||||
_externalIdentifiers
|
||||
);
|
||||
|
||||
@ -558,11 +557,11 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
|
||||
#endif
|
||||
}
|
||||
|
||||
string CompilerContext::revertReasonIfDebug(string const& _message)
|
||||
std::string CompilerContext::revertReasonIfDebug(std::string const& _message)
|
||||
{
|
||||
return YulUtilFunctions::revertReasonIfDebugBody(
|
||||
m_revertStrings,
|
||||
"mload(" + to_string(CompilerUtils::freeMemoryPointer) + ")",
|
||||
"mload(" + std::to_string(CompilerUtils::freeMemoryPointer) + ")",
|
||||
_message
|
||||
);
|
||||
}
|
||||
@ -590,14 +589,14 @@ evmasm::AssemblyItem CompilerContext::FunctionCompilationQueue::entryLabel(
|
||||
}
|
||||
|
||||
// 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(
|
||||
labelName,
|
||||
params,
|
||||
returns,
|
||||
_declaration.id()
|
||||
);
|
||||
m_entryLabels.insert(make_pair(&_declaration, tag));
|
||||
m_entryLabels.insert(std::make_pair(&_declaration, tag));
|
||||
m_functionsToCompile.push(&_declaration);
|
||||
return tag.tag();
|
||||
}
|
||||
|
||||
@ -33,7 +33,6 @@
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/StackTooDeepString.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -105,9 +104,9 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType)
|
||||
}
|
||||
|
||||
void CompilerUtils::revertWithError(
|
||||
string const& _signature,
|
||||
vector<Type const*> const& _parameterTypes,
|
||||
vector<Type const*> const& _argumentTypes
|
||||
std::string const& _signature,
|
||||
std::vector<Type const*> const& _parameterTypes,
|
||||
std::vector<Type const*> const& _argumentTypes
|
||||
)
|
||||
{
|
||||
fetchFreeMemoryPointer();
|
||||
@ -215,7 +214,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
|
||||
m_context << Instruction::DUP1;
|
||||
storeStringData(bytesConstRef(str->value()));
|
||||
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
|
||||
m_context << u256(str->value().size());
|
||||
m_context << Instruction::ADD;
|
||||
@ -264,7 +263,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
Whiskers templ(R"({
|
||||
if lt(len, <encodedSize>) { <revertString> }
|
||||
})");
|
||||
templ("encodedSize", to_string(encodedSize));
|
||||
templ("encodedSize", std::to_string(encodedSize));
|
||||
templ("revertString", m_context.revertReasonIfDebug("Calldata too short"));
|
||||
m_context.appendInlineAssembly(templ.render(), {"len"});
|
||||
|
||||
@ -320,7 +319,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
mstore(dst, array_length)
|
||||
dst := add(dst, 0x20)
|
||||
})");
|
||||
templ("item_size", to_string(arrayType.calldataStride()));
|
||||
templ("item_size", std::to_string(arrayType.calldataStride()));
|
||||
// TODO add test
|
||||
templ("revertStringPointer", m_context.revertReasonIfDebug("ABI memory decoding: invalid data pointer"));
|
||||
templ("revertStringStart", m_context.revertReasonIfDebug("ABI memory decoding: invalid data start"));
|
||||
@ -374,7 +373,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
m_context.appendInlineAssembly(Whiskers(R"({
|
||||
if or(
|
||||
gt(array_length, 0x100000000),
|
||||
gt(add(data_ptr, mul(array_length, )" + to_string(arrayType.calldataStride()) + R"()), input_end)
|
||||
gt(add(data_ptr, mul(array_length, )" + std::to_string(arrayType.calldataStride()) + R"()), input_end)
|
||||
) { <revertString> }
|
||||
})")
|
||||
("revertString", m_context.revertReasonIfDebug("ABI calldata decoding: invalid data pointer"))
|
||||
@ -618,7 +617,7 @@ void CompilerUtils::abiEncodeV2(
|
||||
|
||||
// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
|
||||
|
||||
string encoderName =
|
||||
std::string encoderName =
|
||||
_padToWordBoundaries ?
|
||||
m_context.abiFunctions().tupleEncoderReversed(_givenTypes, _targetTypes, _encodeAsLibraryTypes) :
|
||||
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::SWAP1;
|
||||
// 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));
|
||||
}
|
||||
|
||||
@ -646,7 +645,7 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
|
||||
calldatacopy(memptr, calldatasize(), 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"});
|
||||
}
|
||||
else
|
||||
@ -842,7 +841,7 @@ void CompilerUtils::convertType(
|
||||
m_context << Instruction::POP << u256(0);
|
||||
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 << Instruction::NOT << Instruction::AND;
|
||||
}
|
||||
@ -960,7 +959,7 @@ void CompilerUtils::convertType(
|
||||
case Type::Category::StringLiteral:
|
||||
{
|
||||
auto const& literalType = dynamic_cast<StringLiteralType const&>(_typeOnStack);
|
||||
string const& value = literalType.value();
|
||||
std::string const& value = literalType.value();
|
||||
bytesConstRef data(value);
|
||||
if (targetTypeCategory == Type::Category::FixedBytes)
|
||||
{
|
||||
@ -1186,7 +1185,7 @@ void CompilerUtils::convertType(
|
||||
for (auto const& member: typeOnStack->members(nullptr))
|
||||
{
|
||||
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 << u256(offsets.second);
|
||||
StorageItem(_context, *member.type).retrieveValue(SourceLocation(), true);
|
||||
@ -1268,7 +1267,7 @@ void CompilerUtils::convertType(
|
||||
if (sourceSize > 0 || targetSize > 0)
|
||||
{
|
||||
// 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 <<
|
||||
swapInstruction(depth + targetSize - sourceSize) <<
|
||||
Instruction::POP;
|
||||
@ -1375,7 +1374,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
|
||||
[type](CompilerContext& _context) {
|
||||
CompilerUtils utils(_context);
|
||||
|
||||
utils.allocateMemory(max<u256>(32u, type->memoryDataSize()));
|
||||
utils.allocateMemory(std::max<u256>(32u, type->memoryDataSize()));
|
||||
_context << Instruction::DUP1;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
|
||||
unsigned CompilerUtils::sizeOnStack(std::vector<Type const*> const& _variableTypes)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (Type const* type: _variableTypes)
|
||||
@ -1509,7 +1508,7 @@ void CompilerUtils::computeHashStatic()
|
||||
|
||||
void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract, bool _creation)
|
||||
{
|
||||
string which = _creation ? "Creation" : "Runtime";
|
||||
std::string which = _creation ? "Creation" : "Runtime";
|
||||
m_context.callLowLevelFunction(
|
||||
"$copyContract" + which + "CodeToMemory_" + contract.type()->identifier(),
|
||||
1,
|
||||
@ -1517,7 +1516,7 @@ void CompilerUtils::copyContractCodeToMemory(ContractDefinition const& contract,
|
||||
[&contract, _creation](CompilerContext& _context)
|
||||
{
|
||||
// copy the contract's code into memory
|
||||
shared_ptr<evmasm::Assembly> assembly =
|
||||
std::shared_ptr<evmasm::Assembly> assembly =
|
||||
_creation ?
|
||||
_context.compiledContract(contract) :
|
||||
_context.compiledContractRuntime(contract);
|
||||
|
||||
@ -55,7 +55,6 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -80,7 +79,7 @@ public:
|
||||
{
|
||||
solAssert(
|
||||
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:
|
||||
@ -92,7 +91,7 @@ private:
|
||||
|
||||
void ContractCompiler::compileContract(
|
||||
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);
|
||||
@ -111,7 +110,7 @@ void ContractCompiler::compileContract(
|
||||
|
||||
size_t ContractCompiler::compileConstructor(
|
||||
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);
|
||||
@ -126,7 +125,7 @@ size_t ContractCompiler::compileConstructor(
|
||||
|
||||
void ContractCompiler::initializeContext(
|
||||
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);
|
||||
@ -187,7 +186,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _contract);
|
||||
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);
|
||||
auto const& immutables = contractType.immutableVariables();
|
||||
@ -231,7 +230,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _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.pushSubroutineOffset(m_context.runtimeSub());
|
||||
// This code replaces the address added by appendDeployTimeAddress().
|
||||
@ -324,8 +323,8 @@ void ContractCompiler::appendDelegatecallCheck()
|
||||
}
|
||||
|
||||
void ContractCompiler::appendInternalSelector(
|
||||
map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints,
|
||||
vector<FixedHash<4>> const& _ids,
|
||||
std::map<FixedHash<4>, evmasm::AssemblyItem const> const& _entryPoints,
|
||||
std::vector<FixedHash<4>> const& _ids,
|
||||
evmasm::AssemblyItem const& _notFoundTag,
|
||||
size_t _runs
|
||||
)
|
||||
@ -369,11 +368,11 @@ void ContractCompiler::appendInternalSelector(
|
||||
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT;
|
||||
evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()};
|
||||
// Here, we have funid >= pivot
|
||||
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);
|
||||
m_context << lessTag;
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
@ -411,8 +410,8 @@ bool hasPayableFunctions(ContractDefinition const& _contract)
|
||||
|
||||
void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
{
|
||||
map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
|
||||
map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints;
|
||||
std::map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions();
|
||||
std::map<FixedHash<4>, evmasm::AssemblyItem const> callDataUnpackerEntryPoints;
|
||||
|
||||
if (_contract.isLibrary())
|
||||
{
|
||||
@ -448,7 +447,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
||||
CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true, false);
|
||||
|
||||
// stack now is: <can-call-non-view-functions>? <funhash>
|
||||
vector<FixedHash<4>> sortedIDs;
|
||||
std::vector<FixedHash<4>> sortedIDs;
|
||||
for (auto const& it: interfaceFunctions)
|
||||
{
|
||||
callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag());
|
||||
@ -572,7 +571,7 @@ void ContractCompiler::appendReturnValuePacker(TypePointers const& _typeParamete
|
||||
void ContractCompiler::registerStateVariables(ContractDefinition const& _contract)
|
||||
{
|
||||
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)
|
||||
@ -645,7 +644,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
|
||||
m_breakTags.clear();
|
||||
m_continueTags.clear();
|
||||
m_currentFunction = &_function;
|
||||
m_modifierDepth = numeric_limits<unsigned>::max();
|
||||
m_modifierDepth = std::numeric_limits<unsigned>::max();
|
||||
m_scopeStackHeight.clear();
|
||||
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_returnValuesSize = CompilerUtils::sizeOnStack(_function.returnParameters());
|
||||
|
||||
vector<int> stackLayout;
|
||||
std::vector<int> stackLayout;
|
||||
if (!_function.isConstructor() && !_function.isFallback())
|
||||
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)
|
||||
stackLayout.push_back(static_cast<int>(i));
|
||||
|
||||
@ -684,7 +683,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
|
||||
else
|
||||
{
|
||||
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)
|
||||
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);
|
||||
if (!ref->second.suffix.empty())
|
||||
{
|
||||
string const& suffix = ref->second.suffix;
|
||||
std::string const& suffix = ref->second.suffix;
|
||||
if (variable->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(suffix == "offset" || suffix == "slot", "");
|
||||
@ -865,7 +864,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
// lvalue context
|
||||
auto variable = dynamic_cast<VariableDeclaration const*>(decl);
|
||||
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1;
|
||||
string const& suffix = ref->second.suffix;
|
||||
std::string const& suffix = ref->second.suffix;
|
||||
if (variable->type()->dataStoredIn(DataLocation::Storage))
|
||||
{
|
||||
solAssert(
|
||||
@ -928,7 +927,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get();
|
||||
|
||||
// Only used in the scope below, but required to live outside to keep the
|
||||
// shared_ptr's alive
|
||||
// std::shared_ptr's alive
|
||||
yul::Object object = {};
|
||||
|
||||
// The optimiser cannot handle external references
|
||||
@ -941,8 +940,8 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
solAssert(dialect, "");
|
||||
|
||||
// Create a modifiable copy of the code and analysis
|
||||
object.code = make_shared<yul::Block>(yul::ASTCopier().translate(*code));
|
||||
object.analysisInfo = make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
|
||||
object.code = std::make_shared<yul::Block>(yul::ASTCopier().translate(*code));
|
||||
object.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
|
||||
|
||||
m_context.optimizeYul(object, *dialect, m_optimiserSettings);
|
||||
|
||||
@ -989,10 +988,10 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
|
||||
TryCatchClause const& successClause = *_tryStatement.clauses().front();
|
||||
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()))
|
||||
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(), "");
|
||||
for (size_t i = 0; i < exprTypes.size(); ++i)
|
||||
solAssert(params[i] && exprTypes[i] && *params[i]->annotation().type == *exprTypes[i], "");
|
||||
@ -1008,7 +1007,7 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
|
||||
return false;
|
||||
}
|
||||
|
||||
void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _catchClauses)
|
||||
void ContractCompiler::handleCatch(std::vector<ASTPointer<TryCatchClause>> const& _catchClauses)
|
||||
{
|
||||
// Stack is empty.
|
||||
ASTPointer<TryCatchClause> error{};
|
||||
@ -1285,7 +1284,7 @@ bool ContractCompiler::visit(Return const& _return)
|
||||
if (Expression const* expression = _return.expression())
|
||||
{
|
||||
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
|
||||
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
_return.annotation().functionReturnParameters->parameters();
|
||||
TypePointers types;
|
||||
for (auto const& retVariable: returnParameters)
|
||||
@ -1432,7 +1431,7 @@ void ContractCompiler::appendModifierOrFunctionCode()
|
||||
solAssert(m_currentFunction, "");
|
||||
unsigned stackSurplus = 0;
|
||||
Block const* codeBlock = nullptr;
|
||||
vector<VariableDeclaration const*> addedVariables;
|
||||
std::vector<VariableDeclaration const*> addedVariables;
|
||||
|
||||
m_modifierDepth++;
|
||||
m_context.setModifierDepth(m_modifierDepth);
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -242,7 +241,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
|
||||
if (!arrayType->isByteArrayOrString())
|
||||
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);
|
||||
Type const* memberType = structType->memberType(names[i]);
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
for (auto const& component: _tuple.components())
|
||||
@ -383,7 +382,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<unique_ptr<LValue>> lvalues;
|
||||
std::vector<std::unique_ptr<LValue>> lvalues;
|
||||
for (auto const& component: _tuple.components())
|
||||
if (component)
|
||||
{
|
||||
@ -395,13 +394,13 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
|
||||
}
|
||||
}
|
||||
else if (_tuple.annotation().willBeWrittenTo)
|
||||
lvalues.push_back(unique_ptr<LValue>());
|
||||
lvalues.push_back(std::unique_ptr<LValue>());
|
||||
if (_tuple.annotation().willBeWrittenTo)
|
||||
{
|
||||
if (_tuple.components().size() == 1)
|
||||
m_currentLValue = std::move(lvalues[0]);
|
||||
else
|
||||
m_currentLValue = make_unique<TupleObject>(m_context, std::move(lvalues));
|
||||
m_currentLValue = std::make_unique<TupleObject>(m_context, std::move(lvalues));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -524,7 +523,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
|
||||
m_context << u256(0) << Instruction::SUB;
|
||||
break;
|
||||
default:
|
||||
solAssert(false, "Invalid unary operator: " + string(TokenTraits::toString(_unaryOperation.getOperator())));
|
||||
solAssert(false, "Invalid unary operator: " + std::string(TokenTraits::toString(_unaryOperation.getOperator())));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -659,14 +658,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
|
||||
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)
|
||||
{
|
||||
TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
|
||||
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;
|
||||
|
||||
for (unsigned i = 0; i < arguments.size(); ++i)
|
||||
@ -992,7 +991,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::Error:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
vector<Type const*> argumentTypes;
|
||||
std::vector<Type const*> argumentTypes;
|
||||
for (ASTPointer<Expression const> const& arg: _functionCall.sortedArguments())
|
||||
{
|
||||
arg->accept(*this);
|
||||
@ -1060,7 +1059,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::RIPEMD160:
|
||||
{
|
||||
_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::SHA256, 2},
|
||||
{FunctionType::Kind::RIPEMD160, 3}
|
||||
@ -1151,8 +1150,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::BytesConcat:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
vector<Type const*> argumentTypes;
|
||||
vector<Type const*> targetTypes;
|
||||
std::vector<Type const*> argumentTypes;
|
||||
std::vector<Type const*> targetTypes;
|
||||
for (auto const& argument: arguments)
|
||||
{
|
||||
argument->accept(*this);
|
||||
@ -1416,7 +1415,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
// stack: <memory pointer> <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"({
|
||||
let data_start := add(mem_ptr, 0x20)
|
||||
let data := mload(data_start)
|
||||
@ -1476,7 +1475,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
// Desired Stack: [salt], [gas], [value]
|
||||
enum Option { Salt, Gas, Value };
|
||||
|
||||
vector<Option> presentOptions;
|
||||
std::vector<Option> presentOptions;
|
||||
FunctionType const& funType = dynamic_cast<FunctionType const&>(
|
||||
*_functionCallOptions.expression().annotation().type
|
||||
);
|
||||
@ -1486,7 +1485,7 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
|
||||
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();
|
||||
Option newOption;
|
||||
if (name == "salt")
|
||||
@ -1818,7 +1817,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
);
|
||||
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, "");
|
||||
utils().convertType(
|
||||
@ -1827,7 +1826,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
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(
|
||||
*_memberAccess.expression().annotation().type,
|
||||
*TypeProvider::address(),
|
||||
@ -1910,7 +1909,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
Whiskers(R"({
|
||||
mstore(start, sub(end, add(start, 0x20)))
|
||||
mstore(<free>, and(add(end, 31), not(31)))
|
||||
})")("free", to_string(CompilerUtils::freeMemoryPointer)).render(),
|
||||
})")("free", std::to_string(CompilerUtils::freeMemoryPointer)).render(),
|
||||
{"start", "end"}
|
||||
);
|
||||
m_context << Instruction::POP;
|
||||
@ -1946,7 +1945,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
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
|
||||
}
|
||||
@ -1961,7 +1960,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
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);
|
||||
setLValueToStorageItem(_memberAccess);
|
||||
break;
|
||||
@ -2454,7 +2453,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons
|
||||
IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
|
||||
if (m_context.arithmetic() == Arithmetic::Checked)
|
||||
{
|
||||
string functionName;
|
||||
std::string functionName;
|
||||
switch (_operator)
|
||||
{
|
||||
case Token::Add:
|
||||
@ -2620,7 +2619,7 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons
|
||||
|
||||
void ExpressionCompiler::appendExternalFunctionCall(
|
||||
FunctionType const& _functionType,
|
||||
vector<ASTPointer<Expression const>> const& _arguments,
|
||||
std::vector<ASTPointer<Expression const>> const& _arguments,
|
||||
bool _tryCall
|
||||
)
|
||||
{
|
||||
|
||||
@ -30,7 +30,6 @@
|
||||
|
||||
#include <libsolutil/StackTooDeepString.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -410,7 +409,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
|
||||
if (sourceType.location() == DataLocation::Storage)
|
||||
{
|
||||
// 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 << u256(offsets.second);
|
||||
// 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...
|
||||
}
|
||||
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 << u256(offsets.second);
|
||||
// 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;
|
||||
if (memberType->category() == Type::Category::Mapping)
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member.name);
|
||||
m_context
|
||||
<< offsets.first << Instruction::DUP3 << Instruction::ADD
|
||||
<< 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.
|
||||
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];
|
||||
unsigned stackHeight = m_context.stackHeight();
|
||||
solAssert(!valType == !lvalue, "");
|
||||
|
||||
@ -26,44 +26,43 @@
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
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_requestedFunctions.clear();
|
||||
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))
|
||||
{
|
||||
m_requestedFunctions.insert(_name);
|
||||
string fun = _creator();
|
||||
std::string fun = _creator();
|
||||
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);
|
||||
}
|
||||
return _name;
|
||||
}
|
||||
|
||||
string MultiUseYulFunctionCollector::createFunction(
|
||||
string const& _name,
|
||||
function<string(vector<string>&, vector<string>&)> const& _creator
|
||||
std::string MultiUseYulFunctionCollector::createFunction(
|
||||
std::string const& _name,
|
||||
std::function<std::string(std::vector<std::string>&, std::vector<std::string>&)> const& _creator
|
||||
)
|
||||
{
|
||||
solAssert(!_name.empty(), "");
|
||||
if (!m_requestedFunctions.count(_name))
|
||||
{
|
||||
m_requestedFunctions.insert(_name);
|
||||
vector<string> arguments;
|
||||
vector<string> returnParameters;
|
||||
string body = _creator(arguments, returnParameters);
|
||||
std::vector<std::string> arguments;
|
||||
std::vector<std::string> returnParameters;
|
||||
std::string body = _creator(arguments, returnParameters);
|
||||
solAssert(!body.empty(), "");
|
||||
|
||||
m_code += Whiskers(R"(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,6 @@
|
||||
|
||||
#include <libyul/AsmPrinter.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
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))
|
||||
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())
|
||||
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
|
||||
// for each invocation.
|
||||
solAssert(!_modifierInvocation.name().path().empty(), "");
|
||||
string const& modifierName = _modifierInvocation.name().path().back();
|
||||
std::string const& modifierName = _modifierInvocation.name().path().back();
|
||||
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());
|
||||
}
|
||||
|
||||
string IRNames::deployedObject(ContractDefinition const& _contract)
|
||||
std::string IRNames::deployedObject(ContractDefinition const& _contract)
|
||||
{
|
||||
return _contract.name() + "_" + toString(_contract.id()) + "_deployed";
|
||||
}
|
||||
|
||||
string IRNames::internalDispatch(YulArity const& _arity)
|
||||
std::string IRNames::internalDispatch(YulArity const& _arity)
|
||||
{
|
||||
return "dispatch_internal"
|
||||
"_in_" + to_string(_arity.in) +
|
||||
"_out_" + to_string(_arity.out);
|
||||
"_in_" + std::to_string(_arity.in) +
|
||||
"_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";
|
||||
}
|
||||
|
||||
string IRNames::constantValueFunction(VariableDeclaration const& _constant)
|
||||
std::string IRNames::constantValueFunction(VariableDeclaration const& _constant)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
solAssert(annotation, "");
|
||||
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;
|
||||
}
|
||||
|
||||
string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context)
|
||||
std::string dispenseLocationComment(langutil::SourceLocation const& _location, IRGenerationContext& _context)
|
||||
{
|
||||
solAssert(_location.sourceName, "");
|
||||
_context.markSourceUsed(*_location.sourceName);
|
||||
|
||||
string debugInfo = AsmPrinter::formatSourceLocation(
|
||||
std::string debugInfo = AsmPrinter::formatSourceLocation(
|
||||
_location,
|
||||
_context.sourceIndices(),
|
||||
_context.debugInfoSelection(),
|
||||
@ -154,7 +153,7 @@ string dispenseLocationComment(langutil::SourceLocation const& _location, IRGene
|
||||
return debugInfo.empty() ? "" : "/// " + debugInfo;
|
||||
}
|
||||
|
||||
string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
|
||||
std::string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context)
|
||||
{
|
||||
return dispenseLocationComment(_node.location(), _context);
|
||||
}
|
||||
|
||||
@ -32,14 +32,13 @@
|
||||
|
||||
#include <range/v3/view/map.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
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))
|
||||
m_functionGenerationQueue.insert(&_function);
|
||||
@ -121,12 +120,12 @@ void IRGenerationContext::addStateVariable(
|
||||
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)
|
||||
|
||||
@ -38,25 +38,23 @@
|
||||
#include <libsolutil/StringUtils.h>
|
||||
#include <libsolutil/Whiskers.h>
|
||||
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <json/json.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::util;
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void verifyCallGraph(
|
||||
set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables,
|
||||
set<FunctionDefinition const*> _generatedFunctions
|
||||
std::set<CallableDeclaration const*, ASTNode::CompareByID> const& _expectedCallables,
|
||||
std::set<FunctionDefinition const*> _generatedFunctions
|
||||
)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables;
|
||||
std::set<CallableDeclaration const*, ASTNode::CompareByID> reachableCallables;
|
||||
for (CallGraph::Node const& reachableNode: _graph.edges | ranges::views::keys)
|
||||
if (holds_alternative<CallableDeclaration const*>(reachableNode))
|
||||
reachableCallables.emplace(get<CallableDeclaration const*>(reachableNode));
|
||||
if (std::holds_alternative<CallableDeclaration const*>(reachableNode))
|
||||
reachableCallables.emplace(std::get<CallableDeclaration const*>(reachableNode));
|
||||
|
||||
return reachableCallables;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string IRGenerator::run(
|
||||
std::string IRGenerator::run(
|
||||
ContractDefinition const& _contract,
|
||||
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));
|
||||
}
|
||||
|
||||
string IRGenerator::generate(
|
||||
std::string IRGenerator::generate(
|
||||
ContractDefinition const& _contract,
|
||||
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;
|
||||
for (ContractDefinition const* subObject: subObjects)
|
||||
subObjectsSources += _otherYulSources.at(subObject);
|
||||
return subObjectsSources;
|
||||
};
|
||||
auto formatUseSrcMap = [](IRGenerationContext const& _context) -> string
|
||||
auto formatUseSrcMap = [](IRGenerationContext const& _context) -> std::string
|
||||
{
|
||||
return joinHumanReadable(
|
||||
ranges::views::transform(_context.usedSourceNames(), [_context](string const& _sourceName) {
|
||||
return to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName);
|
||||
ranges::views::transform(_context.usedSourceNames(), [_context](std::string const& _sourceName) {
|
||||
return std::to_string(_context.sourceIndices().at(_sourceName)) + ":" + escapeAndQuoteString(_sourceName);
|
||||
}),
|
||||
", "
|
||||
);
|
||||
@ -164,7 +162,7 @@ string IRGenerator::generate(
|
||||
|
||||
FunctionDefinition const* constructor = _contract.constructor();
|
||||
t("callValueCheck", !constructor || !constructor->isPayable() ? callValueCheck() : "");
|
||||
vector<string> constructorParams;
|
||||
std::vector<std::string> constructorParams;
|
||||
if (constructor && !constructor->parameters().empty())
|
||||
{
|
||||
for (size_t i = 0; i < CompilerUtils::sizeOnStack(constructor->parameters()); ++i)
|
||||
@ -180,7 +178,7 @@ string IRGenerator::generate(
|
||||
|
||||
t("deploy", deployCode(_contract));
|
||||
generateConstructors(_contract);
|
||||
set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
|
||||
std::set<FunctionDefinition const*> creationFunctionList = generateQueuedFunctions();
|
||||
InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract);
|
||||
|
||||
t("functions", m_context.functionCollector().requestedFunctions());
|
||||
@ -203,7 +201,7 @@ string IRGenerator::generate(
|
||||
t("sourceLocationCommentDeployed", dispenseLocationComment(_contract));
|
||||
t("library_address", IRNames::libraryAddressImmutable());
|
||||
t("dispatch", dispatchRoutine(_contract));
|
||||
set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
|
||||
std::set<FunctionDefinition const*> deployedFunctionList = generateQueuedFunctions();
|
||||
generateInternalDispatchFunctions(_contract);
|
||||
t("deployedFunctions", m_context.functionCollector().requestedFunctions());
|
||||
t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated()));
|
||||
@ -224,16 +222,16 @@ string IRGenerator::generate(
|
||||
return t.render();
|
||||
}
|
||||
|
||||
string IRGenerator::generate(Block const& _block)
|
||||
std::string IRGenerator::generate(Block const& _block)
|
||||
{
|
||||
IRGeneratorForStatements generator(m_context, m_utils);
|
||||
generator.generate(_block);
|
||||
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())
|
||||
{
|
||||
@ -258,7 +256,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
InternalDispatchMap internalDispatchMap = m_context.consumeInternalDispatchMap();
|
||||
for (YulArity const& arity: internalDispatchMap | ranges::views::keys)
|
||||
{
|
||||
string funName = IRNames::internalDispatch(arity);
|
||||
std::string funName = IRNames::internalDispatch(arity);
|
||||
m_context.functionCollector().createFunction(funName, [&]() {
|
||||
Whiskers templ(R"(
|
||||
<sourceLocationComment>
|
||||
@ -280,7 +278,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
templ("in", suffixedVariableNameList("in_", 0, arity.in));
|
||||
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))
|
||||
{
|
||||
solAssert(function, "");
|
||||
@ -293,8 +291,8 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
solAssert(function->id() != 0, "Unexpected function ID: 0");
|
||||
solAssert(m_context.functionCollector().contains(IRNames::function(*function)), "");
|
||||
|
||||
cases.emplace_back(map<string, string>{
|
||||
{"funID", to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
|
||||
cases.emplace_back(std::map<std::string, std::string>{
|
||||
{"funID", std::to_string(m_context.mostDerivedContract().annotation().internalFunctionIDs.at(function))},
|
||||
{"name", IRNames::function(*function)}
|
||||
});
|
||||
}
|
||||
@ -313,9 +311,9 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefin
|
||||
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, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
@ -328,7 +326,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
)");
|
||||
|
||||
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
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(_function));
|
||||
@ -338,12 +336,12 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
);
|
||||
|
||||
t("functionName", functionName);
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
for (auto const& varDecl: _function.parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
t("params", joinHumanReadable(params));
|
||||
vector<string> retParams;
|
||||
string retInit;
|
||||
std::vector<std::string> retParams;
|
||||
std::string retInit;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
{
|
||||
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)
|
||||
{
|
||||
ModifierInvocation const& modifier = *_function.modifiers().at(i);
|
||||
string next =
|
||||
std::string next =
|
||||
i + 1 < _function.modifiers().size() ?
|
||||
IRNames::modifierInvocation(*_function.modifiers().at(i + 1)) :
|
||||
IRNames::functionWithModifierInner(_function);
|
||||
generateModifier(modifier, _function, next);
|
||||
}
|
||||
t("body",
|
||||
(retParams.empty() ? string{} : joinHumanReadable(retParams) + " := ") +
|
||||
(retParams.empty() ? std::string{} : joinHumanReadable(retParams) + " := ") +
|
||||
IRNames::modifierInvocation(*_function.modifiers().at(0)) +
|
||||
"(" +
|
||||
joinHumanReadable(retParams + params) +
|
||||
@ -380,13 +378,13 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function)
|
||||
});
|
||||
}
|
||||
|
||||
string IRGenerator::generateModifier(
|
||||
std::string IRGenerator::generateModifier(
|
||||
ModifierInvocation const& _modifierInvocation,
|
||||
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, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
@ -400,15 +398,15 @@ string IRGenerator::generateModifier(
|
||||
)");
|
||||
|
||||
t("functionName", functionName);
|
||||
vector<string> retParamsIn;
|
||||
std::vector<std::string> retParamsIn;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
retParamsIn += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
vector<string> params = retParamsIn;
|
||||
std::vector<std::string> params = retParamsIn;
|
||||
for (auto const& varDecl: _function.parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
t("params", joinHumanReadable(params));
|
||||
vector<string> retParams;
|
||||
string assignRetParams;
|
||||
std::vector<std::string> retParams;
|
||||
std::string assignRetParams;
|
||||
for (size_t i = 0; i < retParamsIn.size(); ++i)
|
||||
{
|
||||
retParams.emplace_back(m_context.newYulVariable());
|
||||
@ -423,7 +421,7 @@ string IRGenerator::generateModifier(
|
||||
solAssert(modifier, "");
|
||||
|
||||
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
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(*modifier));
|
||||
@ -465,7 +463,7 @@ string IRGenerator::generateModifier(
|
||||
|
||||
t("evalArgs", expressionEvaluator.code());
|
||||
IRGeneratorForStatements generator(m_context, m_utils, [&]() {
|
||||
string ret = joinHumanReadable(retParams);
|
||||
std::string ret = joinHumanReadable(retParams);
|
||||
return
|
||||
(ret.empty() ? "" : ret + " := ") +
|
||||
_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, [&]() {
|
||||
m_context.resetLocalVariables();
|
||||
Whiskers t(R"(
|
||||
@ -495,17 +493,17 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const&
|
||||
dispenseLocationComment(m_context.mostDerivedContract())
|
||||
);
|
||||
t("functionName", functionName);
|
||||
vector<string> retParams;
|
||||
vector<string> retParamsIn;
|
||||
std::vector<std::string> retParams;
|
||||
std::vector<std::string> retParamsIn;
|
||||
for (auto const& varDecl: _function.returnParameters())
|
||||
retParams += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
string assignRetParams;
|
||||
std::string assignRetParams;
|
||||
for (size_t i = 0; i < retParams.size(); ++i)
|
||||
{
|
||||
retParamsIn.emplace_back(m_context.newYulVariable());
|
||||
assignRetParams += retParams.at(i) + " := " + retParamsIn.at(i) + "\n";
|
||||
}
|
||||
vector<string> params = retParamsIn;
|
||||
std::vector<std::string> params = retParamsIn;
|
||||
for (auto const& varDecl: _function.parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
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, [&]() {
|
||||
Type const* type = _varDecl.annotation().type;
|
||||
|
||||
@ -540,7 +538,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
@ -549,7 +547,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
dispenseLocationComment(m_context.mostDerivedContract())
|
||||
)
|
||||
("functionName", functionName)
|
||||
("id", to_string(_varDecl.id()))
|
||||
("id", std::to_string(_varDecl.id()))
|
||||
.render();
|
||||
}
|
||||
else if (_varDecl.isConstant())
|
||||
@ -565,7 +563,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("sourceLocationComment", dispenseLocationComment(_varDecl))
|
||||
@ -579,7 +577,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
.render();
|
||||
}
|
||||
|
||||
string code;
|
||||
std::string code;
|
||||
|
||||
auto const& location = m_context.storageLocationOfStateVariable(_varDecl);
|
||||
code += Whiskers(R"(
|
||||
@ -587,7 +585,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
let offset := <offset>
|
||||
)")
|
||||
("slot", location.first.str())
|
||||
("offset", to_string(location.second))
|
||||
("offset", std::to_string(location.second))
|
||||
.render();
|
||||
|
||||
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.
|
||||
Type const* currentType = _varDecl.annotation().type;
|
||||
|
||||
vector<string> parameters;
|
||||
vector<string> returnVariables;
|
||||
std::vector<std::string> parameters;
|
||||
std::vector<std::string> returnVariables;
|
||||
|
||||
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);
|
||||
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()
|
||||
).stackSlots();
|
||||
parameters += keys;
|
||||
@ -655,8 +653,8 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
)
|
||||
continue;
|
||||
|
||||
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
vector<string> retVars = IRVariable("ret_" + to_string(returnVariables.size()), *returnTypes[i]).stackSlots();
|
||||
std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
std::vector<std::string> retVars = IRVariable("ret_" + std::to_string(returnVariables.size()), *returnTypes[i]).stackSlots();
|
||||
returnVariables += retVars;
|
||||
code += Whiskers(R"(
|
||||
<ret> := <readStorage>(add(slot, <slotOffset>))
|
||||
@ -673,7 +671,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(returnTypes.front());
|
||||
if (arrayType)
|
||||
solAssert(arrayType->isByteArrayOrString(), "");
|
||||
vector<string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
|
||||
std::vector<std::string> retVars = IRVariable("ret", *returnTypes.front()).stackSlots();
|
||||
returnVariables += retVars;
|
||||
code += Whiskers(R"(
|
||||
<ret> := <readStorage>(slot, offset)
|
||||
@ -697,7 +695,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
||||
(
|
||||
"astIDComment",
|
||||
m_context.debugInfoSelection().astID ?
|
||||
"/// @ast-id " + to_string(_varDecl.id()) + "\n" :
|
||||
"/// @ast-id " + std::to_string(_varDecl.id()) + "\n" :
|
||||
""
|
||||
)
|
||||
("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());
|
||||
return m_context.functionCollector().createFunction(functionName, [&](vector<string>&, vector<string>&) -> string {
|
||||
std::string functionName = IRNames::externalFunctionABIWrapper(_functionType.declaration());
|
||||
return m_context.functionCollector().createFunction(functionName, [&](std::vector<std::string>&, std::vector<std::string>&) -> std::string {
|
||||
Whiskers t(R"X(
|
||||
<callValueCheck>
|
||||
<?+params>let <params> := </+params> <abiDecode>(4, calldatasize())
|
||||
@ -723,8 +721,8 @@ string IRGenerator::generateExternalFunction(ContractDefinition const& _contract
|
||||
)X");
|
||||
t("callValueCheck", (_functionType.isPayable() || _contract.isLibrary()) ? "" : callValueCheck());
|
||||
|
||||
unsigned paramVars = make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
|
||||
unsigned retVars = make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
|
||||
unsigned paramVars = std::make_shared<TupleType>(_functionType.parameterTypes())->sizeOnStack();
|
||||
unsigned retVars = std::make_shared<TupleType>(_functionType.returnParameterTypes())->sizeOnStack();
|
||||
|
||||
ABIFunctions abiFunctions(m_evmVersion, m_context.revertStrings(), m_context.functionCollector());
|
||||
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);
|
||||
generator.initializeLocalVar(_varDecl);
|
||||
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
|
||||
)
|
||||
{
|
||||
@ -767,12 +765,12 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua
|
||||
auto it2 = find(linearizedBaseContracts.begin(), linearizedBaseContracts.end(), _c2);
|
||||
return it1 < it2;
|
||||
}
|
||||
vector<ContractDefinition const*> const& linearizedBaseContracts;
|
||||
std::vector<ContractDefinition const*> const& 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);
|
||||
|
||||
for (ASTPointer<InheritanceSpecifier> const& base: _contract.baseContracts())
|
||||
@ -804,7 +802,7 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua
|
||||
solAssert(baseContract && arguments, "");
|
||||
if (baseContract->constructor() && !arguments->empty())
|
||||
{
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
for (size_t i = 0; i < arguments->size(); ++i)
|
||||
params += generator.evaluateExpression(
|
||||
*(arguments->at(i)),
|
||||
@ -817,7 +815,7 @@ pair<string, map<ContractDefinition const*, vector<string>>> IRGenerator::evalua
|
||||
return {generator.code(), constructorParams};
|
||||
}
|
||||
|
||||
string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
std::string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
{
|
||||
IRGeneratorForStatements generator{m_context, m_utils};
|
||||
for (VariableDeclaration const* variable: _contract.stateVariables())
|
||||
@ -831,16 +829,16 @@ string IRGenerator::initStateVariables(ContractDefinition const& _contract)
|
||||
void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
{
|
||||
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)
|
||||
if (baseParams.count(contract))
|
||||
params += baseParams.at(contract);
|
||||
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)
|
||||
{
|
||||
ContractDefinition const* contract = _contract.annotation().linearizedBaseContracts[i];
|
||||
@ -859,13 +857,13 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
}
|
||||
<contractSourceLocationComment>
|
||||
)");
|
||||
vector<string> params;
|
||||
std::vector<std::string> params;
|
||||
if (contract->constructor())
|
||||
for (ASTPointer<VariableDeclaration> const& varDecl: contract->constructor()->parameters())
|
||||
params += m_context.addLocalVariable(*varDecl).stackSlots();
|
||||
|
||||
if (m_context.debugInfoSelection().astID && contract->constructor())
|
||||
t("astIDComment", "/// @ast-id " + to_string(contract->constructor()->id()) + "\n");
|
||||
t("astIDComment", "/// @ast-id " + std::to_string(contract->constructor()->id()) + "\n");
|
||||
else
|
||||
t("astIDComment", "");
|
||||
t("sourceLocationComment", dispenseLocationComment(
|
||||
@ -879,11 +877,11 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
);
|
||||
|
||||
t("params", joinHumanReadable(params));
|
||||
vector<string> baseParams = listAllParams(baseConstructorParams);
|
||||
std::vector<std::string> baseParams = listAllParams(baseConstructorParams);
|
||||
t("baseParams", joinHumanReadable(baseParams));
|
||||
t("comma", !params.empty() && !baseParams.empty() ? ", " : "");
|
||||
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());
|
||||
t("evalBaseArguments", evaluatedArgs.first);
|
||||
if (i < _contract.annotation().linearizedBaseContracts.size() - 1)
|
||||
@ -896,10 +894,10 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract)
|
||||
else
|
||||
t("hasNextConstructor", false);
|
||||
t("initStateVariables", initStateVariables(*contract));
|
||||
string body;
|
||||
std::string body;
|
||||
if (FunctionDefinition const* constructor = contract->constructor())
|
||||
{
|
||||
vector<ModifierInvocation*> realModifiers;
|
||||
std::vector<ModifierInvocation*> realModifiers;
|
||||
for (auto const& modifierInvocation: constructor->modifiers())
|
||||
// Filter out the base constructor calls
|
||||
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)
|
||||
{
|
||||
ModifierInvocation const& modifier = *realModifiers.at(i);
|
||||
string next =
|
||||
std::string next =
|
||||
i + 1 < realModifiers.size() ?
|
||||
IRNames::modifierInvocation(*realModifiers.at(i + 1)) :
|
||||
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(
|
||||
let <codeOffset> := <allocateUnbounded>()
|
||||
@ -947,11 +945,11 @@ string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
t("codeOffset", m_context.newYulVariable());
|
||||
t("object", IRNames::deployedObject(_contract));
|
||||
|
||||
vector<map<string, string>> immutables;
|
||||
std::vector<std::map<std::string, std::string>> immutables;
|
||||
if (_contract.isLibrary())
|
||||
{
|
||||
solAssert(ContractType(_contract).immutableVariables().empty(), "");
|
||||
immutables.emplace_back(map<string, string>{
|
||||
immutables.emplace_back(std::map<std::string, std::string>{
|
||||
{"immutableName"s, IRNames::libraryAddressImmutable()},
|
||||
{"value"s, "address()"}
|
||||
});
|
||||
@ -962,21 +960,21 @@ string IRGenerator::deployCode(ContractDefinition const& _contract)
|
||||
{
|
||||
solUnimplementedAssert(immutable->type()->isValueType());
|
||||
solUnimplementedAssert(immutable->type()->sizeOnStack() == 1);
|
||||
immutables.emplace_back(map<string, string>{
|
||||
{"immutableName"s, to_string(immutable->id())},
|
||||
{"value"s, "mload(" + to_string(m_context.immutableMemoryOffset(*immutable)) + ")"}
|
||||
immutables.emplace_back(std::map<std::string, std::string>{
|
||||
{"immutableName"s, std::to_string(immutable->id())},
|
||||
{"value"s, "mload(" + std::to_string(m_context.immutableMemoryOffset(*immutable)) + ")"}
|
||||
});
|
||||
}
|
||||
t("immutables", std::move(immutables));
|
||||
return t.render();
|
||||
}
|
||||
|
||||
string IRGenerator::callValueCheck()
|
||||
std::string IRGenerator::callValueCheck()
|
||||
{
|
||||
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(
|
||||
<?+cases>if iszero(lt(calldatasize(), 4))
|
||||
@ -997,15 +995,15 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
<fallback>
|
||||
)X");
|
||||
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())
|
||||
{
|
||||
functions.emplace_back();
|
||||
map<string, string>& templ = functions.back();
|
||||
std::map<std::string, std::string>& templ = functions.back();
|
||||
templ["functionSelector"] = "0x" + function.first.hex();
|
||||
FunctionTypePointer const& type = function.second;
|
||||
templ["functionName"] = type->externalSignature();
|
||||
string delegatecallCheck;
|
||||
std::string delegatecallCheck;
|
||||
if (_contract.isLibrary())
|
||||
{
|
||||
solAssert(!type->isPayable(), "");
|
||||
@ -1033,7 +1031,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
if (FunctionDefinition const* fallback = _contract.fallbackFunction())
|
||||
{
|
||||
solAssert(!_contract.isLibrary(), "");
|
||||
string fallbackCode;
|
||||
std::string fallbackCode;
|
||||
if (!fallback->isPayable())
|
||||
fallbackCode += callValueCheck() + "\n";
|
||||
if (fallback->parameters().empty())
|
||||
@ -1057,7 +1055,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
|
||||
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
|
||||
// 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>, <freeMemoryStart>)"
|
||||
}
|
||||
("memPtr", to_string(CompilerUtils::freeMemoryPointer))
|
||||
("memPtr", std::to_string(CompilerUtils::freeMemoryPointer))
|
||||
(
|
||||
"freeMemoryStart",
|
||||
to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory())
|
||||
std::to_string(CompilerUtils::generalPurposeMemoryStart + m_context.reservedMemory())
|
||||
).render();
|
||||
}
|
||||
|
||||
@ -1101,10 +1099,10 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon
|
||||
|
||||
m_context.setMostDerivedContract(_contract);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -49,7 +49,6 @@
|
||||
|
||||
#include <range/v3/view/transform.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
@ -95,8 +94,8 @@ struct CopyTranslate: public yul::ASTCopier
|
||||
return ASTCopier::translate(_identifier);
|
||||
|
||||
yul::Expression translated = translateReference(_identifier);
|
||||
solAssert(holds_alternative<yul::Identifier>(translated));
|
||||
return get<yul::Identifier>(std::move(translated));
|
||||
solAssert(std::holds_alternative<yul::Identifier>(translated));
|
||||
return std::get<yul::Identifier>(std::move(translated));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -109,9 +108,9 @@ private:
|
||||
auto const& reference = m_references.at(&_identifier);
|
||||
auto const varDecl = dynamic_cast<VariableDeclaration const*>(reference.declaration);
|
||||
solUnimplementedAssert(varDecl);
|
||||
string const& suffix = reference.suffix;
|
||||
std::string const& suffix = reference.suffix;
|
||||
|
||||
string value;
|
||||
std::string value;
|
||||
if (suffix.empty() && varDecl->isLocalVariable())
|
||||
{
|
||||
auto const& var = m_context.localVariable(*varDecl);
|
||||
@ -165,7 +164,7 @@ private:
|
||||
if (suffix == "slot")
|
||||
value = m_context.storageLocationOfStateVariable(*varDecl).first.str();
|
||||
else if (suffix == "offset")
|
||||
value = to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
value = std::to_string(m_context.storageLocationOfStateVariable(*varDecl).second);
|
||||
else
|
||||
solAssert(false);
|
||||
}
|
||||
@ -216,7 +215,7 @@ private:
|
||||
|
||||
}
|
||||
|
||||
string IRGeneratorForStatementsBase::code() const
|
||||
std::string IRGeneratorForStatementsBase::code() const
|
||||
{
|
||||
return m_code.str();
|
||||
}
|
||||
@ -240,7 +239,7 @@ void IRGeneratorForStatementsBase::setLocation(ASTNode const& _node)
|
||||
m_currentLocation = _node.location();
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::code() const
|
||||
std::string IRGeneratorForStatements::code() const
|
||||
{
|
||||
solAssert(!m_currentLValue, "LValue not reset!");
|
||||
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
|
||||
{
|
||||
string functionName = IRNames::constantValueFunction(_constant);
|
||||
std::string functionName = IRNames::constantValueFunction(_constant);
|
||||
return m_context.functionCollector().createFunction(functionName, [&] {
|
||||
Whiskers templ(R"(
|
||||
<sourceLocationComment>
|
||||
@ -410,7 +409,7 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional)
|
||||
|
||||
setLocation(_conditional);
|
||||
|
||||
string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
|
||||
std::string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean());
|
||||
declare(_conditional);
|
||||
|
||||
appendCode() << "switch " << condition << "\n" "case 0 {\n";
|
||||
@ -501,7 +500,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
_tuple.components().size() <<
|
||||
")\n";
|
||||
|
||||
string mpos = IRVariable(_tuple).part("mpos").name();
|
||||
std::string mpos = IRVariable(_tuple).part("mpos").name();
|
||||
Type const& baseType = *arrayType.baseType();
|
||||
for (size_t i = 0; i < _tuple.components().size(); i++)
|
||||
{
|
||||
@ -512,7 +511,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
appendCode() <<
|
||||
m_utils.writeToMemoryFunction(baseType) <<
|
||||
"(" <<
|
||||
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
|
||||
("add(" + mpos + ", " + std::to_string(i * arrayType.memoryStride()) + ")") <<
|
||||
", " <<
|
||||
converted.commaSeparatedList() <<
|
||||
")\n";
|
||||
@ -535,7 +534,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<optional<IRLValue>> lvalues;
|
||||
std::vector<std::optional<IRLValue>> lvalues;
|
||||
for (size_t i = 0; i < _tuple.components().size(); ++i)
|
||||
if (auto const& component = _tuple.components()[i])
|
||||
{
|
||||
@ -586,7 +585,7 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement)
|
||||
{
|
||||
_ifStatement.condition().accept(*this);
|
||||
setLocation(_ifStatement);
|
||||
string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean());
|
||||
std::string condition = expressionAsType(_ifStatement.condition(), *TypeProvider::boolean());
|
||||
|
||||
if (_ifStatement.falseStatement())
|
||||
{
|
||||
@ -658,7 +657,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return)
|
||||
if (Expression const* value = _return.expression())
|
||||
{
|
||||
solAssert(_return.annotation().functionReturnParameters, "Invalid return parameters pointer.");
|
||||
vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters =
|
||||
_return.annotation().functionReturnParameters->parameters();
|
||||
if (returnParameters.size() > 1)
|
||||
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()[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(_unaryOperation.userDefinedFunctionType()->kind() == FunctionType::Kind::Internal);
|
||||
@ -812,8 +811,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
solAssert(function->returnParameters().size() == 1);
|
||||
solAssert(*function->returnParameters()[0]->type() == *_binOp.annotation().type);
|
||||
|
||||
string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type());
|
||||
string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type());
|
||||
std::string left = expressionAsType(_binOp.leftExpression(), *function->parameters()[0]->type());
|
||||
std::string right = expressionAsType(_binOp.rightExpression(), *function->parameters()[1]->type());
|
||||
solAssert(!left.empty() && !right.empty());
|
||||
|
||||
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))
|
||||
isSigned = type->isSigned();
|
||||
|
||||
string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType);
|
||||
std::string args = expressionAsCleanedType(_binOp.leftExpression(), *commonType);
|
||||
args += ", " + expressionAsCleanedType(_binOp.rightExpression(), *commonType);
|
||||
|
||||
auto functionType = dynamic_cast<FunctionType const*>(commonType);
|
||||
solAssert(functionType ? (op == Token::Equal || op == Token::NotEqual) : true, "Invalid function pointer comparison!");
|
||||
|
||||
string expr;
|
||||
std::string expr;
|
||||
|
||||
if (functionType && functionType->kind() == FunctionType::Kind::External)
|
||||
{
|
||||
@ -879,9 +878,9 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
else if (op == Token::NotEqual)
|
||||
expr = "iszero(eq(" + std::move(args) + "))";
|
||||
else if (op == Token::GreaterThanOrEqual)
|
||||
expr = "iszero(" + string(isSigned ? "slt(" : "lt(") + std::move(args) + "))";
|
||||
expr = "iszero(" + std::string(isSigned ? "slt(" : "lt(") + std::move(args) + "))";
|
||||
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)
|
||||
expr = (isSigned ? "sgt(" : "gt(") + std::move(args) + ")";
|
||||
else if (op == Token::LessThan)
|
||||
@ -925,8 +924,8 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
}
|
||||
else
|
||||
{
|
||||
string left = expressionAsType(_binOp.leftExpression(), *commonType);
|
||||
string right = expressionAsType(_binOp.rightExpression(), *commonType);
|
||||
std::string left = expressionAsType(_binOp.leftExpression(), *commonType);
|
||||
std::string right = expressionAsType(_binOp.rightExpression(), *commonType);
|
||||
define(_binOp) << binaryOperation(_binOp.getOperator(), *commonType, left, right) << "\n";
|
||||
}
|
||||
return false;
|
||||
@ -960,7 +959,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
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)
|
||||
{
|
||||
@ -1001,7 +1000,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
solAssert(!functionType->takesArbitraryParameters());
|
||||
|
||||
vector<string> args;
|
||||
std::vector<std::string> args;
|
||||
if (functionType->hasBoundFirstArgument())
|
||||
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
|
||||
|
||||
@ -1049,8 +1048,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
TypePointers paramTypes = functionType->parameterTypes();
|
||||
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
|
||||
|
||||
vector<IRVariable> indexedArgs;
|
||||
vector<string> nonIndexedArgs;
|
||||
std::vector<IRVariable> indexedArgs;
|
||||
std::vector<std::string> nonIndexedArgs;
|
||||
TypePointers nonIndexedArgTypes;
|
||||
TypePointers nonIndexedParamTypes;
|
||||
if (!event.isAnonymous())
|
||||
@ -1061,7 +1060,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
Expression const& arg = *arguments[i];
|
||||
if (event.parameters()[i]->isIndexed())
|
||||
{
|
||||
string value;
|
||||
std::string value;
|
||||
if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[i]))
|
||||
define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::uint256())) <<
|
||||
m_utils.packedHashFunction({arg.annotation().type}, {referenceType}) <<
|
||||
@ -1106,7 +1105,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("encode", abi.tupleEncoder(nonIndexedArgTypes, nonIndexedParamTypes));
|
||||
templ("nonIndexedArgs", joinHumanReadablePrefixed(nonIndexedArgs));
|
||||
templ("log", "log" + to_string(indexedArgs.size()));
|
||||
templ("log", "log" + std::to_string(indexedArgs.size()));
|
||||
templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) {
|
||||
return _arg.commaSeparatedList();
|
||||
})));
|
||||
@ -1152,7 +1151,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip ?
|
||||
arguments[1]->annotation().type :
|
||||
nullptr;
|
||||
string requireOrAssertFunction = m_utils.requireOrAssertFunction(
|
||||
std::string requireOrAssertFunction = m_utils.requireOrAssertFunction(
|
||||
functionType->kind() == FunctionType::Kind::Assert,
|
||||
messageArgumentType
|
||||
);
|
||||
@ -1179,9 +1178,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
TypePointers argumentTypes;
|
||||
TypePointers targetTypes;
|
||||
vector<string> argumentVars;
|
||||
string selector;
|
||||
vector<ASTPointer<Expression const>> argumentsOfEncodeFunction;
|
||||
std::vector<std::string> argumentVars;
|
||||
std::string selector;
|
||||
std::vector<ASTPointer<Expression const>> argumentsOfEncodeFunction;
|
||||
|
||||
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.
|
||||
// We might want to introduce a new set of memory handling functions here
|
||||
// a la "setMemoryCheckPoint" and "freeUntilCheckPoint".
|
||||
string freeMemoryPre = m_context.newYulVariable();
|
||||
std::string freeMemoryPre = m_context.newYulVariable();
|
||||
appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n";
|
||||
IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory());
|
||||
IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32));
|
||||
|
||||
string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory());
|
||||
string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory());
|
||||
std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*TypeProvider::bytesMemory());
|
||||
std::string arrayLengthFunction = m_utils.arrayLengthFunction(*TypeProvider::bytesMemory());
|
||||
define(hashVariable) <<
|
||||
"keccak256(" <<
|
||||
(dataAreaFunction + "(" + array.commaSeparatedList() + ")") <<
|
||||
@ -1389,8 +1388,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
{
|
||||
auto array = convert(*arguments[0], *arrayType);
|
||||
|
||||
string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType);
|
||||
string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType);
|
||||
std::string dataAreaFunction = m_utils.arrayDataAreaFunction(*arrayType);
|
||||
std::string arrayLengthFunction = m_utils.arrayLengthFunction(*arrayType);
|
||||
define(_functionCall) <<
|
||||
"keccak256(" <<
|
||||
(dataAreaFunction + "(" + array.commaSeparatedList() + ")") <<
|
||||
@ -1453,7 +1452,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::BytesConcat:
|
||||
{
|
||||
TypePointers argumentTypes;
|
||||
vector<string> argumentVars;
|
||||
std::vector<std::string> argumentVars;
|
||||
for (ASTPointer<Expression const> const& argument: arguments)
|
||||
{
|
||||
argumentTypes.emplace_back(&type(*argument));
|
||||
@ -1473,7 +1472,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::AddMod:
|
||||
case FunctionType::Kind::MulMod:
|
||||
{
|
||||
static map<FunctionType::Kind, string> functions = {
|
||||
static std::map<FunctionType::Kind, std::string> functions = {
|
||||
{FunctionType::Kind::AddMod, "addmod"},
|
||||
{FunctionType::Kind::MulMod, "mulmod"},
|
||||
};
|
||||
@ -1487,7 +1486,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero));
|
||||
appendCode() << templ.render();
|
||||
|
||||
string args;
|
||||
std::string args;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
args += expressionAsType(*arguments[i], *(parameterTypes[i])) + ", ";
|
||||
args += modulus.name();
|
||||
@ -1498,14 +1497,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::Selfdestruct:
|
||||
case FunctionType::Kind::BlockHash:
|
||||
{
|
||||
static map<FunctionType::Kind, string> functions = {
|
||||
static std::map<FunctionType::Kind, std::string> functions = {
|
||||
{FunctionType::Kind::GasLeft, "gas"},
|
||||
{FunctionType::Kind::Selfdestruct, "selfdestruct"},
|
||||
{FunctionType::Kind::BlockHash, "blockhash"},
|
||||
};
|
||||
solAssert(functions.find(functionType->kind()) != functions.end());
|
||||
|
||||
string args;
|
||||
std::string args;
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
args += (args.empty() ? "" : ", ") + expressionAsType(*arguments[i], *(parameterTypes[i]));
|
||||
define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n";
|
||||
@ -1520,7 +1519,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
);
|
||||
|
||||
TypePointers argumentTypes;
|
||||
vector<string> constructorParams;
|
||||
std::vector<std::string> constructorParams;
|
||||
for (ASTPointer<Expression const> const& arg: arguments)
|
||||
{
|
||||
argumentTypes.push_back(arg->annotation().type);
|
||||
@ -1575,8 +1574,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::Transfer:
|
||||
{
|
||||
solAssert(arguments.size() == 1 && parameterTypes.size() == 1);
|
||||
string address{IRVariable(_functionCall.expression()).part("address").name()};
|
||||
string value{expressionAsType(*arguments[0], *(parameterTypes[0]))};
|
||||
std::string address{IRVariable(_functionCall.expression()).part("address").name()};
|
||||
std::string value{expressionAsType(*arguments[0], *(parameterTypes[0]))};
|
||||
Whiskers templ(R"(
|
||||
let <gas> := 0
|
||||
if iszero(<value>) { <gas> := <callStipend> }
|
||||
@ -1608,14 +1607,14 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
solAssert(!functionType->gasSet());
|
||||
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::SHA256, std::make_tuple(2, 0)},
|
||||
{FunctionType::Kind::RIPEMD160, std::make_tuple(3, 12)},
|
||||
};
|
||||
auto [ address, offset ] = precompiles[functionType->kind()];
|
||||
TypePointers argumentTypes;
|
||||
vector<string> argumentStrings;
|
||||
std::vector<std::string> argumentStrings;
|
||||
for (auto const& arg: arguments)
|
||||
{
|
||||
argumentTypes.emplace_back(&type(*arg));
|
||||
@ -1676,11 +1675,11 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
|
||||
|
||||
// Copy over existing values.
|
||||
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)
|
||||
{
|
||||
string const& name = *_options.names()[i];
|
||||
std::string const& name = *_options.names()[i];
|
||||
solAssert(name == "salt" || name == "gas" || name == "value");
|
||||
|
||||
define(IRVariable(_options).part(name), *_options.options()[i]);
|
||||
@ -1785,7 +1784,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
")\n";
|
||||
else if (member == "code")
|
||||
{
|
||||
string externalCodeFunction = m_utils.externalCodeFunction();
|
||||
std::string externalCodeFunction = m_utils.externalCodeFunction();
|
||||
define(_memberAccess) <<
|
||||
externalCodeFunction <<
|
||||
"(" <<
|
||||
@ -1797,12 +1796,12 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
"extcodehash(" <<
|
||||
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
|
||||
")\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);
|
||||
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());
|
||||
else
|
||||
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);
|
||||
|
||||
string requestedValue;
|
||||
std::string requestedValue;
|
||||
if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(arg->typeArgument()))
|
||||
{
|
||||
if (member == "min")
|
||||
@ -1956,16 +1955,16 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
else if (EnumType const* enumType = dynamic_cast<EnumType const*>(arg->typeArgument()))
|
||||
{
|
||||
if (member == "min")
|
||||
requestedValue = to_string(enumType->minValue());
|
||||
requestedValue = std::to_string(enumType->minValue());
|
||||
else
|
||||
requestedValue = to_string(enumType->maxValue());
|
||||
requestedValue = std::to_string(enumType->maxValue());
|
||||
}
|
||||
else
|
||||
solAssert(false, "min/max requested on unexpected type.");
|
||||
|
||||
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
|
||||
}
|
||||
@ -1981,8 +1980,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
{
|
||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
||||
string slot = m_context.newYulVariable();
|
||||
std::pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
||||
std::string slot = m_context.newYulVariable();
|
||||
appendCode() << "let " << slot << " := " <<
|
||||
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
|
||||
setLValue(_memberAccess, IRLValue{
|
||||
@ -1993,7 +1992,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
case DataLocation::Memory:
|
||||
{
|
||||
string pos = m_context.newYulVariable();
|
||||
std::string pos = m_context.newYulVariable();
|
||||
appendCode() << "let " << pos << " := " <<
|
||||
("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n");
|
||||
setLValue(_memberAccess, IRLValue{
|
||||
@ -2004,9 +2003,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
case DataLocation::CallData:
|
||||
{
|
||||
string baseRef = expression.part("offset").name();
|
||||
string offset = m_context.newYulVariable();
|
||||
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
||||
std::string baseRef = expression.part("offset").name();
|
||||
std::string offset = m_context.newYulVariable();
|
||||
appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << std::to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
||||
if (_memberAccess.annotation().type->isDynamicallyEncoded())
|
||||
define(_memberAccess) <<
|
||||
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
|
||||
@ -2036,7 +2035,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
case Type::Category::Enum:
|
||||
{
|
||||
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;
|
||||
}
|
||||
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);
|
||||
if (member == "length")
|
||||
define(_memberAccess) << to_string(type.numBytes()) << "\n";
|
||||
define(_memberAccess) << std::to_string(type.numBytes()) << "\n";
|
||||
else
|
||||
solAssert(false, "Illegal fixed bytes member.");
|
||||
break;
|
||||
@ -2162,7 +2161,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
solAssert(false);
|
||||
}
|
||||
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))
|
||||
solAssert(member == "wrap" || member == "unwrap");
|
||||
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());
|
||||
|
||||
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.
|
||||
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);
|
||||
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");
|
||||
templ("slot", slot);
|
||||
templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType));
|
||||
@ -2273,8 +2272,8 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
{
|
||||
string slot = m_context.newYulVariable();
|
||||
string offset = m_context.newYulVariable();
|
||||
std::string slot = m_context.newYulVariable();
|
||||
std::string offset = m_context.newYulVariable();
|
||||
|
||||
appendCode() << Whiskers(R"(
|
||||
let <slot>, <offset> := <indexFunc>(<array>, <index>)
|
||||
@ -2295,13 +2294,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
}
|
||||
case DataLocation::Memory:
|
||||
{
|
||||
string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType);
|
||||
string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name();
|
||||
string const indexExpression = expressionAsType(
|
||||
std::string const indexAccessFunction = m_utils.memoryArrayIndexAccessFunction(arrayType);
|
||||
std::string const baseRef = IRVariable(_indexAccess.baseExpression()).part("mpos").name();
|
||||
std::string const indexExpression = expressionAsType(
|
||||
*_indexAccess.indexExpression(),
|
||||
*TypeProvider::uint256()
|
||||
);
|
||||
string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
std::string const memAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
|
||||
setLValue(_indexAccess, IRLValue{
|
||||
*arrayType.baseType(),
|
||||
@ -2311,13 +2310,13 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
}
|
||||
case DataLocation::CallData:
|
||||
{
|
||||
string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType);
|
||||
string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList();
|
||||
string const indexExpression = expressionAsType(
|
||||
std::string const indexAccessFunction = m_utils.calldataArrayIndexAccessFunction(arrayType);
|
||||
std::string const baseRef = IRVariable(_indexAccess.baseExpression()).commaSeparatedList();
|
||||
std::string const indexExpression = expressionAsType(
|
||||
*_indexAccess.indexExpression(),
|
||||
*TypeProvider::uint256()
|
||||
);
|
||||
string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
std::string const calldataAddress = indexAccessFunction + "(" + baseRef + ", " + indexExpression + ")";
|
||||
|
||||
if (arrayType.isByteArrayOrString())
|
||||
define(_indexAccess) <<
|
||||
@ -2349,7 +2348,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
let <result> := <shl248>(byte(<index>, <array>))
|
||||
)")
|
||||
("index", index.name())
|
||||
("length", to_string(fixedBytesType.numBytes()))
|
||||
("length", std::to_string(fixedBytesType.numBytes()))
|
||||
("panic", m_utils.panicFunction(PanicCode::ArrayOutOfBounds))
|
||||
("array", IRVariable(_indexAccess.baseExpression()).name())
|
||||
("shl248", m_utils.shiftLeftFunction(256 - 8))
|
||||
@ -2538,7 +2537,7 @@ void IRGeneratorForStatements::handleVariableReference(
|
||||
|
||||
void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
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()));
|
||||
@ -2559,7 +2558,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
|
||||
TypePointers parameterTypes = funType.parameterTypes();
|
||||
TypePointers argumentTypes;
|
||||
vector<string> argumentStrings;
|
||||
std::vector<std::string> argumentStrings;
|
||||
if (funType.hasBoundFirstArgument())
|
||||
{
|
||||
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
|
||||
// would remove that, so we use MSTORE here.
|
||||
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.
|
||||
@ -2649,10 +2648,10 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
if (returnInfo.dynamicReturnSize)
|
||||
solAssert(m_context.evmVersion().supportsReturndata());
|
||||
templ("returnDataSizeVar", m_context.newYulVariable());
|
||||
templ("staticReturndataSize", to_string(returnInfo.estimatedReturnSize));
|
||||
templ("staticReturndataSize", std::to_string(returnInfo.estimatedReturnSize));
|
||||
templ("supportsReturnData", m_context.evmVersion().supportsReturndata());
|
||||
|
||||
string const retVars = IRVariable(_functionCall).commaSeparatedList();
|
||||
std::string const retVars = IRVariable(_functionCall).commaSeparatedList();
|
||||
templ("retVars", retVars);
|
||||
solAssert(retVars.empty() == returnInfo.returnTypes.empty());
|
||||
|
||||
@ -2704,7 +2703,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall(
|
||||
|
||||
void IRGeneratorForStatements::appendBareCall(
|
||||
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()));
|
||||
@ -2807,7 +2806,7 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
|
||||
return;
|
||||
|
||||
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";
|
||||
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)
|
||||
{
|
||||
string output;
|
||||
std::string output;
|
||||
if (_lhs.type() == _rhs.type() && !_forceCleanup)
|
||||
for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems())
|
||||
if (stackItemType)
|
||||
@ -2894,7 +2893,7 @@ IRVariable IRGeneratorForStatements::zeroValue(Type const& _type, bool _splitFun
|
||||
|
||||
void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const& _operation, Expression const& _expr)
|
||||
{
|
||||
string func;
|
||||
std::string func;
|
||||
|
||||
if (_operation.getOperator() == Token::Not)
|
||||
func = "iszero";
|
||||
@ -2913,18 +2912,18 @@ void IRGeneratorForStatements::appendSimpleUnaryOperation(UnaryOperation const&
|
||||
")\n";
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::binaryOperation(
|
||||
std::string IRGeneratorForStatements::binaryOperation(
|
||||
langutil::Token _operator,
|
||||
Type const& _type,
|
||||
string const& _left,
|
||||
string const& _right
|
||||
std::string const& _left,
|
||||
std::string const& _right
|
||||
)
|
||||
{
|
||||
solAssert(
|
||||
!TokenTraits::isShiftOp(_operator),
|
||||
"Have to use specific shift operation function for shifts."
|
||||
);
|
||||
string fun;
|
||||
std::string fun;
|
||||
if (TokenTraits::isBitOp(_operator))
|
||||
{
|
||||
solAssert(
|
||||
@ -3030,12 +3029,12 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
||||
std::visit(
|
||||
util::GenericVisitor{
|
||||
[&](IRLValue::Storage const& _storage) {
|
||||
string offsetArgument;
|
||||
optional<unsigned> offsetStatic;
|
||||
std::string offsetArgument;
|
||||
std::optional<unsigned> offsetStatic;
|
||||
|
||||
std::visit(GenericVisitor{
|
||||
[&](unsigned _offset) { offsetStatic = _offset; },
|
||||
[&](string const& _offset) { offsetArgument = ", " + _offset; }
|
||||
[&](std::string const& _offset) { offsetArgument = ", " + _offset; }
|
||||
}, _storage.offset);
|
||||
|
||||
appendCode() <<
|
||||
@ -3068,7 +3067,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
||||
}
|
||||
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() <<
|
||||
writeUInt <<
|
||||
"(" <<
|
||||
@ -3099,7 +3098,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
||||
IRVariable prepared(m_context.newYulVariable(), _lvalue.type);
|
||||
define(prepared, _value);
|
||||
|
||||
appendCode() << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
|
||||
appendCode() << "mstore(" << std::to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n";
|
||||
},
|
||||
[&](IRLValue::Tuple const& _tuple) {
|
||||
auto components = std::move(_tuple.components);
|
||||
@ -3122,13 +3121,13 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue)
|
||||
[&](IRLValue::Storage const& _storage) {
|
||||
if (!_lvalue.type.isValueType())
|
||||
define(result) << _storage.slot << "\n";
|
||||
else if (std::holds_alternative<string>(_storage.offset))
|
||||
else if (std::holds_alternative<std::string>(_storage.offset))
|
||||
define(result) <<
|
||||
m_utils.readFromStorageDynamic(_lvalue.type, true) <<
|
||||
"(" <<
|
||||
_storage.slot <<
|
||||
", " <<
|
||||
std::get<string>(_storage.offset) <<
|
||||
std::get<std::string>(_storage.offset) <<
|
||||
")\n";
|
||||
else
|
||||
define(result) <<
|
||||
@ -3156,15 +3155,15 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue)
|
||||
solAssert(_lvalue.type == *_immutable.variable->type());
|
||||
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) <<
|
||||
readFunction <<
|
||||
"(" <<
|
||||
to_string(m_context.immutableMemoryOffset(*_immutable.variable)) <<
|
||||
std::to_string(m_context.immutableMemoryOffset(*_immutable.variable)) <<
|
||||
")\n";
|
||||
}
|
||||
else
|
||||
define(result) << "loadimmutable(\"" << to_string(_immutable.variable->id()) << "\")\n";
|
||||
define(result) << "loadimmutable(\"" << std::to_string(_immutable.variable->id()) << "\")\n";
|
||||
},
|
||||
[&](IRLValue::Tuple const&) {
|
||||
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));
|
||||
if (_lvalue.type.dataStoredIn(DataLocation::CallData))
|
||||
solAssert(holds_alternative<IRLValue::Stack>(_lvalue.kind));
|
||||
solAssert(std::holds_alternative<IRLValue::Stack>(_lvalue.kind));
|
||||
}
|
||||
else
|
||||
// Only define the expression, if it will not be written to.
|
||||
@ -3196,7 +3195,7 @@ void IRGeneratorForStatements::generateLoop(
|
||||
bool _isDoWhile
|
||||
)
|
||||
{
|
||||
string firstRun;
|
||||
std::string firstRun;
|
||||
|
||||
if (_isDoWhile)
|
||||
{
|
||||
@ -3278,7 +3277,7 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement)
|
||||
void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||
{
|
||||
setLocation(_tryStatement);
|
||||
string const runFallback = m_context.newYulVariable();
|
||||
std::string const runFallback = m_context.newYulVariable();
|
||||
appendCode() << "let " << runFallback << " := 1\n";
|
||||
|
||||
// This function returns zero on "short returndata". We have to add a success flag
|
||||
@ -3290,7 +3289,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||
{
|
||||
appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n";
|
||||
setLocation(*errorClause);
|
||||
string const dataVariable = m_context.newYulVariable();
|
||||
std::string const dataVariable = m_context.newYulVariable();
|
||||
appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
|
||||
appendCode() << "if " << dataVariable << " {\n";
|
||||
appendCode() << runFallback << " := 0\n";
|
||||
@ -3310,8 +3309,8 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
||||
{
|
||||
appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n";
|
||||
setLocation(*panicClause);
|
||||
string const success = m_context.newYulVariable();
|
||||
string const code = m_context.newYulVariable();
|
||||
std::string const success = m_context.newYulVariable();
|
||||
std::string const code = m_context.newYulVariable();
|
||||
appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n";
|
||||
appendCode() << "if " << success << " {\n";
|
||||
appendCode() << runFallback << " := 0\n";
|
||||
@ -3358,9 +3357,9 @@ void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallba
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::revertWithError(
|
||||
string const& _signature,
|
||||
vector<Type const*> const& _parameterTypes,
|
||||
vector<ASTPointer<Expression const>> const& _errorArguments
|
||||
std::string const& _signature,
|
||||
std::vector<Type const*> const& _parameterTypes,
|
||||
std::vector<ASTPointer<Expression const>> const& _errorArguments
|
||||
)
|
||||
{
|
||||
Whiskers templ(R"({
|
||||
@ -3374,8 +3373,8 @@ void IRGeneratorForStatements::revertWithError(
|
||||
templ("hash", util::selectorFromSignatureU256(_signature).str());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
|
||||
vector<string> errorArgumentVars;
|
||||
vector<Type const*> errorArgumentTypes;
|
||||
std::vector<std::string> errorArgumentVars;
|
||||
std::vector<Type const*> errorArgumentTypes;
|
||||
for (ASTPointer<Expression const> const& arg: _errorArguments)
|
||||
{
|
||||
errorArgumentVars += IRVariable(*arg).stackSlots();
|
||||
@ -3395,7 +3394,7 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause)
|
||||
return false;
|
||||
}
|
||||
|
||||
string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||
std::string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const
|
||||
{
|
||||
solAssert(_library.isLibrary());
|
||||
return "linkersymbol(" + util::escapeAndQuoteString(_library.fullyQualifiedName()) + ")";
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
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())
|
||||
if (itemName == _name)
|
||||
@ -63,9 +62,9 @@ bool IRVariable::hasPart(std::string const& _name) const
|
||||
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())
|
||||
if (itemType)
|
||||
{
|
||||
@ -81,17 +80,17 @@ vector<string> IRVariable::stackSlots() const
|
||||
return result;
|
||||
}
|
||||
|
||||
string IRVariable::commaSeparatedList() const
|
||||
std::string IRVariable::commaSeparatedList() const
|
||||
{
|
||||
return joinHumanReadable(stackSlots());
|
||||
}
|
||||
|
||||
string IRVariable::commaSeparatedListPrefixed() const
|
||||
std::string IRVariable::commaSeparatedListPrefixed() const
|
||||
{
|
||||
return joinHumanReadablePrefixed(stackSlots());
|
||||
}
|
||||
|
||||
string IRVariable::name() const
|
||||
std::string IRVariable::name() const
|
||||
{
|
||||
solAssert(m_type.sizeOnStack() == 1, "");
|
||||
auto const& [itemName, type] = m_type.stackItems().front();
|
||||
@ -108,7 +107,7 @@ IRVariable IRVariable::tupleComponent(size_t _i) const
|
||||
return part(IRNames::tupleComponent(_i));
|
||||
}
|
||||
|
||||
string IRVariable::suffixedName(string const& _suffix) const
|
||||
std::string IRVariable::suffixedName(std::string const& _suffix) const
|
||||
{
|
||||
if (_suffix.empty())
|
||||
return m_baseName;
|
||||
|
||||
34
libsolidity/experimental/analysis/Analysis.cpp
Normal file
34
libsolidity/experimental/analysis/Analysis.cpp
Normal 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;
|
||||
}
|
||||
@ -15,33 +15,35 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// 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
|
||||
|
||||
#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;
|
||||
|
||||
/**
|
||||
* Prerequisites: Function Grouper
|
||||
*/
|
||||
class MainFunction
|
||||
class Analysis
|
||||
{
|
||||
public:
|
||||
static constexpr char const* name{"MainFunction"};
|
||||
static void run(OptimiserStepContext&, Block& _ast) { MainFunction{}(_ast); }
|
||||
Analysis(langutil::ErrorReporter& _errorReporter):
|
||||
m_errorReporter(_errorReporter)
|
||||
{}
|
||||
|
||||
void operator()(Block& _block);
|
||||
bool check(std::vector<std::shared_ptr<SourceUnit const>> const& _sourceUnits);
|
||||
|
||||
private:
|
||||
MainFunction() = default;
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
};
|
||||
|
||||
}
|
||||
@ -20,18 +20,17 @@
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::smtutil;
|
||||
using namespace solidity::frontend;
|
||||
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, "");
|
||||
auto tupleSort = dynamic_pointer_cast<TupleSort>(_sort);
|
||||
auto tupleSort = std::dynamic_pointer_cast<TupleSort>(_sort);
|
||||
solAssert(tupleSort, "");
|
||||
|
||||
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 iVar{TypeProvider::uint256(), TypeProvider::uint256(), "i_" + tupleName, _context};
|
||||
|
||||
vector<SortPointer> domain{sort, sort, startVar.sort(), endVar.sort()};
|
||||
auto sliceSort = make_shared<FunctionSort>(domain, SortProvider::boolSort);
|
||||
std::vector<SortPointer> domain{sort, sort, startVar.sort(), endVar.sort()};
|
||||
auto sliceSort = std::make_shared<FunctionSort>(domain, SortProvider::boolSort);
|
||||
Predicate const& slice = *Predicate::create(sliceSort, "array_slice_" + tupleName, PredicateType::Custom, _context);
|
||||
|
||||
domain.emplace_back(iVar.sort());
|
||||
auto predSort = 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& loop = *Predicate::create(predSort, "array_slice_loop_" + tupleName, PredicateType::Custom, _context);
|
||||
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include <z3_version.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
@ -41,13 +40,13 @@ BMC::BMC(
|
||||
smt::EncodingContext& _context,
|
||||
UniqueErrorReporter& _errorReporter,
|
||||
UniqueErrorReporter& _unsupportedErrorReporter,
|
||||
map<h256, string> const& _smtlib2Responses,
|
||||
std::map<h256, std::string> const& _smtlib2Responses,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
ModelCheckerSettings _settings,
|
||||
CharStreamProvider const& _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
|
||||
))
|
||||
{
|
||||
@ -65,7 +64,7 @@ BMC::BMC(
|
||||
#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.
|
||||
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,
|
||||
{},
|
||||
"BMC: " +
|
||||
to_string(m_unprovedAmt) +
|
||||
std::to_string(m_unprovedAmt) +
|
||||
" verification condition(s) could not be proved." +
|
||||
" Enable the model checker option \"show unproved\" to see all of them." +
|
||||
" Consider choosing a specific contract to be verified in order to reduce the solving problems." +
|
||||
@ -108,7 +107,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
|
||||
m_errorReporter.info(
|
||||
6002_error,
|
||||
"BMC: " +
|
||||
to_string(m_safeTargets.size()) +
|
||||
std::to_string(m_safeTargets.size()) +
|
||||
" verification condition(s) proved safe!" +
|
||||
" 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."
|
||||
" None of the installed solvers was enabled."
|
||||
#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
|
||||
);
|
||||
}
|
||||
@ -504,11 +503,11 @@ bool BMC::visit(TryStatement const& _tryStatement)
|
||||
if (_tryStatement.successClause()->parameters())
|
||||
expressionToTupleAssignment(_tryStatement.successClause()->parameters()->parameters(), *externalCall);
|
||||
|
||||
smtutil::Expression clauseId = m_context.newVariable("clause_choice_" + 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();
|
||||
m_context.addAssertion(clauseId >= 0 && clauseId < clauses.size());
|
||||
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)
|
||||
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,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
@ -800,10 +799,10 @@ void BMC::reset()
|
||||
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;
|
||||
vector<string> expressionNames;
|
||||
std::vector<smtutil::Expression> expressionsToEvaluate;
|
||||
std::vector<std::string> expressionNames;
|
||||
for (auto const& var: m_context.variables())
|
||||
if (var.first->type()->isValueType())
|
||||
{
|
||||
@ -826,7 +825,7 @@ pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
|
||||
if (uf->annotation().type->isValueType())
|
||||
{
|
||||
expressionsToEvaluate.emplace_back(expr(*uf));
|
||||
string expressionName;
|
||||
std::string expressionName;
|
||||
if (uf->location().hasText())
|
||||
expressionName = m_charStreamProvider.charStream(*uf->location().sourceName).text(
|
||||
uf->location()
|
||||
@ -839,7 +838,7 @@ pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
|
||||
|
||||
/// Verification targets.
|
||||
|
||||
string BMC::targetDescription(BMCVerificationTarget const& _target)
|
||||
std::string BMC::targetDescription(BMCVerificationTarget const& _target)
|
||||
{
|
||||
if (
|
||||
_target.type == VerificationTargetType::Underflow ||
|
||||
@ -1065,20 +1064,20 @@ void BMC::addVerificationTarget(
|
||||
void BMC::checkCondition(
|
||||
BMCVerificationTarget const& _target,
|
||||
smtutil::Expression _condition,
|
||||
vector<SMTEncoder::CallStackEntry> const& _callStack,
|
||||
pair<vector<smtutil::Expression>, vector<string>> const& _modelExpressions,
|
||||
std::vector<SMTEncoder::CallStackEntry> const& _callStack,
|
||||
std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> const& _modelExpressions,
|
||||
SourceLocation const& _location,
|
||||
ErrorId _errorHappens,
|
||||
ErrorId _errorMightHappen,
|
||||
string const& _additionalValueName,
|
||||
std::string const& _additionalValueName,
|
||||
smtutil::Expression const* _additionalValue
|
||||
)
|
||||
{
|
||||
m_interface->push();
|
||||
m_interface->addAssertion(_condition);
|
||||
|
||||
vector<smtutil::Expression> expressionsToEvaluate;
|
||||
vector<string> expressionNames;
|
||||
std::vector<smtutil::Expression> expressionsToEvaluate;
|
||||
std::vector<std::string> expressionNames;
|
||||
tie(expressionsToEvaluate, expressionNames) = _modelExpressions;
|
||||
if (!_callStack.empty())
|
||||
if (_additionalValue)
|
||||
@ -1087,10 +1086,10 @@ void BMC::checkCondition(
|
||||
expressionNames.push_back(_additionalValueName);
|
||||
}
|
||||
smtutil::CheckResult result;
|
||||
vector<string> values;
|
||||
std::vector<std::string> values;
|
||||
tie(result, values) = checkSatisfiableAndGenerateModel(expressionsToEvaluate);
|
||||
|
||||
string extraComment = SMTEncoder::extraComment();
|
||||
std::string extraComment = SMTEncoder::extraComment();
|
||||
if (m_loopExecutionHappened)
|
||||
extraComment +=
|
||||
"False negatives are possible when unrolling loops.\n"
|
||||
@ -1119,7 +1118,7 @@ void BMC::checkCondition(
|
||||
if (values.size() == expressionNames.size())
|
||||
{
|
||||
modelMessage << "Counterexample:\n";
|
||||
map<string, string> sortedModel;
|
||||
std::map<std::string, std::string> sortedModel;
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
if (expressionsToEvaluate.at(i).name != values.at(i))
|
||||
sortedModel[expressionNames.at(i)] = values.at(i);
|
||||
@ -1165,7 +1164,7 @@ void BMC::checkBooleanNotConstant(
|
||||
Expression const& _condition,
|
||||
smtutil::Expression const& _constraints,
|
||||
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.
|
||||
@ -1198,7 +1197,7 @@ void BMC::checkBooleanNotConstant(
|
||||
m_errorReporter.warning(2512_error, _condition.location(), "BMC: Condition unreachable.", SMTEncoder::callStackMessage(_callStack));
|
||||
else
|
||||
{
|
||||
string description;
|
||||
std::string description;
|
||||
if (positiveResult == smtutil::CheckResult::SATISFIABLE)
|
||||
{
|
||||
solAssert(negatedResult == smtutil::CheckResult::UNSATISFIABLE, "");
|
||||
@ -1219,17 +1218,17 @@ void BMC::checkBooleanNotConstant(
|
||||
}
|
||||
}
|
||||
|
||||
pair<smtutil::CheckResult, vector<string>>
|
||||
BMC::checkSatisfiableAndGenerateModel(vector<smtutil::Expression> const& _expressionsToEvaluate)
|
||||
std::pair<smtutil::CheckResult, std::vector<std::string>>
|
||||
BMC::checkSatisfiableAndGenerateModel(std::vector<smtutil::Expression> const& _expressionsToEvaluate)
|
||||
{
|
||||
smtutil::CheckResult result;
|
||||
vector<string> values;
|
||||
std::vector<std::string> values;
|
||||
try
|
||||
{
|
||||
if (m_settings.printQuery)
|
||||
{
|
||||
auto portfolio = dynamic_cast<smtutil::SMTPortfolio*>(m_interface.get());
|
||||
string smtlibCode = portfolio->dumpQuery(_expressionsToEvaluate);
|
||||
std::string smtlibCode = portfolio->dumpQuery(_expressionsToEvaluate);
|
||||
m_errorReporter.info(
|
||||
6240_error,
|
||||
"BMC: Requested query:\n" + smtlibCode
|
||||
@ -1239,14 +1238,14 @@ BMC::checkSatisfiableAndGenerateModel(vector<smtutil::Expression> const& _expres
|
||||
}
|
||||
catch (smtutil::SolverError const& _e)
|
||||
{
|
||||
string description("BMC: Error querying SMT solver");
|
||||
std::string description("BMC: Error querying SMT solver");
|
||||
if (_e.comment())
|
||||
description += ": " + *_e.comment();
|
||||
m_errorReporter.warning(8140_error, description);
|
||||
result = smtutil::CheckResult::ERROR;
|
||||
}
|
||||
|
||||
for (string& value: values)
|
||||
for (std::string& value: values)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@ -51,7 +51,6 @@
|
||||
#include <charconv>
|
||||
#include <queue>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
@ -63,7 +62,7 @@ CHC::CHC(
|
||||
EncodingContext& _context,
|
||||
UniqueErrorReporter& _errorReporter,
|
||||
UniqueErrorReporter& _unsupportedErrorReporter,
|
||||
map<util::h256, string> const& _smtlib2Responses,
|
||||
std::map<util::h256, std::string> const& _smtlib2Responses,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
ModelCheckerSettings _settings,
|
||||
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()))
|
||||
return smtlib2->unhandledQueries();
|
||||
@ -213,7 +212,7 @@ void CHC::endVisit(ContractDefinition const& _contract)
|
||||
auto baseConstructor = base->constructor();
|
||||
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();
|
||||
solAssert(params.size() == args.size(), "");
|
||||
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 && 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;
|
||||
}
|
||||
|
||||
@ -433,7 +432,7 @@ bool CHC::visit(WhileStatement const& _while)
|
||||
solAssert(m_currentFunction, "");
|
||||
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 loopBodyBlock = createBlock(&_while.body(), PredicateType::FunctionBlock, namePrefix + "_body_");
|
||||
auto afterLoopBlock = createBlock(&functionBody, PredicateType::FunctionBlock);
|
||||
@ -622,8 +621,8 @@ void CHC::endVisit(IndexRangeAccess const& _range)
|
||||
{
|
||||
createExpr(_range);
|
||||
|
||||
auto baseArray = dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range.baseExpression()));
|
||||
auto sliceArray = dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range));
|
||||
auto baseArray = std::dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range.baseExpression()));
|
||||
auto sliceArray = std::dynamic_pointer_cast<SymbolicArrayVariable>(m_context.expression(_range));
|
||||
solAssert(baseArray && sliceArray, "");
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
for (auto const* var: _contract.stateVariables())
|
||||
@ -879,8 +878,8 @@ void CHC::nondetCall(ContractDefinition const& _contract, VariableDeclaration co
|
||||
&_var,
|
||||
m_currentContract
|
||||
);
|
||||
auto postCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables(_contract);
|
||||
vector<smtutil::Expression> stateExprs{error, address, state().abi(), state().crypto()};
|
||||
auto postCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables(_contract);
|
||||
std::vector<smtutil::Expression> stateExprs{error, address, state().abi(), state().crypto()};
|
||||
|
||||
auto nondet = (*m_nondetInterfaces.at(&_contract))(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))
|
||||
decreaseBalanceFromOptionsValue(*value);
|
||||
|
||||
auto preCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables();
|
||||
auto preCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables();
|
||||
|
||||
if (!usesStaticCall(_funCall))
|
||||
{
|
||||
@ -962,8 +961,8 @@ void CHC::externalFunctionCall(FunctionCall const& _funCall)
|
||||
PredicateType::ExternalCallUntrusted,
|
||||
&_funCall
|
||||
);
|
||||
auto postCallState = vector<smtutil::Expression>{state().state()} + currentStateVariables();
|
||||
vector<smtutil::Expression> stateExprs{error, state().thisAddress(), state().abi(), state().crypto()};
|
||||
auto postCallState = std::vector<smtutil::Expression>{state().state()} + currentStateVariables();
|
||||
std::vector<smtutil::Expression> stateExprs{error, state().thisAddress(), state().abi(), state().crypto()};
|
||||
|
||||
auto nondet = (*m_nondetInterfaces.at(m_currentContract))(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()));
|
||||
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, "");
|
||||
|
||||
verificationTargetEncountered(&_arrayPop, VerificationTargetType::PopEmptyArray, symbArray->length() <= 0);
|
||||
@ -1089,7 +1088,7 @@ void CHC::makeOutOfBoundsVerificationTarget(IndexAccess const& _indexAccess)
|
||||
|
||||
auto baseType = _indexAccess.baseExpression().annotation().type;
|
||||
|
||||
optional<smtutil::Expression> length;
|
||||
std::optional<smtutil::Expression> length;
|
||||
if (smt::isArray(*baseType))
|
||||
length = dynamic_cast<smt::SymbolicArrayVariable const&>(
|
||||
*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))
|
||||
length = smtutil::Expression(static_cast<size_t>(type->numBytes()));
|
||||
|
||||
optional<smtutil::Expression> target;
|
||||
std::optional<smtutil::Expression> target;
|
||||
if (
|
||||
auto index = _indexAccess.indexExpression();
|
||||
index && length
|
||||
@ -1108,7 +1107,7 @@ void CHC::makeOutOfBoundsVerificationTarget(IndexAccess const& _indexAccess)
|
||||
verificationTargetEncountered(&_indexAccess, VerificationTargetType::OutOfBounds, *target);
|
||||
}
|
||||
|
||||
pair<smtutil::Expression, smtutil::Expression> CHC::arithmeticOperation(
|
||||
std::pair<smtutil::Expression, smtutil::Expression> CHC::arithmeticOperation(
|
||||
Token _op,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
@ -1192,7 +1191,7 @@ void CHC::resetSourceAnalysis()
|
||||
solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld);
|
||||
|
||||
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());
|
||||
solAssert(smtlib2Interface, "");
|
||||
@ -1249,9 +1248,9 @@ void CHC::setCurrentBlock(Predicate const& _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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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}
|
||||
};
|
||||
if (options.count(_option))
|
||||
@ -1283,15 +1282,15 @@ optional<CHC::CHCNatspecOption> CHC::natspecOptionFromString(string const& _opti
|
||||
return {};
|
||||
}
|
||||
|
||||
set<CHC::CHCNatspecOption> CHC::smtNatspecTags(FunctionDefinition const& _function)
|
||||
std::set<CHC::CHCNatspecOption> CHC::smtNatspecTags(FunctionDefinition const& _function)
|
||||
{
|
||||
set<CHC::CHCNatspecOption> options;
|
||||
string smtStr = "custom:smtchecker";
|
||||
std::set<CHC::CHCNatspecOption> options;
|
||||
std::string smtStr = "custom:smtchecker";
|
||||
bool errorSeen = false;
|
||||
for (auto const& [tag, value]: _function.annotation().docTags)
|
||||
if (tag == smtStr)
|
||||
{
|
||||
string const& content = value.content;
|
||||
std::string const& content = value.content;
|
||||
if (auto option = natspecOptionFromString(content))
|
||||
options.insert(*option);
|
||||
else if (!errorSeen)
|
||||
@ -1327,7 +1326,7 @@ SortPointer CHC::sort(ASTNode const* _node)
|
||||
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);
|
||||
m_interface->registerRelation(block->functor());
|
||||
@ -1339,7 +1338,7 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
|
||||
for (auto const& node: _source.nodes())
|
||||
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_nondetInterfaces[contract] = createSymbolicBlock(nondetInterfaceSort(*contract, state()), "nondet_interface_" + uniquePrefix() + "_" + suffix, PredicateType::NondetInterface, contract, contract);
|
||||
m_constructorSummaries[contract] = createConstructorBlock(*contract, "summary_constructor");
|
||||
@ -1385,10 +1384,10 @@ void CHC::defineInterfacesAndSummaries(SourceUnit const& _source)
|
||||
auto errorPost = errorFlag().increaseIndex();
|
||||
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 +
|
||||
applyMap(function->parameters(), [this](auto _var) { return valueAtIndex(*_var, 0); }) +
|
||||
vector<smtutil::Expression>{state().state(2)} +
|
||||
std::vector<smtutil::Expression>{state().state(2)} +
|
||||
state2 +
|
||||
applyMap(function->parameters(), [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.
|
||||
// So the only constraint we can add here is that the balance of
|
||||
// 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"));
|
||||
// Assume that address(this).balance cannot overflow.
|
||||
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);
|
||||
}
|
||||
|
||||
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(
|
||||
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(
|
||||
constructorSort(_contract, state()),
|
||||
@ -1622,7 +1621,7 @@ void CHC::createErrorBlock()
|
||||
{
|
||||
m_errorPredicate = createSymbolicBlock(
|
||||
arity0FunctionSort(),
|
||||
"error_target_" + to_string(m_context.newUniqueId()),
|
||||
"error_target_" + std::to_string(m_context.newUniqueId()),
|
||||
PredicateType::Error
|
||||
);
|
||||
m_interface->registerRelation(m_errorPredicate->functor());
|
||||
@ -1650,18 +1649,18 @@ smtutil::Expression CHC::initialConstraints(ContractDefinition const& _contract,
|
||||
return conj;
|
||||
}
|
||||
|
||||
vector<smtutil::Expression> CHC::initialStateVariables()
|
||||
std::vector<smtutil::Expression> CHC::initialStateVariables()
|
||||
{
|
||||
return stateVariablesAtIndex(0);
|
||||
}
|
||||
|
||||
vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index)
|
||||
std::vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index)
|
||||
{
|
||||
solAssert(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(
|
||||
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, "");
|
||||
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); });
|
||||
}
|
||||
|
||||
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 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))
|
||||
{
|
||||
prefix += TokenTraits::toString(funDef->kind());
|
||||
@ -1701,7 +1700,7 @@ string CHC::predicateName(ASTNode const* _node, ContractDefinition const* _contr
|
||||
|
||||
auto contract = _contract ? _contract : m_currentContract;
|
||||
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)
|
||||
@ -1756,7 +1755,7 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
|
||||
solAssert(false, "Unreachable!");
|
||||
};
|
||||
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& hierarchy = m_currentContract->annotation().linearizedBaseContracts;
|
||||
@ -1773,7 +1772,7 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
|
||||
for (auto const& var: stateVariablesIncludingInheritedAndPrivate(*contract))
|
||||
m_context.variable(*var)->increaseIndex();
|
||||
}
|
||||
args += vector<smtutil::Expression>{state().state()};
|
||||
args += std::vector<smtutil::Expression>{state().state()};
|
||||
args += currentStateVariables(*contract);
|
||||
|
||||
for (auto var: function->parameters() + function->returnParameters())
|
||||
@ -1798,12 +1797,12 @@ smtutil::Expression CHC::predicate(FunctionCall const& _funCall)
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
smtutil::Expression invariant(true);
|
||||
@ -1812,13 +1811,13 @@ tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query
|
||||
{
|
||||
auto smtLibInterface = dynamic_cast<CHCSmtLib2Interface*>(m_interface.get());
|
||||
solAssert(smtLibInterface, "Requested to print queries but CHCSmtLib2Interface not available");
|
||||
string smtLibCode = smtLibInterface->dumpQuery(_query);
|
||||
std::string smtLibCode = smtLibInterface->dumpQuery(_query);
|
||||
m_errorReporter.info(
|
||||
2339_error,
|
||||
"CHC: Requested query:\n" + smtLibCode
|
||||
);
|
||||
}
|
||||
tie(result, invariant, cex) = m_interface->query(_query);
|
||||
std::tie(result, invariant, cex) = m_interface->query(_query);
|
||||
switch (result)
|
||||
{
|
||||
case CheckResult::SATISFIABLE:
|
||||
@ -1836,7 +1835,7 @@ tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query
|
||||
CheckResult resultNoOpt;
|
||||
smtutil::Expression invariantNoOpt(true);
|
||||
CHCSolverInterface::CexGraph cexNoOpt;
|
||||
tie(resultNoOpt, invariantNoOpt, cexNoOpt) = m_interface->query(_query);
|
||||
std::tie(resultNoOpt, invariantNoOpt, cexNoOpt) = m_interface->query(_query);
|
||||
|
||||
if (resultNoOpt == CheckResult::SATISFIABLE)
|
||||
cex = std::move(cexNoOpt);
|
||||
@ -1902,7 +1901,7 @@ void CHC::verificationTargetEncountered(
|
||||
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)
|
||||
{
|
||||
@ -1950,7 +1949,7 @@ void CHC::checkVerificationTargets()
|
||||
// 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
|
||||
// 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)
|
||||
{
|
||||
auto functionTargets = transactionVerificationTargetsIds(function);
|
||||
@ -1959,7 +1958,7 @@ void CHC::checkVerificationTargets()
|
||||
targetEntryPoints[id].push_back(placeholder);
|
||||
}
|
||||
|
||||
set<unsigned> checkedErrorIds;
|
||||
std::set<unsigned> checkedErrorIds;
|
||||
for (auto const& [targetId, placeholders]: targetEntryPoints)
|
||||
{
|
||||
auto const& target = m_verificationTargets.at(targetId);
|
||||
@ -1988,7 +1987,7 @@ void CHC::checkVerificationTargets()
|
||||
5840_error,
|
||||
{},
|
||||
"CHC: " +
|
||||
to_string(m_unprovedTargets.size()) +
|
||||
std::to_string(m_unprovedTargets.size()) +
|
||||
" verification condition(s) could not be proved." +
|
||||
" Enable the model checker option \"show unproved\" to see all of them." +
|
||||
" Consider choosing a specific contract to be verified in order to reduce the solving problems." +
|
||||
@ -1999,7 +1998,7 @@ void CHC::checkVerificationTargets()
|
||||
m_errorReporter.info(
|
||||
1391_error,
|
||||
"CHC: " +
|
||||
to_string(m_safeTargets.size()) +
|
||||
std::to_string(m_safeTargets.size()) +
|
||||
" verification condition(s) proved safe!" +
|
||||
" 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())
|
||||
{
|
||||
string msg;
|
||||
std::string msg;
|
||||
for (auto pred: m_invariants | ranges::views::keys)
|
||||
{
|
||||
ASTNode const* node = pred->programNode();
|
||||
string what;
|
||||
std::string what;
|
||||
if (auto contract = dynamic_cast<ContractDefinition const*>(node))
|
||||
what = contract->fullyQualifiedName();
|
||||
else
|
||||
solAssert(false, "");
|
||||
|
||||
string invType;
|
||||
std::string invType;
|
||||
if (pred->type() == PredicateType::Interface)
|
||||
invType = "Contract invariant(s)";
|
||||
else if (pred->type() == PredicateType::NondetInterface)
|
||||
@ -2038,16 +2037,16 @@ void CHC::checkVerificationTargets()
|
||||
for (auto const& inv: m_invariants.at(pred))
|
||||
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";
|
||||
for (auto const& [id, target]: m_verificationTargets)
|
||||
if (!seenErrors.count(target.errorId))
|
||||
{
|
||||
seenErrors.insert(target.errorId);
|
||||
string loc = 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";
|
||||
std::string loc = std::string(m_charStreamProvider.charStream(*target.errorNode->location().sourceName).text(target.errorNode->location()));
|
||||
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.
|
||||
// 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.
|
||||
set<unsigned> allErrorIds;
|
||||
std::set<unsigned> allErrorIds;
|
||||
for (auto const& entry: m_functionTargetIds)
|
||||
for (unsigned id: entry.second)
|
||||
allErrorIds.insert(id);
|
||||
|
||||
set<unsigned> unreachableErrorIds;
|
||||
std::set<unsigned> unreachableErrorIds;
|
||||
set_difference(
|
||||
allErrorIds.begin(),
|
||||
allErrorIds.end(),
|
||||
@ -2077,10 +2076,10 @@ void CHC::checkVerificationTargets()
|
||||
|
||||
void CHC::checkAndReportTarget(
|
||||
CHCVerificationTarget const& _target,
|
||||
vector<CHCQueryPlaceholder> const& _placeholders,
|
||||
std::vector<CHCQueryPlaceholder> const& _placeholders,
|
||||
ErrorId _errorReporterId,
|
||||
string _satMsg,
|
||||
string _unknownMsg
|
||||
std::string _satMsg,
|
||||
std::string _unknownMsg
|
||||
)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_safeTargets[_target.errorNode].insert(_target);
|
||||
set<Predicate const*> predicates;
|
||||
std::set<Predicate const*> predicates;
|
||||
for (auto const* pred: m_interfaces | ranges::views::values)
|
||||
predicates.insert(pred);
|
||||
for (auto const* pred: m_nondetInterfaces | ranges::views::values)
|
||||
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)
|
||||
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
|
||||
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)
|
||||
if (node.name == _root)
|
||||
{
|
||||
@ -2165,8 +2164,8 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
||||
if (!rootId)
|
||||
return {};
|
||||
|
||||
vector<string> path;
|
||||
string localState;
|
||||
std::vector<std::string> path;
|
||||
std::string localState;
|
||||
|
||||
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())
|
||||
localState += outStr + "\n";
|
||||
|
||||
optional<unsigned> localErrorId;
|
||||
std::optional<unsigned> localErrorId;
|
||||
solidity::util::BreadthFirstSearch<unsigned> bfs{{summaryId}};
|
||||
bfs.run([&](auto _nodeId, auto&& _addChild) {
|
||||
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 pred = nodePred(node);
|
||||
auto parentPred = nodePred(parent);
|
||||
@ -2254,7 +2253,7 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
||||
|
||||
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())
|
||||
calls.front() += " -- internal call";
|
||||
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");
|
||||
}
|
||||
|
||||
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 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.
|
||||
// For most predicates, this actually doesn't matter.
|
||||
// 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);
|
||||
};
|
||||
|
||||
queue<pair<unsigned, unsigned>> q;
|
||||
std::queue<std::pair<unsigned, unsigned>> q;
|
||||
q.push({_root, _root});
|
||||
while (!q.empty())
|
||||
{
|
||||
@ -2334,19 +2333,19 @@ map<unsigned, vector<unsigned>> CHC::summaryCalls(CHCSolverInterface::CexGraph c
|
||||
root = 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});
|
||||
}
|
||||
|
||||
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) {
|
||||
vector<string> args = applyMap(
|
||||
std::vector<std::string> args = applyMap(
|
||||
_node.arguments,
|
||||
[&](auto const& arg) { return arg.name; }
|
||||
);
|
||||
@ -2361,14 +2360,14 @@ string CHC::cex2dot(CHCSolverInterface::CexGraph const& _cex)
|
||||
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()
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
#include <libsolidity/formal/SymbolicTypes.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend::smt;
|
||||
@ -51,7 +50,7 @@ unsigned EncodingContext::newUniqueId()
|
||||
|
||||
/// Variables.
|
||||
|
||||
shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl)
|
||||
std::shared_ptr<SymbolicVariable> EncodingContext::variable(frontend::VariableDeclaration const& _varDecl)
|
||||
{
|
||||
solAssert(knownVariable(_varDecl), "");
|
||||
return m_variables[&_varDecl];
|
||||
@ -61,7 +60,7 @@ bool EncodingContext::createVariable(frontend::VariableDeclaration const& _varDe
|
||||
{
|
||||
solAssert(!knownVariable(_varDecl), "");
|
||||
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);
|
||||
return result.first;
|
||||
}
|
||||
@ -77,13 +76,13 @@ void EncodingContext::resetVariable(frontend::VariableDeclaration const& _variab
|
||||
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)
|
||||
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)
|
||||
{
|
||||
@ -127,14 +126,14 @@ void EncodingContext::setUnknownValue(SymbolicVariable& _variable)
|
||||
|
||||
/// Expressions
|
||||
|
||||
shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e)
|
||||
std::shared_ptr<SymbolicVariable> EncodingContext::expression(frontend::Expression const& _e)
|
||||
{
|
||||
if (!knownExpression(_e))
|
||||
createExpression(_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, "");
|
||||
if (knownExpression(_e))
|
||||
@ -149,7 +148,7 @@ bool EncodingContext::createExpression(frontend::Expression const& _e, shared_pt
|
||||
}
|
||||
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);
|
||||
return result.first;
|
||||
}
|
||||
@ -162,13 +161,13 @@ bool EncodingContext::knownExpression(frontend::Expression const& _e) const
|
||||
|
||||
/// 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), "");
|
||||
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), "");
|
||||
auto result = newSymbolicVariable(*_expr.annotation().type, _name, *this);
|
||||
@ -177,7 +176,7 @@ bool EncodingContext::createGlobalSymbol(string const& _name, frontend::Expressi
|
||||
return result.first;
|
||||
}
|
||||
|
||||
bool EncodingContext::knownGlobalSymbol(string const& _var) const
|
||||
bool EncodingContext::knownGlobalSymbol(std::string const& _var) const
|
||||
{
|
||||
return m_globalContext.count(_var);
|
||||
}
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using boost::algorithm::starts_with;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
@ -42,7 +41,7 @@ namespace solidity::frontend::smt
|
||||
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;
|
||||
|
||||
@ -63,9 +62,9 @@ string formatDatatypeAccessor(smtutil::Expression const& _expr, vector<string> c
|
||||
if (op == "dt_accessor_ecrecover")
|
||||
return "ecrecover";
|
||||
|
||||
string accessorStr = "accessor_";
|
||||
std::string accessorStr = "accessor_";
|
||||
// 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, "");
|
||||
|
||||
if (type == "length")
|
||||
@ -87,22 +86,22 @@ string formatDatatypeAccessor(smtutil::Expression const& _expr, vector<string> c
|
||||
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, ", ") + ")";
|
||||
}
|
||||
|
||||
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 + " ") + ")";
|
||||
}
|
||||
|
||||
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")
|
||||
{
|
||||
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"))
|
||||
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);
|
||||
}
|
||||
|
||||
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")
|
||||
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,
|
||||
// but we should support them in the future.
|
||||
@ -135,7 +134,7 @@ smtutil::Expression substitute(smtutil::Expression _from, map<string, string> co
|
||||
return _from;
|
||||
}
|
||||
|
||||
string toSolidityStr(smtutil::Expression const& _expr)
|
||||
std::string toSolidityStr(smtutil::Expression const& _expr)
|
||||
{
|
||||
auto const& op = _expr.name;
|
||||
|
||||
@ -150,7 +149,7 @@ string toSolidityStr(smtutil::Expression const& _expr)
|
||||
return formatDatatypeAccessor(_expr, strArgs);
|
||||
|
||||
// Infix operators with format replacements.
|
||||
static map<string, string> const infixOps{
|
||||
static std::map<std::string, std::string> const infixOps{
|
||||
{"and", "&&"},
|
||||
{"or", "||"},
|
||||
{"implies", "=>"},
|
||||
@ -170,7 +169,7 @@ string toSolidityStr(smtutil::Expression const& _expr)
|
||||
if (infixOps.count(op))
|
||||
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))
|
||||
return formatArrayOp(_expr, strArgs);
|
||||
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace std;
|
||||
using boost::algorithm::starts_with;
|
||||
using namespace solidity;
|
||||
using namespace solidity::smtutil;
|
||||
@ -34,19 +33,19 @@ using 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,
|
||||
set<Predicate const*> const& _predicates,
|
||||
std::set<Predicate const*> const& _predicates,
|
||||
ModelCheckerInvariants const& _invariantsSetting
|
||||
)
|
||||
{
|
||||
set<string> targets;
|
||||
std::set<std::string> targets;
|
||||
if (_invariantsSetting.has(InvariantType::Contract))
|
||||
targets.insert("interface_");
|
||||
if (_invariantsSetting.has(InvariantType::Reentrancy))
|
||||
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.
|
||||
util::BreadthFirstSearch<smtutil::Expression const*>{{&_proof}}.run([&](auto&& _expr, auto&& _addChild) {
|
||||
if (_expr->name == "=")
|
||||
@ -63,7 +62,7 @@ map<Predicate const*, set<string>> collectInvariants(
|
||||
_addChild(&arg);
|
||||
});
|
||||
|
||||
map<Predicate const*, set<string>> invariants;
|
||||
std::map<Predicate const*, std::set<std::string>> invariants;
|
||||
for (auto pred: _predicates)
|
||||
{
|
||||
auto predName = pred->functor().name;
|
||||
@ -74,7 +73,7 @@ map<Predicate const*, set<string>> collectInvariants(
|
||||
|
||||
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));
|
||||
// No point in reporting true/false as invariants.
|
||||
if (!ignore.count(r.name))
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include <range/v3/algorithm/any_of.hpp>
|
||||
#include <range/v3/view.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
@ -41,7 +40,7 @@ using namespace solidity::smtutil;
|
||||
ModelChecker::ModelChecker(
|
||||
ErrorReporter& _errorReporter,
|
||||
langutil::CharStreamProvider const& _charStreamProvider,
|
||||
map<h256, string> const& _smtlib2Responses,
|
||||
std::map<h256, std::string> const& _smtlib2Responses,
|
||||
ModelCheckerSettings _settings,
|
||||
ReadCallback::Callback const& _smtCallback
|
||||
):
|
||||
@ -54,19 +53,19 @@ ModelChecker::ModelChecker(
|
||||
}
|
||||
|
||||
// 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 _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 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());
|
||||
|
||||
// Requested sources
|
||||
@ -100,7 +99,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
|
||||
{
|
||||
PragmaDirective const* smtPragma = nullptr;
|
||||
for (auto node: _source.nodes())
|
||||
if (auto pragma = dynamic_pointer_cast<PragmaDirective>(node))
|
||||
if (auto pragma = std::dynamic_pointer_cast<PragmaDirective>(node))
|
||||
if (
|
||||
pragma->literals().size() >= 2 &&
|
||||
pragma->literals().at(1) == "SMTChecker"
|
||||
@ -125,7 +124,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
|
||||
if (m_settings.engine.chc)
|
||||
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& target: targets)
|
||||
@ -147,7 +146,7 @@ void ModelChecker::analyze(SourceUnit const& _source)
|
||||
5724_error,
|
||||
{},
|
||||
"SMTChecker: " +
|
||||
to_string(m_unsupportedErrorReporter.errors().size()) +
|
||||
std::to_string(m_unsupportedErrorReporter.errors().size()) +
|
||||
" unsupported language feature(s)."
|
||||
" 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();
|
||||
}
|
||||
|
||||
vector<string> ModelChecker::unhandledQueries()
|
||||
std::vector<std::string> ModelChecker::unhandledQueries()
|
||||
{
|
||||
return m_bmc.unhandledQueries() + m_chc.unhandledQueries();
|
||||
}
|
||||
@ -212,7 +211,7 @@ SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, Er
|
||||
SourceLocation(),
|
||||
"Solver z3 was selected for SMTChecker but it is not available."
|
||||
#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
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,18 +21,17 @@
|
||||
#include <optional>
|
||||
#include <range/v3/view.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
map<string, InvariantType> const ModelCheckerInvariants::validInvariants{
|
||||
std::map<std::string, InvariantType> const ModelCheckerInvariants::validInvariants{
|
||||
{"contract", InvariantType::Contract},
|
||||
{"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")
|
||||
{
|
||||
// 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)
|
||||
chosenInvs.insert(v);
|
||||
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))
|
||||
return {};
|
||||
@ -51,7 +50,7 @@ std::optional<ModelCheckerInvariants> ModelCheckerInvariants::fromString(string
|
||||
return ModelCheckerInvariants{chosenInvs};
|
||||
}
|
||||
|
||||
bool ModelCheckerInvariants::setFromString(string const& _inv)
|
||||
bool ModelCheckerInvariants::setFromString(std::string const& _inv)
|
||||
{
|
||||
if (!validInvariants.count(_inv))
|
||||
return false;
|
||||
@ -60,7 +59,7 @@ bool ModelCheckerInvariants::setFromString(string const& _inv)
|
||||
}
|
||||
|
||||
using TargetType = VerificationTargetType;
|
||||
map<string, TargetType> const ModelCheckerTargets::targetStrings{
|
||||
std::map<std::string, TargetType> const ModelCheckerTargets::targetStrings{
|
||||
{"constantCondition", TargetType::ConstantCondition},
|
||||
{"underflow", TargetType::Underflow},
|
||||
{"overflow", TargetType::Overflow},
|
||||
@ -71,7 +70,7 @@ map<string, TargetType> const ModelCheckerTargets::targetStrings{
|
||||
{"outOfBounds", TargetType::OutOfBounds}
|
||||
};
|
||||
|
||||
map<TargetType, string> const ModelCheckerTargets::targetTypeToString{
|
||||
std::map<TargetType, std::string> const ModelCheckerTargets::targetTypeToString{
|
||||
{TargetType::ConstantCondition, "Constant condition"},
|
||||
{TargetType::Underflow, "Underflow"},
|
||||
{TargetType::Overflow, "Overflow"},
|
||||
@ -82,9 +81,9 @@ map<TargetType, string> const ModelCheckerTargets::targetTypeToString{
|
||||
{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")
|
||||
{
|
||||
bool all = _targets == "all";
|
||||
@ -96,7 +95,7 @@ std::optional<ModelCheckerTargets> ModelCheckerTargets::fromString(string const&
|
||||
}
|
||||
}
|
||||
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))
|
||||
return {};
|
||||
@ -106,7 +105,7 @@ std::optional<ModelCheckerTargets> ModelCheckerTargets::fromString(string const&
|
||||
return ModelCheckerTargets{chosenTargets};
|
||||
}
|
||||
|
||||
bool ModelCheckerTargets::setFromString(string const& _target)
|
||||
bool ModelCheckerTargets::setFromString(std::string const& _target)
|
||||
{
|
||||
if (!targetStrings.count(_target))
|
||||
return false;
|
||||
@ -114,15 +113,15 @@ bool ModelCheckerTargets::setFromString(string const& _target)
|
||||
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")
|
||||
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())
|
||||
return {};
|
||||
chosen[names.at(0)].insert(names.at(1));
|
||||
@ -131,7 +130,7 @@ std::optional<ModelCheckerContracts> ModelCheckerContracts::fromString(string co
|
||||
return ModelCheckerContracts{chosen};
|
||||
}
|
||||
|
||||
std::optional<ModelCheckerExtCalls> ModelCheckerExtCalls::fromString(string const& _mode)
|
||||
std::optional<ModelCheckerExtCalls> ModelCheckerExtCalls::fromString(std::string const& _mode)
|
||||
{
|
||||
if (_mode == "untrusted")
|
||||
return ModelCheckerExtCalls{Mode::UNTRUSTED};
|
||||
|
||||
@ -31,27 +31,26 @@
|
||||
#include <range/v3/view.hpp>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
using boost::algorithm::starts_with;
|
||||
using namespace solidity;
|
||||
using namespace solidity::smtutil;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::frontend::smt;
|
||||
|
||||
map<string, Predicate> Predicate::m_predicates;
|
||||
std::map<std::string, Predicate> Predicate::m_predicates;
|
||||
|
||||
Predicate const* Predicate::create(
|
||||
SortPointer _sort,
|
||||
string _name,
|
||||
std::string _name,
|
||||
PredicateType _type,
|
||||
EncodingContext& _context,
|
||||
ASTNode const* _node,
|
||||
ContractDefinition const* _contractContext,
|
||||
vector<ScopeOpener const*> _scopeStack
|
||||
std::vector<ScopeOpener const*> _scopeStack
|
||||
)
|
||||
{
|
||||
smt::SymbolicFunctionVariable predicate{_sort, std::move(_name), _context};
|
||||
string functorName = predicate.currentName();
|
||||
std::string functorName = predicate.currentName();
|
||||
solAssert(!m_predicates.count(functorName), "");
|
||||
return &m_predicates.emplace(
|
||||
std::piecewise_construct,
|
||||
@ -65,7 +64,7 @@ Predicate::Predicate(
|
||||
PredicateType _type,
|
||||
ASTNode const* _node,
|
||||
ContractDefinition const* _contractContext,
|
||||
vector<ScopeOpener const*> _scopeStack
|
||||
std::vector<ScopeOpener const*> _scopeStack
|
||||
):
|
||||
m_predicate(std::move(_predicate)),
|
||||
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);
|
||||
}
|
||||
@ -85,7 +84,7 @@ void Predicate::reset()
|
||||
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);
|
||||
}
|
||||
@ -149,12 +148,12 @@ VariableDeclaration const* Predicate::programVariable() const
|
||||
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)
|
||||
return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*m_contractContext);
|
||||
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool Predicate::isSummary() const
|
||||
@ -211,8 +210,8 @@ bool Predicate::isNondetInterface() const
|
||||
return m_type == PredicateType::NondetInterface;
|
||||
}
|
||||
|
||||
string Predicate::formatSummaryCall(
|
||||
vector<smtutil::Expression> const& _args,
|
||||
std::string Predicate::formatSummaryCall(
|
||||
std::vector<smtutil::Expression> const& _args,
|
||||
langutil::CharStreamProvider const& _charStreamProvider,
|
||||
bool _appendTxVars
|
||||
) const
|
||||
@ -225,7 +224,7 @@ string Predicate::formatSummaryCall(
|
||||
if (auto funCall = programFunctionCall())
|
||||
{
|
||||
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
|
||||
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).
|
||||
/// Here we are interested in preInputVars to format the function call.
|
||||
|
||||
string txModel;
|
||||
std::string txModel;
|
||||
|
||||
if (_appendTxVars)
|
||||
{
|
||||
set<string> txVars;
|
||||
std::set<std::string> txVars;
|
||||
if (isFunctionSummary())
|
||||
{
|
||||
solAssert(programFunction(), "");
|
||||
@ -276,7 +275,7 @@ string Predicate::formatSummaryCall(
|
||||
return true;
|
||||
}
|
||||
|
||||
set<string> txVars;
|
||||
std::set<std::string> txVars;
|
||||
} txVarsVisitor;
|
||||
|
||||
if (auto fun = programFunction())
|
||||
@ -287,7 +286,7 @@ string Predicate::formatSummaryCall(
|
||||
|
||||
// Here we are interested in txData from the summary predicate.
|
||||
auto txValues = readTxVars(_args.at(4));
|
||||
vector<string> values;
|
||||
std::vector<std::string> values;
|
||||
for (auto const& _var: txVars)
|
||||
if (auto v = txValues.at(_var))
|
||||
values.push_back(_var + ": " + *v);
|
||||
@ -309,8 +308,8 @@ string Predicate::formatSummaryCall(
|
||||
solAssert(first >= _args.begin() && first <= _args.end(), "");
|
||||
solAssert(last >= _args.begin() && last <= _args.end(), "");
|
||||
auto inTypes = SMTEncoder::replaceUserTypes(FunctionType(*fun).parameterTypes());
|
||||
vector<optional<string>> functionArgsCex = formatExpressions(vector<smtutil::Expression>(first, last), inTypes);
|
||||
vector<string> functionArgs;
|
||||
std::vector<std::optional<std::string>> functionArgsCex = formatExpressions(std::vector<smtutil::Expression>(first, last), inTypes);
|
||||
std::vector<std::string> functionArgs;
|
||||
|
||||
auto const& params = fun->parameters();
|
||||
solAssert(params.size() == functionArgsCex.size(), "");
|
||||
@ -320,12 +319,12 @@ string Predicate::formatSummaryCall(
|
||||
else
|
||||
functionArgs.emplace_back(params[i]->name());
|
||||
|
||||
string fName = fun->isConstructor() ? "constructor" :
|
||||
std::string fName = fun->isConstructor() ? "constructor" :
|
||||
fun->isFallback() ? "fallback" :
|
||||
fun->isReceive() ? "receive" :
|
||||
fun->name();
|
||||
|
||||
string prefix;
|
||||
std::string prefix;
|
||||
if (fun->isFree())
|
||||
prefix = !fun->sourceUnitName().empty() ? (fun->sourceUnitName() + ":") : "";
|
||||
else
|
||||
@ -336,7 +335,7 @@ string Predicate::formatSummaryCall(
|
||||
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 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();
|
||||
solAssert(stateVars.has_value(), "");
|
||||
|
||||
vector<smtutil::Expression>::const_iterator stateFirst;
|
||||
vector<smtutil::Expression>::const_iterator stateLast;
|
||||
std::vector<smtutil::Expression>::const_iterator stateFirst;
|
||||
std::vector<smtutil::Expression>::const_iterator stateLast;
|
||||
if (auto const* function = programFunction())
|
||||
{
|
||||
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(stateLast >= _args.begin() && stateLast <= _args.end(), "");
|
||||
|
||||
vector<smtutil::Expression> stateArgs(stateFirst, stateLast);
|
||||
std::vector<smtutil::Expression> stateArgs(stateFirst, stateLast);
|
||||
solAssert(stateArgs.size() == stateVars->size(), "");
|
||||
auto stateTypes = util::applyMap(*stateVars, [&](auto const& _var) { return _var->type(); });
|
||||
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).
|
||||
/// 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(last >= _args.begin() && last <= _args.end(), "");
|
||||
|
||||
vector<smtutil::Expression> inValues(first, last);
|
||||
std::vector<smtutil::Expression> inValues(first, last);
|
||||
solAssert(inValues.size() == inParams.size(), "");
|
||||
auto inTypes = SMTEncoder::replaceUserTypes(FunctionType(*function).parameterTypes());
|
||||
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).
|
||||
/// 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(), "");
|
||||
|
||||
vector<smtutil::Expression> outValues(first, _args.end());
|
||||
std::vector<smtutil::Expression> outValues(first, _args.end());
|
||||
solAssert(outValues.size() == function->returnParameters().size(), "");
|
||||
auto outTypes = SMTEncoder::replaceUserTypes(FunctionType(*function).returnParameterTypes());
|
||||
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:
|
||||
/// 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 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(
|
||||
localVars,
|
||||
@ -442,10 +441,10 @@ pair<vector<optional<string>>, vector<VariableDeclaration const*>> Predicate::lo
|
||||
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;
|
||||
string predName = functor().name;
|
||||
std::map<std::string, std::string> subst;
|
||||
std::string predName = functor().name;
|
||||
|
||||
solAssert(contextContract(), "");
|
||||
auto const& stateVars = SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*contextContract());
|
||||
@ -486,16 +485,16 @@ map<string, string> Predicate::expressionSubstitution(smtutil::Expression const&
|
||||
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(), "");
|
||||
vector<optional<string>> strExprs;
|
||||
std::vector<std::optional<std::string>> strExprs;
|
||||
for (unsigned i = 0; i < _exprs.size(); ++i)
|
||||
strExprs.push_back(expressionToString(_exprs.at(i), _types.at(i)));
|
||||
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))
|
||||
{
|
||||
@ -514,10 +513,10 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
|
||||
// For some reason the code below returns "0x" for "0".
|
||||
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);
|
||||
}
|
||||
catch(out_of_range const&)
|
||||
catch(std::out_of_range const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
catch(invalid_argument const&)
|
||||
catch(std::invalid_argument const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@ -567,12 +566,12 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
|
||||
return {};
|
||||
try
|
||||
{
|
||||
vector<string> array(length);
|
||||
std::vector<std::string> array(length);
|
||||
if (!fillArray(_expr.arguments.at(0), array, arrayType))
|
||||
return {};
|
||||
return "[" + boost::algorithm::join(array, ", ") + "]";
|
||||
}
|
||||
catch (bad_alloc const&)
|
||||
catch (std::bad_alloc const&)
|
||||
{
|
||||
// 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();
|
||||
solAssert(tupleSort.components.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)
|
||||
{
|
||||
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() : ""));
|
||||
}
|
||||
return "{" + boost::algorithm::join(elements, ", ") + "}";
|
||||
@ -597,13 +596,13 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr,
|
||||
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
|
||||
if (_expr.name == "const_array")
|
||||
{
|
||||
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)
|
||||
return false;
|
||||
_array.clear();
|
||||
@ -616,7 +615,7 @@ bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _arr
|
||||
{
|
||||
if (!fillArray(_expr.arguments.at(0), _array, _type))
|
||||
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)
|
||||
return false;
|
||||
// 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);
|
||||
}
|
||||
catch (out_of_range const&)
|
||||
catch (std::out_of_range const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch (invalid_argument const&)
|
||||
catch (std::invalid_argument const&)
|
||||
{
|
||||
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)
|
||||
return false;
|
||||
if (index < _array.size())
|
||||
@ -652,9 +651,9 @@ bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _arr
|
||||
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.chainid", TypeProvider::uint256()},
|
||||
{"block.coinbase", TypeProvider::address()},
|
||||
@ -670,7 +669,7 @@ map<string, optional<string>> Predicate::readTxVars(smtutil::Expression const& _
|
||||
{"tx.gasprice", TypeProvider::uint256()},
|
||||
{"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)
|
||||
vars.emplace(v.first, expressionToString(_tx.arguments.at(i), v.second));
|
||||
return vars;
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
#include <libsolidity/formal/EncodingContext.h>
|
||||
#include <libsolidity/formal/SMTEncoder.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::smtutil;
|
||||
|
||||
@ -30,14 +29,14 @@ namespace solidity::frontend::smt
|
||||
smtutil::Expression interfacePre(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
smtutil::Expression interface(Predicate const& _pred, ContractDefinition const& _contract, EncodingContext& _context)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@ -49,12 +48,12 @@ smtutil::Expression nondetInterface(
|
||||
unsigned _postIdx)
|
||||
{
|
||||
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(
|
||||
stateExprs +
|
||||
vector<smtutil::Expression>{_context.state().state(_preIdx)} +
|
||||
std::vector<smtutil::Expression>{_context.state().state(_preIdx)} +
|
||||
stateVariablesAtIndex(_preIdx, _contract, _context) +
|
||||
vector<smtutil::Expression>{_context.state().state(_postIdx)} +
|
||||
std::vector<smtutil::Expression>{_context.state().state(_postIdx)} +
|
||||
stateVariablesAtIndex(_postIdx, _contract, _context)
|
||||
);
|
||||
}
|
||||
@ -66,7 +65,7 @@ smtutil::Expression constructor(Predicate const& _pred, EncodingContext& _contex
|
||||
return _pred(currentFunctionVariablesForDefinition(*constructor, &contract, _context));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -77,9 +76,9 @@ smtutil::Expression constructorCall(Predicate const& _pred, EncodingContext& _co
|
||||
return _pred(currentFunctionVariablesForCall(*constructor, &contract, _context, _internal));
|
||||
|
||||
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();
|
||||
stateExprs += vector<smtutil::Expression>{state.state()};
|
||||
stateExprs += std::vector<smtutil::Expression>{state.state()};
|
||||
stateExprs += currentStateVariables(contract, _context);
|
||||
stateExprs += newStateVariables(contract, _context);
|
||||
return _pred(stateExprs);
|
||||
@ -117,12 +116,12 @@ smtutil::Expression functionBlock(
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
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,
|
||||
ContractDefinition const* _contract,
|
||||
EncodingContext& _context
|
||||
)
|
||||
{
|
||||
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)};
|
||||
exprs += _contract ? initialStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
||||
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) : std::vector<smtutil::Expression>{};
|
||||
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->valueAtIndex(0); });
|
||||
exprs += vector<smtutil::Expression>{state.state()};
|
||||
exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
||||
exprs += std::vector<smtutil::Expression>{state.state()};
|
||||
exprs += _contract ? currentStateVariables(*_contract, _context) : std::vector<smtutil::Expression>{};
|
||||
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
||||
exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
||||
return exprs;
|
||||
}
|
||||
|
||||
vector<smtutil::Expression> currentFunctionVariablesForCall(
|
||||
std::vector<smtutil::Expression> currentFunctionVariablesForCall(
|
||||
FunctionDefinition const& _function,
|
||||
ContractDefinition const* _contract,
|
||||
EncodingContext& _context,
|
||||
@ -171,20 +170,20 @@ vector<smtutil::Expression> currentFunctionVariablesForCall(
|
||||
)
|
||||
{
|
||||
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()};
|
||||
exprs += _contract ? currentStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
||||
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) : std::vector<smtutil::Expression>{};
|
||||
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
||||
|
||||
state.newState();
|
||||
|
||||
exprs += vector<smtutil::Expression>{state.state()};
|
||||
exprs += _contract ? newStateVariables(*_contract, _context) : vector<smtutil::Expression>{};
|
||||
exprs += std::vector<smtutil::Expression>{state.state()};
|
||||
exprs += _contract ? newStateVariables(*_contract, _context) : std::vector<smtutil::Expression>{};
|
||||
exprs += applyMap(_function.parameters(), [&](auto _var) { return _context.variable(*_var)->increaseIndex(); });
|
||||
exprs += applyMap(_function.returnParameters(), [&](auto _var) { return _context.variable(*_var)->currentValue(); });
|
||||
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) +
|
||||
applyMap(
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
#include <libsolidity/formal/SMTEncoder.h>
|
||||
#include <libsolidity/formal/SymbolicTypes.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::smtutil;
|
||||
|
||||
@ -30,8 +29,8 @@ namespace solidity::frontend::smt
|
||||
|
||||
SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _state)
|
||||
{
|
||||
return make_shared<FunctionSort>(
|
||||
vector<SortPointer>{_state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.stateSort()} + stateSorts(_contract),
|
||||
return std::make_shared<FunctionSort>(
|
||||
std::vector<SortPointer>{_state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.stateSort()} + stateSorts(_contract),
|
||||
SortProvider::boolSort
|
||||
);
|
||||
}
|
||||
@ -39,9 +38,9 @@ SortPointer interfaceSort(ContractDefinition const& _contract, SymbolicState& _s
|
||||
SortPointer nondetInterfaceSort(ContractDefinition const& _contract, SymbolicState& _state)
|
||||
{
|
||||
auto varSorts = stateSorts(_contract);
|
||||
vector<SortPointer> stateSort{_state.stateSort()};
|
||||
return make_shared<FunctionSort>(
|
||||
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort()} +
|
||||
std::vector<SortPointer> stateSort{_state.stateSort()};
|
||||
return std::make_shared<FunctionSort>(
|
||||
std::vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort()} +
|
||||
stateSort +
|
||||
varSorts +
|
||||
stateSort +
|
||||
@ -56,9 +55,9 @@ SortPointer constructorSort(ContractDefinition const& _contract, SymbolicState&
|
||||
return functionSort(*constructor, &_contract, _state);
|
||||
|
||||
auto varSorts = stateSorts(_contract);
|
||||
vector<SortPointer> stateSort{_state.stateSort()};
|
||||
return make_shared<FunctionSort>(
|
||||
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort(), _state.stateSort()} + varSorts + varSorts,
|
||||
std::vector<SortPointer> stateSort{_state.stateSort()};
|
||||
return std::make_shared<FunctionSort>(
|
||||
std::vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort(), _state.stateSort()} + varSorts + varSorts,
|
||||
SortProvider::boolSort
|
||||
);
|
||||
}
|
||||
@ -66,14 +65,14 @@ SortPointer constructorSort(ContractDefinition const& _contract, SymbolicState&
|
||||
SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition const* _contract, SymbolicState& _state)
|
||||
{
|
||||
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 outputSorts = applyMap(_function.returnParameters(), smtSort);
|
||||
return make_shared<FunctionSort>(
|
||||
vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort()} +
|
||||
return std::make_shared<FunctionSort>(
|
||||
std::vector<SortPointer>{_state.errorFlagSort(), _state.thisAddressSort(), _state.abiSort(), _state.cryptoSort(), _state.txSort(), _state.stateSort()} +
|
||||
varSorts +
|
||||
inputSorts +
|
||||
vector<SortPointer>{_state.stateSort()} +
|
||||
std::vector<SortPointer>{_state.stateSort()} +
|
||||
varSorts +
|
||||
inputSorts +
|
||||
outputSorts,
|
||||
@ -83,11 +82,11 @@ SortPointer functionSort(FunctionDefinition const& _function, ContractDefinition
|
||||
|
||||
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, "");
|
||||
|
||||
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),
|
||||
SortProvider::boolSort
|
||||
);
|
||||
@ -95,15 +94,15 @@ SortPointer functionBodySort(FunctionDefinition const& _function, ContractDefini
|
||||
|
||||
SortPointer arity0FunctionSort()
|
||||
{
|
||||
return make_shared<FunctionSort>(
|
||||
vector<SortPointer>(),
|
||||
return std::make_shared<FunctionSort>(
|
||||
std::vector<SortPointer>(),
|
||||
SortProvider::boolSort
|
||||
);
|
||||
}
|
||||
|
||||
/// Helpers
|
||||
|
||||
vector<SortPointer> stateSorts(ContractDefinition const& _contract)
|
||||
std::vector<SortPointer> stateSorts(ContractDefinition const& _contract)
|
||||
{
|
||||
return applyMap(
|
||||
SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract),
|
||||
|
||||
@ -40,11 +40,11 @@
|
||||
#include <limits>
|
||||
#include <deque>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
using namespace std::string_literals;
|
||||
|
||||
SMTEncoder::SMTEncoder(
|
||||
smt::EncodingContext& _context,
|
||||
@ -72,8 +72,8 @@ bool SMTEncoder::visit(ContractDefinition const& _contract)
|
||||
|
||||
for (auto const& node: _contract.subNodes())
|
||||
if (
|
||||
!dynamic_pointer_cast<FunctionDefinition>(node) &&
|
||||
!dynamic_pointer_cast<VariableDeclaration>(node)
|
||||
!std::dynamic_pointer_cast<FunctionDefinition>(node) &&
|
||||
!std::dynamic_pointer_cast<VariableDeclaration>(node)
|
||||
)
|
||||
node->accept(*this);
|
||||
|
||||
@ -198,7 +198,7 @@ void SMTEncoder::inlineModifierInvocation(ModifierInvocation const* _invocation,
|
||||
solAssert(_invocation, "");
|
||||
_invocation->accept(*this);
|
||||
|
||||
vector<smtutil::Expression> args;
|
||||
std::vector<smtutil::Expression> args;
|
||||
if (auto const* arguments = _invocation->arguments())
|
||||
{
|
||||
auto const& modifierParams = _definition->parameters();
|
||||
@ -314,8 +314,8 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm)
|
||||
this->operator()(_inlineAsm.operations());
|
||||
}
|
||||
|
||||
map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> const& externalReferences;
|
||||
set<VariableDeclaration const*> assignedVars;
|
||||
std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> const& externalReferences;
|
||||
std::set<VariableDeclaration const*> assignedVars;
|
||||
|
||||
using yul::ASTWalker::operator();
|
||||
void operator()(yul::Assignment const& _assignment)
|
||||
@ -425,14 +425,14 @@ void SMTEncoder::endVisit(TupleExpression const& _tuple)
|
||||
if (_tuple.isInlineArray())
|
||||
{
|
||||
// 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, "");
|
||||
|
||||
addArrayLiteralAssertions(*symbArray, applyMap(_tuple.components(), [&](auto const& c) { return expr(*c); }));
|
||||
}
|
||||
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 (!m_context.knownExpression(*component))
|
||||
@ -816,19 +816,19 @@ void SMTEncoder::visitABIFunction(FunctionCall const& _funCall)
|
||||
defineExpr(_funCall, smt::zeroValue(TypeProvider::bytesMemory()));
|
||||
return;
|
||||
}
|
||||
vector<smtutil::Expression> symbArgs;
|
||||
std::vector<smtutil::Expression> symbArgs;
|
||||
for (unsigned i = 0; i < argsActualLength; ++i)
|
||||
if (args.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)
|
||||
arg = expr(*args.at(0), inTypes.at(0));
|
||||
else
|
||||
{
|
||||
auto inputSort = dynamic_cast<smtutil::ArraySort&>(*symbFunction.sort).domain;
|
||||
arg = smtutil::Expression::tuple_constructor(
|
||||
smtutil::Expression(make_shared<smtutil::SortSort>(inputSort), ""),
|
||||
smtutil::Expression(std::make_shared<smtutil::SortSort>(inputSort), ""),
|
||||
symbArgs
|
||||
);
|
||||
}
|
||||
@ -838,7 +838,7 @@ void SMTEncoder::visitABIFunction(FunctionCall const& _funCall)
|
||||
defineExpr(_funCall, out);
|
||||
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->components().size() == outTypes.size(), "");
|
||||
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 kind = funType.kind();
|
||||
auto arg0 = expr(*_funCall.arguments().at(0));
|
||||
optional<smtutil::Expression> result;
|
||||
std::optional<smtutil::Expression> result;
|
||||
if (kind == FunctionType::Kind::KECCAK256)
|
||||
result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0);
|
||||
else if (kind == FunctionType::Kind::SHA256)
|
||||
@ -870,7 +870,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
|
||||
auto arg3 = expr(*_funCall.arguments().at(3));
|
||||
auto inputSort = dynamic_cast<smtutil::ArraySort&>(*e.sort).domain;
|
||||
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}
|
||||
);
|
||||
result = smtutil::Expression::select(e, ecrecoverInput);
|
||||
@ -883,7 +883,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
|
||||
|
||||
void SMTEncoder::visitGasLeft(FunctionCall const& _funCall)
|
||||
{
|
||||
string gasLeft = "gasleft";
|
||||
std::string gasLeft = "gasleft";
|
||||
// We increase the variable index since gasleft changes
|
||||
// inside a tx.
|
||||
defineGlobalVariable(gasLeft, _funCall, true);
|
||||
@ -930,7 +930,7 @@ void SMTEncoder::visitObjectCreation(FunctionCall const& _funCall)
|
||||
smtutil::Expression arraySize = expr(*args.front());
|
||||
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, "");
|
||||
smt::setSymbolicZeroValue(*symbArray, m_context);
|
||||
auto zeroElements = symbArray->elements();
|
||||
@ -1004,9 +1004,9 @@ bool isReturnedFromStructGetter(Type const* _type)
|
||||
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))
|
||||
if (isReturnedFromStructGetter(member.type))
|
||||
returnedMembers.push_back(member.name);
|
||||
@ -1023,7 +1023,7 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
|
||||
auto paramExpectedTypes = replaceUserTypes(FunctionType(*var).parameterTypes());
|
||||
auto actualArguments = _funCall.arguments();
|
||||
solAssert(actualArguments.size() == paramExpectedTypes.size(), "");
|
||||
deque<smtutil::Expression> symbArguments;
|
||||
std::deque<smtutil::Expression> symbArguments;
|
||||
for (unsigned i = 0; i < paramExpectedTypes.size(); ++i)
|
||||
symbArguments.push_back(expr(*actualArguments[i], paramExpectedTypes[i]));
|
||||
|
||||
@ -1063,11 +1063,11 @@ void SMTEncoder::visitPublicGetter(FunctionCall const& _funCall)
|
||||
case Type::Category::Struct:
|
||||
{
|
||||
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);
|
||||
auto returnedMembers = structGetterReturnedMembers(dynamic_cast<StructType const&>(*structVar.type()));
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -1118,7 +1118,7 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -1129,8 +1129,8 @@ void SMTEncoder::visitTypeConversion(FunctionCall const& _funCall)
|
||||
unsigned castSize = funCallType->storageBytes();
|
||||
bool castIsSigned = smt::isNumber(*funCallType) && smt::isSigned(funCallType);
|
||||
bool argIsSigned = smt::isNumber(*argType) && smt::isSigned(argType);
|
||||
optional<smtutil::Expression> symbMin;
|
||||
optional<smtutil::Expression> symbMax;
|
||||
std::optional<smtutil::Expression> symbMin;
|
||||
std::optional<smtutil::Expression> symbMax;
|
||||
if (smt::isNumber(*funCallType))
|
||||
{
|
||||
symbMin = smt::minValue(funCallType);
|
||||
@ -1285,7 +1285,7 @@ void SMTEncoder::endVisit(Literal const& _literal)
|
||||
createExpr(_literal);
|
||||
|
||||
// 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, "");
|
||||
|
||||
addArrayLiteralAssertions(
|
||||
@ -1299,7 +1299,7 @@ void SMTEncoder::endVisit(Literal const& _literal)
|
||||
|
||||
void SMTEncoder::addArrayLiteralAssertions(
|
||||
smt::SymbolicArrayVariable& _symArray,
|
||||
vector<smtutil::Expression> const& _elementValues
|
||||
std::vector<smtutil::Expression> const& _elementValues
|
||||
)
|
||||
{
|
||||
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 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);
|
||||
m_context.addAssertion(k.currentValue() == 0);
|
||||
size_t n = fixed.numBytes();
|
||||
@ -1333,7 +1333,7 @@ void SMTEncoder::endVisit(Return const& _return)
|
||||
auto returnParams = m_callStack.back().first->returnParameters();
|
||||
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->components().size() == returnParams.size(), "");
|
||||
|
||||
@ -1428,7 +1428,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
|
||||
else if (smt::isNonRecursiveStruct(*exprType))
|
||||
{
|
||||
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()));
|
||||
return false;
|
||||
}
|
||||
@ -1471,7 +1471,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
|
||||
memberExpr->accept(*this);
|
||||
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, "");
|
||||
defineExpr(_memberAccess, symbArray->length());
|
||||
m_uninterpretedTerms.insert(&_memberAccess);
|
||||
@ -1554,7 +1554,7 @@ void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
|
||||
return;
|
||||
}
|
||||
|
||||
shared_ptr<smt::SymbolicVariable> array;
|
||||
std::shared_ptr<smt::SymbolicVariable> array;
|
||||
if (auto const* id = dynamic_cast<Identifier const*>(&_indexAccess.baseExpression()))
|
||||
{
|
||||
auto varDecl = identifierToVariable(*id);
|
||||
@ -1570,7 +1570,7 @@ void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
|
||||
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, "");
|
||||
|
||||
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;
|
||||
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, "");
|
||||
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()}
|
||||
);
|
||||
defineExpr(*indexAccess, smtutil::Expression::select(
|
||||
@ -1650,7 +1650,7 @@ void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expre
|
||||
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, "");
|
||||
symbStruct->assignMember(memberAccess->memberName(), toStore);
|
||||
toStore = symbStruct->currentValue();
|
||||
@ -1688,7 +1688,7 @@ void SMTEncoder::arrayPush(FunctionCall const& _funCall)
|
||||
{
|
||||
auto memberAccess = dynamic_cast<MemberAccess const*>(&_funCall.expression());
|
||||
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, "");
|
||||
auto oldLength = symbArray->length();
|
||||
m_context.addAssertion(oldLength >= 0);
|
||||
@ -1722,7 +1722,7 @@ void SMTEncoder::arrayPop(FunctionCall const& _funCall)
|
||||
{
|
||||
auto memberAccess = dynamic_cast<MemberAccess const*>(cleanExpression(_funCall.expression()));
|
||||
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, "");
|
||||
|
||||
makeArrayPopVerificationTarget(_funCall);
|
||||
@ -1742,7 +1742,7 @@ void SMTEncoder::arrayPop(FunctionCall const& _funCall)
|
||||
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))
|
||||
{
|
||||
@ -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,
|
||||
smtutil::Expression const& _left,
|
||||
smtutil::Expression const& _right,
|
||||
@ -1815,7 +1815,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
|
||||
Expression const& _operation
|
||||
)
|
||||
{
|
||||
static set<Token> validOperators{
|
||||
static std::set<Token> validOperators{
|
||||
Token::Add,
|
||||
Token::Sub,
|
||||
Token::Mul,
|
||||
@ -1862,7 +1862,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
|
||||
// - RHS is -1
|
||||
// the result is then -(type.min), which wraps back to type.min
|
||||
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);
|
||||
return {wrap, valueUnbounded};
|
||||
}
|
||||
@ -1871,7 +1871,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
|
||||
auto symbMax = smt::maxValue(*intType);
|
||||
|
||||
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 m(intType, intType, "m_" + suffix, m_context);
|
||||
|
||||
@ -1905,7 +1905,7 @@ smtutil::Expression SMTEncoder::bitwiseOperation(
|
||||
Type const* _commonType
|
||||
)
|
||||
{
|
||||
static set<Token> validOperators{
|
||||
static std::set<Token> validOperators{
|
||||
Token::BitAnd,
|
||||
Token::BitOr,
|
||||
Token::BitXor,
|
||||
@ -1921,7 +1921,7 @@ smtutil::Expression SMTEncoder::bitwiseOperation(
|
||||
auto bvLeft = smtutil::Expression::int2bv(_left, bvSize);
|
||||
auto bvRight = smtutil::Expression::int2bv(_right, bvSize);
|
||||
|
||||
optional<smtutil::Expression> result;
|
||||
std::optional<smtutil::Expression> result;
|
||||
switch (_op)
|
||||
{
|
||||
case Token::BitAnd:
|
||||
@ -1962,10 +1962,10 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op)
|
||||
smtutil::Expression left(expr(_op.leftExpression(), commonType));
|
||||
smtutil::Expression right(expr(_op.rightExpression(), commonType));
|
||||
Token op = _op.getOperator();
|
||||
shared_ptr<smtutil::Expression> value;
|
||||
std::shared_ptr<smtutil::Expression> value;
|
||||
if (smt::isNumber(*commonType))
|
||||
{
|
||||
value = make_shared<smtutil::Expression>(
|
||||
value = std::make_shared<smtutil::Expression>(
|
||||
op == Token::Equal ? (left == right) :
|
||||
op == Token::NotEqual ? (left != right) :
|
||||
op == Token::LessThan ? (left < right) :
|
||||
@ -1977,7 +1977,7 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op)
|
||||
else // Bool
|
||||
{
|
||||
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::NotEqual*/ (left != right)
|
||||
);
|
||||
@ -2039,7 +2039,7 @@ void SMTEncoder::bitwiseNotOperation(UnaryOperation const& _op)
|
||||
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 _right,
|
||||
IntegerType const& _type
|
||||
@ -2049,7 +2049,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::divModWithSlacks(
|
||||
return {_left / _right, _left % _right};
|
||||
|
||||
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 rSymb(intType, intType, "r_" + suffix, m_context);
|
||||
auto d = dSymb.currentValue();
|
||||
@ -2115,7 +2115,7 @@ void SMTEncoder::assignment(
|
||||
{
|
||||
auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
|
||||
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, "");
|
||||
|
||||
auto oldLength = symbArray->length();
|
||||
@ -2190,14 +2190,14 @@ void SMTEncoder::tupleAssignment(Expression const& _left, Expression const& _rig
|
||||
|
||||
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::AssignSub, Token::Sub},
|
||||
{Token::AssignMul, Token::Mul},
|
||||
{Token::AssignDiv, Token::Div},
|
||||
{Token::AssignMod, Token::Mod}
|
||||
};
|
||||
static map<Token, Token> const compoundToBitwise{
|
||||
static std::map<Token, Token> const compoundToBitwise{
|
||||
{Token::AssignBitAnd, Token::BitAnd},
|
||||
{Token::AssignBitOr, Token::BitOr},
|
||||
{Token::AssignBitXor, Token::BitXor},
|
||||
@ -2228,12 +2228,12 @@ smtutil::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment
|
||||
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);
|
||||
if (_variables.size() > 1)
|
||||
{
|
||||
auto symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(symbolicVar);
|
||||
auto symbTuple = std::dynamic_pointer_cast<smt::SymbolicTupleVariable>(symbolicVar);
|
||||
solAssert(symbTuple, "");
|
||||
auto const& symbComponents = symbTuple->components();
|
||||
solAssert(symbComponents.size() == _variables.size(), "");
|
||||
@ -2282,7 +2282,7 @@ void SMTEncoder::assignment(smt::SymbolicVariable& _symVar, smtutil::Expression
|
||||
m_context.addAssertion(_symVar.increaseIndex() == _value);
|
||||
}
|
||||
|
||||
pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
|
||||
std::pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
|
||||
ASTNode const* _statement,
|
||||
smtutil::Expression _condition
|
||||
)
|
||||
@ -2290,7 +2290,7 @@ pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
|
||||
return visitBranch(_statement, &_condition);
|
||||
}
|
||||
|
||||
pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
|
||||
std::pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
|
||||
ASTNode const* _statement,
|
||||
smtutil::Expression const* _condition
|
||||
)
|
||||
@ -2307,7 +2307,7 @@ pair<SMTEncoder::VariableIndices, smtutil::Expression> SMTEncoder::visitBranch(
|
||||
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();
|
||||
solAssert(funParams.size() == _callArgs.size(), "");
|
||||
@ -2319,7 +2319,7 @@ void SMTEncoder::initializeFunctionCallParameters(CallableDeclaration const& _fu
|
||||
m_arrayAssignmentHappened = true;
|
||||
}
|
||||
|
||||
vector<VariableDeclaration const*> localVars;
|
||||
std::vector<VariableDeclaration const*> localVars;
|
||||
if (auto const* fun = dynamic_cast<FunctionDefinition const*>(&_function))
|
||||
localVars = localVariablesIncludingModifiers(*fun, m_currentContract);
|
||||
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())
|
||||
{
|
||||
defineExpr(_e, *_values.front());
|
||||
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, "");
|
||||
symbTuple->increaseIndex();
|
||||
auto const& symbComponents = symbTuple->components();
|
||||
@ -2606,7 +2606,7 @@ smtutil::Expression SMTEncoder::currentPathConditions()
|
||||
return m_pathConditions.back();
|
||||
}
|
||||
|
||||
SecondarySourceLocation SMTEncoder::callStackMessage(vector<CallStackEntry> const& _callStack)
|
||||
SecondarySourceLocation SMTEncoder::callStackMessage(std::vector<CallStackEntry> const& _callStack)
|
||||
{
|
||||
SecondarySourceLocation callStackLocation;
|
||||
solAssert(!_callStack.empty(), "");
|
||||
@ -2617,7 +2617,7 @@ SecondarySourceLocation SMTEncoder::callStackMessage(vector<CallStackEntry> cons
|
||||
return callStackLocation;
|
||||
}
|
||||
|
||||
pair<CallableDeclaration const*, ASTNode const*> SMTEncoder::popCallStack()
|
||||
std::pair<CallableDeclaration const*, ASTNode const*> SMTEncoder::popCallStack()
|
||||
{
|
||||
solAssert(!m_callStack.empty(), "");
|
||||
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();
|
||||
auto const* callOptions = dynamic_cast<FunctionCallOptions const*>(callExpr);
|
||||
@ -2775,9 +2775,9 @@ Expression const* SMTEncoder::cleanExpression(Expression const& _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)
|
||||
callStack.push_back(call.first);
|
||||
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)
|
||||
extra +=
|
||||
"\nNote that array aliasing is not supported,"
|
||||
@ -2921,28 +2921,28 @@ FunctionDefinition const* SMTEncoder::functionCallToDefinition(
|
||||
return {};
|
||||
}
|
||||
|
||||
vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract)
|
||||
std::vector<VariableDeclaration const*> SMTEncoder::stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract)
|
||||
{
|
||||
return fold(
|
||||
_contract.annotation().linearizedBaseContracts,
|
||||
vector<VariableDeclaration const*>{},
|
||||
std::vector<VariableDeclaration const*>{},
|
||||
[](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()))
|
||||
return stateVariablesIncludingInheritedAndPrivate(*contract);
|
||||
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);
|
||||
}
|
||||
|
||||
vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinition const& _function)
|
||||
std::vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinition const& _function)
|
||||
{
|
||||
struct TryCatchVarsVisitor : public ASTConstVisitor
|
||||
{
|
||||
@ -2958,23 +2958,23 @@ vector<VariableDeclaration const*> SMTEncoder::tryCatchVariables(FunctionDefinit
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<VariableDeclaration const*> vars;
|
||||
std::vector<VariableDeclaration const*> vars;
|
||||
} tryCatchVarsVisitor;
|
||||
_function.accept(tryCatchVarsVisitor);
|
||||
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
|
||||
{
|
||||
BlockVars(Block const& _block) { _block.accept(*this); }
|
||||
void endVisit(VariableDeclaration const& _var) { vars.push_back(&_var); }
|
||||
vector<VariableDeclaration const*> vars;
|
||||
std::vector<VariableDeclaration const*> vars;
|
||||
};
|
||||
|
||||
vector<VariableDeclaration const*> vars;
|
||||
set<ModifierDefinition const*> visited;
|
||||
std::vector<VariableDeclaration const*> vars;
|
||||
std::set<ModifierDefinition const*> visited;
|
||||
for (auto invok: _function.modifiers())
|
||||
{
|
||||
if (!invok)
|
||||
@ -3007,12 +3007,12 @@ ModifierDefinition const* SMTEncoder::resolveModifierInvocation(ModifierInvocati
|
||||
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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (base == &_contract)
|
||||
@ -3042,7 +3042,7 @@ set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::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))
|
||||
{
|
||||
@ -3057,9 +3057,9 @@ set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::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)
|
||||
{
|
||||
@ -3104,7 +3104,7 @@ RationalNumberType const* SMTEncoder::isConstant(Expression const& _expr)
|
||||
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
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
||||
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);
|
||||
for (auto const& source: _source.referencedSourceUnits(true))
|
||||
sources.insert(source);
|
||||
@ -3150,24 +3150,24 @@ void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall, Contrac
|
||||
auto const& returnParams = funDef->returnParameters();
|
||||
for (auto param: returnParams)
|
||||
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), "");
|
||||
return currentValue(*param);
|
||||
});
|
||||
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);
|
||||
solAssert(funDef, "");
|
||||
|
||||
vector<smtutil::Expression> args;
|
||||
std::vector<smtutil::Expression> args;
|
||||
Expression const* calledExpr = &_funCall.expression();
|
||||
auto funType = dynamic_cast<FunctionType const*>(calledExpr->annotation().type);
|
||||
solAssert(funType, "");
|
||||
|
||||
vector<ASTPointer<Expression const>> arguments = _funCall.sortedArguments();
|
||||
std::vector<ASTPointer<Expression const>> arguments = _funCall.sortedArguments();
|
||||
auto functionParams = funDef->parameters();
|
||||
unsigned firstParam = 0;
|
||||
if (funType->hasBoundFirstArgument())
|
||||
@ -3204,7 +3204,7 @@ smtutil::Expression SMTEncoder::constantExpr(Expression const& _expr, VariableDe
|
||||
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 node: source->nodes())
|
||||
@ -3220,7 +3220,7 @@ void SMTEncoder::collectFreeFunctions(set<SourceUnit const*, ASTNode::CompareByI
|
||||
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 node: source->nodes())
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
|
||||
#include <libsolidity/formal/SSAVariable.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::frontend::smt;
|
||||
|
||||
|
||||
@ -26,42 +26,41 @@
|
||||
|
||||
#include <range/v3/view.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::smtutil;
|
||||
using namespace solidity::frontend::smt;
|
||||
|
||||
BlockchainVariable::BlockchainVariable(
|
||||
string _name,
|
||||
map<string, smtutil::SortPointer> _members,
|
||||
std::string _name,
|
||||
std::map<std::string, smtutil::SortPointer> _members,
|
||||
EncodingContext& _context
|
||||
):
|
||||
m_name(std::move(_name)),
|
||||
m_members(std::move(_members)),
|
||||
m_context(_context)
|
||||
{
|
||||
vector<string> members;
|
||||
vector<SortPointer> sorts;
|
||||
std::vector<std::string> members;
|
||||
std::vector<SortPointer> sorts;
|
||||
for (auto const& [component, sort]: m_members)
|
||||
{
|
||||
members.emplace_back(component);
|
||||
sorts.emplace_back(sort);
|
||||
m_componentIndices[component] = static_cast<unsigned>(members.size() - 1);
|
||||
}
|
||||
m_tuple = make_unique<SymbolicTupleVariable>(
|
||||
make_shared<smtutil::TupleSort>(m_name + "_type", members, sorts),
|
||||
m_tuple = std::make_unique<SymbolicTupleVariable>(
|
||||
std::make_shared<smtutil::TupleSort>(m_name + "_type", members, sorts),
|
||||
m_name,
|
||||
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));
|
||||
}
|
||||
|
||||
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}});
|
||||
m_context.addAssertion(m_tuple->increaseIndex() == newTuple);
|
||||
@ -104,9 +103,9 @@ smtutil::Expression SymbolicState::blockhash(smtutil::Expression _blockNumber) c
|
||||
|
||||
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"));
|
||||
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());
|
||||
}
|
||||
|
||||
@ -158,7 +157,7 @@ void SymbolicState::newStorage()
|
||||
{
|
||||
auto newStorageVar = SymbolicTupleVariable(
|
||||
m_state->member("storage").sort,
|
||||
"havoc_storage_" + to_string(m_context.newUniqueId()),
|
||||
"havoc_storage_" + std::to_string(m_context.newUniqueId()),
|
||||
m_context
|
||||
);
|
||||
m_state->assignMember("storage", newStorageVar.currentValue());
|
||||
@ -170,7 +169,7 @@ void SymbolicState::writeStateVars(ContractDefinition const& _contract, smtutil:
|
||||
if (stateVars.empty())
|
||||
return;
|
||||
|
||||
map<string, smtutil::Expression> values;
|
||||
std::map<std::string, smtutil::Expression> values;
|
||||
for (auto var: stateVars)
|
||||
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);
|
||||
}
|
||||
|
||||
smtutil::Expression SymbolicState::txMember(string const& _member) const
|
||||
smtutil::Expression SymbolicState::txMember(std::string const& _member) const
|
||||
{
|
||||
return m_tx.member(_member);
|
||||
}
|
||||
@ -268,8 +267,8 @@ void SymbolicState::prepareForSourceUnit(SourceUnit const& _source, bool _storag
|
||||
{
|
||||
auto allSources = _source.referencedSourceUnits(true);
|
||||
allSources.insert(&_source);
|
||||
set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls;
|
||||
set<ContractDefinition const*, ASTCompareByID<ContractDefinition>> contracts;
|
||||
std::set<FunctionCall const*, ASTCompareByID<FunctionCall>> abiCalls;
|
||||
std::set<ContractDefinition const*, ASTCompareByID<ContractDefinition>> contracts;
|
||||
for (auto const& source: allSources)
|
||||
{
|
||||
abiCalls += SMTEncoder::collectABICalls(source);
|
||||
@ -283,34 +282,34 @@ void SymbolicState::prepareForSourceUnit(SourceUnit const& _source, bool _storag
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
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{
|
||||
{"balances", make_shared<smtutil::ArraySort>(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)}
|
||||
std::map<std::string, SortPointer> stateMembers{
|
||||
{"balances", std::make_shared<smtutil::ArraySort>(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort)}
|
||||
};
|
||||
|
||||
if (_allStorages)
|
||||
{
|
||||
vector<string> memberNames;
|
||||
vector<SortPointer> memberSorts;
|
||||
std::vector<std::string> memberNames;
|
||||
std::vector<SortPointer> memberSorts;
|
||||
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
|
||||
// state vars we can't put it there.
|
||||
@ -319,16 +318,16 @@ void SymbolicState::buildState(set<ContractDefinition const*, ASTCompareByID<Con
|
||||
continue;
|
||||
|
||||
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()); });
|
||||
|
||||
string name = "storage" + suffix;
|
||||
auto storageTuple = make_shared<smtutil::TupleSort>(
|
||||
std::string name = "storage" + suffix;
|
||||
auto storageTuple = std::make_shared<smtutil::TupleSort>(
|
||||
name + "_type", names, sorts
|
||||
);
|
||||
|
||||
auto storageSort = make_shared<smtutil::ArraySort>(
|
||||
auto storageSort = std::make_shared<smtutil::ArraySort>(
|
||||
smtSort(*TypeProvider::address()),
|
||||
storageTuple
|
||||
);
|
||||
@ -339,26 +338,26 @@ void SymbolicState::buildState(set<ContractDefinition const*, ASTCompareByID<Con
|
||||
|
||||
stateMembers.emplace(
|
||||
"isActive",
|
||||
make_shared<smtutil::ArraySort>(smtSort(*TypeProvider::address()), smtutil::SortProvider::boolSort)
|
||||
std::make_shared<smtutil::ArraySort>(smtSort(*TypeProvider::address()), smtutil::SortProvider::boolSort)
|
||||
);
|
||||
stateMembers.emplace(
|
||||
"storage",
|
||||
make_shared<smtutil::TupleSort>(
|
||||
std::make_shared<smtutil::TupleSort>(
|
||||
"storage_type", memberNames, memberSorts
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
m_state = make_unique<BlockchainVariable>(
|
||||
m_state = std::make_unique<BlockchainVariable>(
|
||||
"state",
|
||||
std::move(stateMembers),
|
||||
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)
|
||||
{
|
||||
@ -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,
|
||||
/// we generically compute those types.
|
||||
vector<frontend::Type const*> inTypes;
|
||||
vector<frontend::Type const*> outTypes;
|
||||
std::vector<frontend::Type const*> inTypes;
|
||||
std::vector<frontend::Type const*> outTypes;
|
||||
if (t->kind() == FunctionType::Kind::ABIDecode)
|
||||
{
|
||||
/// 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.encodeWithSignature : (string, one_or_more_types) -> bytes
|
||||
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
|
||||
{
|
||||
@ -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.
|
||||
/// 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)
|
||||
return smtSortAbstractFunction(*_types.front());
|
||||
|
||||
vector<string> inNames;
|
||||
vector<SortPointer> sorts;
|
||||
std::vector<std::string> inNames;
|
||||
std::vector<SortPointer> sorts;
|
||||
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)));
|
||||
}
|
||||
return make_shared<smtutil::TupleSort>(
|
||||
return std::make_shared<smtutil::TupleSort>(
|
||||
_name + "_input",
|
||||
inNames,
|
||||
sorts
|
||||
);
|
||||
};
|
||||
|
||||
auto functionSort = make_shared<smtutil::ArraySort>(
|
||||
auto functionSort = std::make_shared<smtutil::ArraySort>(
|
||||
typesToSort(inTypes, name),
|
||||
typesToSort(outTypes, name)
|
||||
);
|
||||
@ -481,13 +480,13 @@ void SymbolicState::buildABIFunctions(set<FunctionCall const*, ASTCompareByID<Fu
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::smtutil;
|
||||
|
||||
@ -52,7 +51,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
{
|
||||
auto fType = dynamic_cast<frontend::FunctionType const*>(&_type);
|
||||
solAssert(fType, "");
|
||||
vector<SortPointer> parameterSorts = smtSort(fType->parameterTypes());
|
||||
std::vector<SortPointer> parameterSorts = smtSort(fType->parameterTypes());
|
||||
auto returnTypes = fType->returnParameterTypes();
|
||||
SortPointer returnSort;
|
||||
// TODO change this when we support tuples.
|
||||
@ -64,22 +63,22 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
returnSort = SortProvider::uintSort;
|
||||
else
|
||||
returnSort = smtSort(*returnTypes.front());
|
||||
return make_shared<FunctionSort>(parameterSorts, returnSort);
|
||||
return std::make_shared<FunctionSort>(parameterSorts, returnSort);
|
||||
}
|
||||
case Kind::Array:
|
||||
{
|
||||
shared_ptr<ArraySort> array;
|
||||
std::shared_ptr<ArraySort> array;
|
||||
if (isMapping(_type))
|
||||
{
|
||||
auto mapType = dynamic_cast<frontend::MappingType const*>(&_type);
|
||||
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))
|
||||
{
|
||||
auto stringLitType = dynamic_cast<frontend::StringLiteralType const*>(&_type);
|
||||
solAssert(stringLitType, "");
|
||||
array = make_shared<ArraySort>(SortProvider::uintSort, SortProvider::uintSort);
|
||||
array = std::make_shared<ArraySort>(SortProvider::uintSort, SortProvider::uintSort);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -92,10 +91,10 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
solAssert(false, "");
|
||||
|
||||
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);
|
||||
ArrayType const* arrayType = sliceArrayType ? &sliceArrayType->arrayType() : dynamic_cast<ArrayType const*>(&_type);
|
||||
if (
|
||||
@ -109,7 +108,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
// Solidity allows implicit conversion also when assigning arrays.
|
||||
// So if the base type potentially has a size, that size cannot go
|
||||
// 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;
|
||||
else if (
|
||||
baseType->category() == frontend::Type::Category::Integer ||
|
||||
@ -128,23 +127,23 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
|
||||
tupleName += "_tuple";
|
||||
|
||||
return make_shared<TupleSort>(
|
||||
return std::make_shared<TupleSort>(
|
||||
tupleName,
|
||||
vector<string>{tupleName + "_accessor_array", tupleName + "_accessor_length"},
|
||||
vector<SortPointer>{array, SortProvider::uintSort}
|
||||
std::vector<std::string>{tupleName + "_accessor_array", tupleName + "_accessor_length"},
|
||||
std::vector<SortPointer>{array, SortProvider::uintSort}
|
||||
);
|
||||
}
|
||||
case Kind::Tuple:
|
||||
{
|
||||
vector<string> members;
|
||||
std::vector<std::string> members;
|
||||
auto const& tupleName = _type.toString(true);
|
||||
vector<SortPointer> sorts;
|
||||
std::vector<SortPointer> sorts;
|
||||
|
||||
if (auto const* tupleType = dynamic_cast<frontend::TupleType const*>(&_type))
|
||||
{
|
||||
auto const& components = tupleType->components();
|
||||
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());
|
||||
}
|
||||
else if (auto const* structType = dynamic_cast<frontend::StructType const*>(&_type))
|
||||
@ -161,7 +160,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
else
|
||||
solAssert(false, "");
|
||||
|
||||
return make_shared<TupleSort>(tupleName, members, sorts);
|
||||
return std::make_shared<TupleSort>(tupleName, members, sorts);
|
||||
}
|
||||
default:
|
||||
// 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)
|
||||
sorts.push_back(smtSort(*type));
|
||||
return sorts;
|
||||
@ -184,9 +183,9 @@ SortPointer smtSortAbstractFunction(frontend::Type const& _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)
|
||||
if (type)
|
||||
sorts.push_back(smtSortAbstractFunction(*type));
|
||||
@ -233,14 +232,14 @@ bool isSupportedTypeDeclaration(frontend::Type const& _type)
|
||||
isFunction(_type);
|
||||
}
|
||||
|
||||
pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
|
||||
std::pair<bool, std::shared_ptr<SymbolicVariable>> newSymbolicVariable(
|
||||
frontend::Type const& _type,
|
||||
std::string const& _uniqueName,
|
||||
EncodingContext& _context
|
||||
)
|
||||
{
|
||||
bool abstract = false;
|
||||
shared_ptr<SymbolicVariable> var;
|
||||
std::shared_ptr<SymbolicVariable> var;
|
||||
frontend::Type const* type = &_type;
|
||||
|
||||
if (auto userType = dynamic_cast<UserDefinedValueType const*>(type))
|
||||
@ -249,10 +248,10 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
|
||||
if (!isSupportedTypeDeclaration(_type))
|
||||
{
|
||||
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))
|
||||
var = make_shared<SymbolicBoolVariable>(type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicBoolVariable>(type, _uniqueName, _context);
|
||||
else if (isFunction(_type))
|
||||
{
|
||||
auto const& fType = dynamic_cast<FunctionType const*>(type);
|
||||
@ -271,45 +270,45 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
|
||||
)
|
||||
{
|
||||
abstract = true;
|
||||
var = make_shared<SymbolicIntVariable>(TypeProvider::uint256(), type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicIntVariable>(TypeProvider::uint256(), type, _uniqueName, _context);
|
||||
}
|
||||
else
|
||||
var = make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context);
|
||||
}
|
||||
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))
|
||||
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
|
||||
else if (isFixedBytes(_type))
|
||||
{
|
||||
auto fixedBytesType = dynamic_cast<frontend::FixedBytesType const*>(type);
|
||||
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))
|
||||
var = make_shared<SymbolicAddressVariable>(_uniqueName, _context);
|
||||
var = std::make_shared<SymbolicAddressVariable>(_uniqueName, _context);
|
||||
else if (isEnum(_type))
|
||||
var = make_shared<SymbolicEnumVariable>(type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicEnumVariable>(type, _uniqueName, _context);
|
||||
else if (isRational(_type))
|
||||
{
|
||||
auto rational = dynamic_cast<frontend::RationalNumberType const*>(&_type);
|
||||
solAssert(rational, "");
|
||||
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
|
||||
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
|
||||
}
|
||||
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))
|
||||
var = make_shared<SymbolicTupleVariable>(type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicTupleVariable>(type, _uniqueName, _context);
|
||||
else if (isStringLiteral(_type))
|
||||
{
|
||||
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))
|
||||
var = make_shared<SymbolicStructVariable>(type, _uniqueName, _context);
|
||||
var = std::make_shared<SymbolicStructVariable>(type, _uniqueName, _context);
|
||||
else
|
||||
solAssert(false, "");
|
||||
return make_pair(abstract, var);
|
||||
@ -482,9 +481,9 @@ smtutil::Expression zeroValue(frontend::Type const* _type)
|
||||
return smtutil::Expression(false);
|
||||
if (isArray(*_type) || isMapping(*_type))
|
||||
{
|
||||
auto tupleSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type));
|
||||
auto tupleSort = std::dynamic_pointer_cast<TupleSort>(smtSort(*_type));
|
||||
solAssert(tupleSort, "");
|
||||
auto sortSort = make_shared<SortSort>(tupleSort->components.front());
|
||||
auto sortSort = std::make_shared<SortSort>(tupleSort->components.front());
|
||||
|
||||
std::optional<smtutil::Expression> zeroArray;
|
||||
auto length = bigint(0);
|
||||
@ -502,16 +501,16 @@ smtutil::Expression zeroValue(frontend::Type const* _type)
|
||||
solAssert(zeroArray, "");
|
||||
return smtutil::Expression::tuple_constructor(
|
||||
smtutil::Expression(std::make_shared<SortSort>(tupleSort), tupleSort->name),
|
||||
vector<smtutil::Expression>{*zeroArray, length}
|
||||
std::vector<smtutil::Expression>{*zeroArray, length}
|
||||
);
|
||||
|
||||
}
|
||||
if (isNonRecursiveStruct(*_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(
|
||||
smtutil::Expression(make_shared<SortSort>(structSort), structSort->name),
|
||||
smtutil::Expression(std::make_shared<SortSort>(structSort), structSort->name),
|
||||
applyMap(
|
||||
structType->structDefinition().members(),
|
||||
[](auto var) { return zeroValue(var->type()); }
|
||||
@ -550,7 +549,7 @@ bool isSigned(frontend::Type const* _type)
|
||||
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))
|
||||
return typeBvSizeAndSignedness(&userType->underlyingType());
|
||||
@ -596,7 +595,7 @@ smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, fronte
|
||||
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))
|
||||
return symbolicTypeConversion(_from, &userType->underlyingType());
|
||||
@ -618,7 +617,7 @@ optional<smtutil::Expression> symbolicTypeConversion(frontend::Type const* _from
|
||||
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);
|
||||
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);
|
||||
vector<smtutil::Expression> args;
|
||||
std::vector<smtutil::Expression> args;
|
||||
for (auto const& m: _sort.members)
|
||||
if (auto* value = util::valueOrNullptr(_values, m))
|
||||
args.emplace_back(*value);
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
|
||||
#include <libsolutil/Algorithms.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::smtutil;
|
||||
@ -33,14 +32,14 @@ using namespace solidity::frontend::smt;
|
||||
SymbolicVariable::SymbolicVariable(
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
m_type(_type),
|
||||
m_originalType(_originalType),
|
||||
m_uniqueName(std::move(_uniqueName)),
|
||||
m_context(_context),
|
||||
m_ssa(make_unique<SSAVariable>())
|
||||
m_ssa(std::make_unique<SSAVariable>())
|
||||
{
|
||||
solAssert(m_type, "");
|
||||
m_sort = smtSort(*m_type);
|
||||
@ -49,13 +48,13 @@ SymbolicVariable::SymbolicVariable(
|
||||
|
||||
SymbolicVariable::SymbolicVariable(
|
||||
SortPointer _sort,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
m_sort(std::move(_sort)),
|
||||
m_uniqueName(std::move(_uniqueName)),
|
||||
m_context(_context),
|
||||
m_ssa(make_unique<SSAVariable>())
|
||||
m_ssa(std::make_unique<SSAVariable>())
|
||||
{
|
||||
solAssert(m_sort, "");
|
||||
}
|
||||
@ -65,7 +64,7 @@ smtutil::Expression SymbolicVariable::currentValue(frontend::Type const*) const
|
||||
return valueAtIndex(m_ssa->index());
|
||||
}
|
||||
|
||||
string SymbolicVariable::currentName() const
|
||||
std::string SymbolicVariable::currentName() const
|
||||
{
|
||||
return uniqueSymbol(m_ssa->index());
|
||||
}
|
||||
@ -75,14 +74,14 @@ smtutil::Expression SymbolicVariable::valueAtIndex(unsigned _index) const
|
||||
return m_context.newVariable(uniqueSymbol(_index), m_sort);
|
||||
}
|
||||
|
||||
string SymbolicVariable::nameAtIndex(unsigned _index) const
|
||||
std::string SymbolicVariable::nameAtIndex(unsigned _index) const
|
||||
{
|
||||
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()
|
||||
@ -105,7 +104,7 @@ smtutil::Expression SymbolicVariable::increaseIndex()
|
||||
|
||||
SymbolicBoolVariable::SymbolicBoolVariable(
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
|
||||
@ -116,7 +115,7 @@ SymbolicBoolVariable::SymbolicBoolVariable(
|
||||
SymbolicIntVariable::SymbolicIntVariable(
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(_type, _originalType, std::move(_uniqueName), _context)
|
||||
@ -125,7 +124,7 @@ SymbolicIntVariable::SymbolicIntVariable(
|
||||
}
|
||||
|
||||
SymbolicAddressVariable::SymbolicAddressVariable(
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicIntVariable(TypeProvider::uint(160), TypeProvider::uint(160), std::move(_uniqueName), _context)
|
||||
@ -135,7 +134,7 @@ SymbolicAddressVariable::SymbolicAddressVariable(
|
||||
SymbolicFixedBytesVariable::SymbolicFixedBytesVariable(
|
||||
frontend::Type const* _originalType,
|
||||
unsigned _numBytes,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicIntVariable(TypeProvider::uint(_numBytes * 8), _originalType, std::move(_uniqueName), _context)
|
||||
@ -144,7 +143,7 @@ SymbolicFixedBytesVariable::SymbolicFixedBytesVariable(
|
||||
|
||||
SymbolicFunctionVariable::SymbolicFunctionVariable(
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(_type, _type, std::move(_uniqueName), _context),
|
||||
@ -155,7 +154,7 @@ SymbolicFunctionVariable::SymbolicFunctionVariable(
|
||||
|
||||
SymbolicFunctionVariable::SymbolicFunctionVariable(
|
||||
SortPointer _sort,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context),
|
||||
@ -204,7 +203,7 @@ smtutil::Expression SymbolicFunctionVariable::increaseIndex()
|
||||
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);
|
||||
}
|
||||
@ -216,7 +215,7 @@ void SymbolicFunctionVariable::resetDeclaration()
|
||||
|
||||
SymbolicEnumVariable::SymbolicEnumVariable(
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
|
||||
@ -226,7 +225,7 @@ SymbolicEnumVariable::SymbolicEnumVariable(
|
||||
|
||||
SymbolicTupleVariable::SymbolicTupleVariable(
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(_type, _type, std::move(_uniqueName), _context)
|
||||
@ -236,7 +235,7 @@ SymbolicTupleVariable::SymbolicTupleVariable(
|
||||
|
||||
SymbolicTupleVariable::SymbolicTupleVariable(
|
||||
SortPointer _sort,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _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))
|
||||
return SymbolicVariable::currentValue();
|
||||
|
||||
auto thisTuple = dynamic_pointer_cast<TupleSort>(sort());
|
||||
auto otherTuple = dynamic_pointer_cast<TupleSort>(smtSort(*_targetType));
|
||||
auto thisTuple = std::dynamic_pointer_cast<TupleSort>(sort());
|
||||
auto otherTuple = std::dynamic_pointer_cast<TupleSort>(smtSort(*_targetType));
|
||||
solAssert(thisTuple && otherTuple, "");
|
||||
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)
|
||||
args.emplace_back(component(i, type(), _targetType));
|
||||
return smtutil::Expression::tuple_constructor(
|
||||
smtutil::Expression(make_shared<smtutil::SortSort>(smtSort(*_targetType)), ""),
|
||||
smtutil::Expression(std::make_shared<smtutil::SortSort>(smtSort(*_targetType)), ""),
|
||||
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, "");
|
||||
return tupleSort->components;
|
||||
}
|
||||
@ -275,7 +274,7 @@ smtutil::Expression SymbolicTupleVariable::component(
|
||||
frontend::Type const* _toType
|
||||
) const
|
||||
{
|
||||
optional<smtutil::Expression> conversion = symbolicTypeConversion(_fromType, _toType);
|
||||
std::optional<smtutil::Expression> conversion = symbolicTypeConversion(_fromType, _toType);
|
||||
if (conversion)
|
||||
return *conversion;
|
||||
|
||||
@ -285,7 +284,7 @@ smtutil::Expression SymbolicTupleVariable::component(
|
||||
SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
frontend::Type const* _type,
|
||||
frontend::Type const* _originalType,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(_type, _originalType, std::move(_uniqueName), _context),
|
||||
@ -300,7 +299,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
|
||||
SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
SortPointer _sort,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _context
|
||||
):
|
||||
SymbolicVariable(std::move(_sort), std::move(_uniqueName), _context),
|
||||
@ -319,7 +318,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
|
||||
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)
|
||||
return *conversion;
|
||||
|
||||
@ -343,7 +342,7 @@ smtutil::Expression SymbolicArrayVariable::length() const
|
||||
|
||||
SymbolicStructVariable::SymbolicStructVariable(
|
||||
frontend::Type const* _type,
|
||||
string _uniqueName,
|
||||
std::string _uniqueName,
|
||||
EncodingContext& _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));
|
||||
}
|
||||
|
||||
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);
|
||||
solAssert(structType, "");
|
||||
@ -385,7 +384,7 @@ smtutil::Expression SymbolicStructVariable::assignMember(string const& _member,
|
||||
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);
|
||||
solAssert(structType, "");
|
||||
|
||||
@ -25,13 +25,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::frontend;
|
||||
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_callStack.clear();
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
@ -42,9 +41,9 @@ bool anyDataStoredInStorage(TypePointers const& _pointers)
|
||||
Json::Value ABI::generate(ContractDefinition const& _contractDef)
|
||||
{
|
||||
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())
|
||||
{
|
||||
@ -144,9 +143,9 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
|
||||
}
|
||||
|
||||
Json::Value ABI::formatTypeList(
|
||||
vector<string> const& _names,
|
||||
vector<Type const*> const& _encodingTypes,
|
||||
vector<Type const*> const& _solidityTypes,
|
||||
std::vector<std::string> const& _names,
|
||||
std::vector<Type const*> const& _encodingTypes,
|
||||
std::vector<Type const*> const& _solidityTypes,
|
||||
bool _forLibrary
|
||||
)
|
||||
{
|
||||
@ -162,7 +161,7 @@ Json::Value ABI::formatTypeList(
|
||||
}
|
||||
|
||||
Json::Value ABI::formatType(
|
||||
string const& _name,
|
||||
std::string const& _name,
|
||||
Type const& _encodingType,
|
||||
Type const& _solidityType,
|
||||
bool _forLibrary
|
||||
@ -171,7 +170,7 @@ Json::Value ABI::formatType(
|
||||
Json::Value ret{Json::objectValue};
|
||||
ret["name"] = _name;
|
||||
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)))
|
||||
ret["type"] = _encodingType.canonicalName() + suffix;
|
||||
else if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(&_encodingType))
|
||||
@ -180,11 +179,11 @@ Json::Value ABI::formatType(
|
||||
ret["type"] = _encodingType.canonicalName() + suffix;
|
||||
else
|
||||
{
|
||||
string suffix;
|
||||
std::string suffix;
|
||||
if (arrayType->isDynamicallySized())
|
||||
suffix = "[]";
|
||||
else
|
||||
suffix = string("[") + arrayType->length().str() + "]";
|
||||
suffix = std::string("[") + arrayType->length().str() + "]";
|
||||
solAssert(arrayType->baseType(), "");
|
||||
Json::Value subtype = formatType(
|
||||
"",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -81,13 +81,15 @@ class Compiler;
|
||||
class GlobalContext;
|
||||
class Natspec;
|
||||
class DeclarationContainer;
|
||||
namespace experimental
|
||||
{
|
||||
class Analysis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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
|
||||
{
|
||||
@ -101,7 +103,7 @@ public:
|
||||
SourcesSet,
|
||||
Parsed,
|
||||
ParsedAndImported,
|
||||
AnalysisPerformed,
|
||||
AnalysisSuccessful,
|
||||
CompilationSuccessful
|
||||
};
|
||||
|
||||
@ -137,10 +139,6 @@ public:
|
||||
/// @returns the current state.
|
||||
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,
|
||||
/// all settings are reset as well.
|
||||
void reset(bool _keepSettings = false);
|
||||
@ -164,14 +162,6 @@ public:
|
||||
/// Sets whether to strip revert strings, add additional strings or do nothing at all.
|
||||
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.
|
||||
/// Must be set before parsing.
|
||||
void setViaIR(bool _viaIR);
|
||||
@ -421,6 +411,14 @@ private:
|
||||
/// @returns true if the contract is requested to be compiled.
|
||||
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.
|
||||
/// This function should only be internally called by compileContract and generateEVMFromIR.
|
||||
void assembleYul(
|
||||
@ -514,15 +512,12 @@ private:
|
||||
|
||||
langutil::ErrorList m_errorList;
|
||||
langutil::ErrorReporter m_errorReporter;
|
||||
std::unique_ptr<experimental::Analysis> m_experimentalAnalysis;
|
||||
bool m_metadataLiteralSources = false;
|
||||
MetadataHash m_metadataHash = MetadataHash::IPFS;
|
||||
langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default();
|
||||
bool m_parserErrorRecovery = false;
|
||||
State m_stackState = Empty;
|
||||
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();
|
||||
};
|
||||
|
||||
|
||||
@ -35,17 +35,13 @@ using solidity::langutil::InternalCompilerError;
|
||||
using solidity::util::errinfo_comment;
|
||||
using solidity::util::readFileAsString;
|
||||
using solidity::util::joinHumanReadable;
|
||||
using std::map;
|
||||
using std::reference_wrapper;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
FileReader::FileReader(
|
||||
boost::filesystem::path _basePath,
|
||||
vector<boost::filesystem::path> const& _includePaths,
|
||||
std::vector<boost::filesystem::path> const& _includePaths,
|
||||
FileSystemPathSet _allowedDirectories
|
||||
):
|
||||
m_allowedDirectories(std::move(_allowedDirectories)),
|
||||
@ -99,19 +95,19 @@ void FileReader::setSourceUnits(StringMap _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
|
||||
{
|
||||
if (_kind != ReadCallback::kindString(ReadCallback::Kind::ReadFile))
|
||||
solAssert(false, "ReadFile callback used as callback kind " + _kind);
|
||||
string strippedSourceUnitName = _sourceUnitName;
|
||||
std::string strippedSourceUnitName = _sourceUnitName;
|
||||
if (strippedSourceUnitName.find("file://") == 0)
|
||||
strippedSourceUnitName.erase(0, 7);
|
||||
|
||||
vector<boost::filesystem::path> candidates;
|
||||
vector<reference_wrapper<boost::filesystem::path>> prefixes = {m_basePath};
|
||||
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path>>>);
|
||||
std::vector<boost::filesystem::path> candidates;
|
||||
std::vector<std::reference_wrapper<boost::filesystem::path>> prefixes = {m_basePath};
|
||||
prefixes += (m_includePaths | ranges::to<std::vector<std::reference_wrapper<boost::filesystem::path>>>);
|
||||
|
||||
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;
|
||||
|
||||
boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(_cliPath);
|
||||
@ -200,17 +196,17 @@ string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPa
|
||||
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)
|
||||
{
|
||||
string sourceUnitName = cliPathToSourceUnitName(cliPath);
|
||||
std::string sourceUnitName = cliPathToSourceUnitName(cliPath);
|
||||
boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(cliPath);
|
||||
nameToPaths[sourceUnitName].insert(normalizedPath);
|
||||
}
|
||||
|
||||
map<string, FileReader::FileSystemPathSet> collisions;
|
||||
std::map<std::string, FileReader::FileSystemPathSet> collisions;
|
||||
for (auto&& [sourceUnitName, cliPaths]: nameToPaths)
|
||||
if (cliPaths.size() >= 2)
|
||||
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)
|
||||
{
|
||||
string rootName = _path.root_name().string();
|
||||
std::string rootName = _path.root_name().string();
|
||||
|
||||
return (
|
||||
rootName.size() == 2 ||
|
||||
|
||||
@ -37,7 +37,6 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
@ -45,16 +44,16 @@ using namespace solidity::langutil;
|
||||
|
||||
GasEstimator::GasConsumption GasEstimator::functionalEstimation(
|
||||
AssemblyItems const& _items,
|
||||
string const& _signature
|
||||
std::string const& _signature
|
||||
) const
|
||||
{
|
||||
auto state = make_shared<KnownState>();
|
||||
auto state = std::make_shared<KnownState>();
|
||||
|
||||
if (!_signature.empty())
|
||||
{
|
||||
ExpressionClasses& classes = state->expressionClasses();
|
||||
using Id = ExpressionClasses::Id;
|
||||
using Ids = vector<Id>;
|
||||
using Ids = std::vector<Id>;
|
||||
Id hashValue = classes.find(u256(util::selectorFromSignatureU32(_signature)));
|
||||
Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))});
|
||||
if (!m_evmVersion.hasBitwiseShifting())
|
||||
@ -88,7 +87,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
|
||||
FunctionDefinition const& _function
|
||||
) const
|
||||
{
|
||||
auto state = make_shared<KnownState>();
|
||||
auto state = std::make_shared<KnownState>();
|
||||
|
||||
unsigned parametersSize = CompilerUtils::sizeOnStack(_function.parameters());
|
||||
if (parametersSize > 16)
|
||||
@ -104,13 +103,13 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
|
||||
return PathGasMeter::estimateMax(_items, m_evmVersion, _offset, state);
|
||||
}
|
||||
|
||||
set<ASTNode const*> GasEstimator::finestNodesAtLocation(
|
||||
vector<ASTNode const*> const& _roots
|
||||
std::set<ASTNode const*> GasEstimator::finestNodesAtLocation(
|
||||
std::vector<ASTNode const*> const& _roots
|
||||
)
|
||||
{
|
||||
map<SourceLocation, ASTNode const*> locations;
|
||||
set<ASTNode const*> nodes;
|
||||
SimpleASTVisitor visitor(function<bool(ASTNode const&)>(), [&](ASTNode const& _n)
|
||||
std::map<SourceLocation, ASTNode const*> locations;
|
||||
std::set<ASTNode const*> nodes;
|
||||
SimpleASTVisitor visitor(std::function<bool(ASTNode const&)>(), [&](ASTNode const& _n)
|
||||
{
|
||||
if (!locations.count(_n.location()))
|
||||
{
|
||||
|
||||
@ -19,29 +19,20 @@
|
||||
#include <libsolutil/CommonIO.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
|
||||
{
|
||||
|
||||
void ImportRemapper::setRemappings(vector<Remapping> _remappings)
|
||||
void ImportRemapper::setRemappings(std::vector<Remapping> _remappings)
|
||||
{
|
||||
for (auto const& remapping: _remappings)
|
||||
solAssert(!remapping.prefix.empty(), "");
|
||||
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.
|
||||
auto isPrefixOf = [](string const& _a, string const& _b)
|
||||
auto isPrefixOf = [](std::string const& _a, std::string const& _b)
|
||||
{
|
||||
if (_a.length() > _b.length())
|
||||
return false;
|
||||
@ -50,12 +41,12 @@ SourceUnitName ImportRemapper::apply(ImportPath const& _path, string const& _con
|
||||
|
||||
size_t longestPrefix = 0;
|
||||
size_t longestContext = 0;
|
||||
string bestMatchTarget;
|
||||
std::string bestMatchTarget;
|
||||
|
||||
for (auto const& redir: m_remappings)
|
||||
{
|
||||
string context = util::sanitizePath(redir.context);
|
||||
string prefix = util::sanitizePath(redir.prefix);
|
||||
std::string context = util::sanitizePath(redir.context);
|
||||
std::string prefix = util::sanitizePath(redir.prefix);
|
||||
|
||||
// Skip if current context is closer
|
||||
if (context.length() < longestContext)
|
||||
@ -74,32 +65,32 @@ SourceUnitName ImportRemapper::apply(ImportPath const& _path, string const& _con
|
||||
longestPrefix = prefix.length();
|
||||
bestMatchTarget = util::sanitizePath(redir.target);
|
||||
}
|
||||
string path = bestMatchTarget;
|
||||
path.append(_path.begin() + static_cast<string::difference_type>(longestPrefix), _path.end());
|
||||
std::string path = bestMatchTarget;
|
||||
path.append(_path.begin() + static_cast<std::string::difference_type>(longestPrefix), _path.end());
|
||||
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())
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
|
||||
auto const colon = find(_input.cbegin(), equals, ':');
|
||||
auto const colon = std::find(_input.cbegin(), equals, ':');
|
||||
|
||||
Remapping remapping{
|
||||
(colon == equals ? "" : string(_input.cbegin(), colon)),
|
||||
(colon == equals ? string(_input.cbegin(), equals) : string(colon + 1, equals)),
|
||||
string(equals + 1, _input.cend()),
|
||||
(colon == equals ? "" : std::string(_input.cbegin(), colon)),
|
||||
(colon == equals ? std::string(_input.cbegin(), equals) : std::string(colon + 1, equals)),
|
||||
std::string(equals + 1, _input.cend()),
|
||||
};
|
||||
|
||||
if (remapping.prefix.empty())
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
|
||||
return remapping;
|
||||
}
|
||||
|
||||
@ -30,8 +30,6 @@
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
@ -46,7 +44,7 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
|
||||
auto constructorDefinition(_contractDef.constructor());
|
||||
if (constructorDefinition)
|
||||
{
|
||||
string const value = extractDoc(constructorDefinition->annotation().docTags, "notice");
|
||||
std::string const value = extractDoc(constructorDefinition->annotation().docTags, "notice");
|
||||
if (!value.empty())
|
||||
{
|
||||
// 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())
|
||||
doc["notice"] = Json::Value(notice);
|
||||
|
||||
for (auto const& it: _contractDef.interfaceFunctions())
|
||||
if (it.second->hasDeclaration())
|
||||
{
|
||||
string value;
|
||||
std::string value;
|
||||
|
||||
if (auto const* f = dynamic_cast<FunctionDefinition const*>(&it.second->declaration()))
|
||||
value = extractDoc(f->annotation().docTags, "notice");
|
||||
@ -80,14 +78,14 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _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())
|
||||
doc["events"][event->functionType(true)->externalSignature()]["notice"] = value;
|
||||
}
|
||||
|
||||
for (auto const& error: _contractDef.interfaceErrors())
|
||||
{
|
||||
string value = extractDoc(error->annotation().docTags, "notice");
|
||||
std::string value = extractDoc(error->annotation().docTags, "notice");
|
||||
if (!value.empty())
|
||||
{
|
||||
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())
|
||||
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())
|
||||
doc["stateVariables"][varDecl->name()][_name] = _content;
|
||||
@ -178,7 +176,7 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
|
||||
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};
|
||||
auto returnDocs = _tags.equal_range("return");
|
||||
@ -188,8 +186,8 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTa
|
||||
size_t n = 0;
|
||||
for (auto i = returnDocs.first; i != returnDocs.second; i++)
|
||||
{
|
||||
string paramName = _returnParameterNames.at(n);
|
||||
string content = i->second.content;
|
||||
std::string paramName = _returnParameterNames.at(n);
|
||||
std::string content = i->second.content;
|
||||
|
||||
if (paramName.empty())
|
||||
paramName = "_" + std::to_string(n);
|
||||
@ -209,18 +207,18 @@ Json::Value Natspec::extractReturnParameterDocs(std::multimap<std::string, DocTa
|
||||
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);
|
||||
for (auto i = range.first; i != range.second; i++)
|
||||
value += i->second.content;
|
||||
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)
|
||||
if (boost::starts_with(tag, "custom"))
|
||||
concatenated[tag] += value.content;
|
||||
@ -255,9 +253,9 @@ Json::Value Natspec::devDocumentation(std::multimap<std::string, DocTag> const&
|
||||
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);
|
||||
solAssert(functionType, "");
|
||||
return functionType->externalSignature();
|
||||
@ -267,13 +265,13 @@ vector<EventDefinition const*> Natspec::uniqueInterfaceEvents(ContractDefinitio
|
||||
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
|
||||
// they're the ones that get selected.
|
||||
uniqueEvents += _contract.definedInterfaceEvents();
|
||||
|
||||
set<EventDefinition const*, decltype(compareBySignature)> filteredUsedEvents{compareBySignature};
|
||||
set<string> usedSignatures;
|
||||
std::set<EventDefinition const*, decltype(compareBySignature)> filteredUsedEvents{compareBySignature};
|
||||
std::set<std::string> usedSignatures;
|
||||
for (EventDefinition const* event: _contract.usedInterfaceEvents())
|
||||
{
|
||||
auto&& [eventIt, eventInserted] = filteredUsedEvents.insert(event);
|
||||
@ -283,5 +281,5 @@ vector<EventDefinition const*> Natspec::uniqueInterfaceEvents(ContractDefinitio
|
||||
}
|
||||
|
||||
uniqueEvents += filteredUsedEvents;
|
||||
return util::convertContainer<vector<EventDefinition const*>>(std::move(uniqueEvents));
|
||||
return util::convertContainer<std::vector<EventDefinition const*>>(std::move(uniqueEvents));
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ struct OptimiserSettings
|
||||
"]"
|
||||
"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.
|
||||
static OptimiserSettings none()
|
||||
|
||||
@ -33,14 +33,13 @@
|
||||
using solidity::langutil::InternalCompilerError;
|
||||
using solidity::util::errinfo_comment;
|
||||
|
||||
using namespace std;
|
||||
|
||||
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
|
||||
{
|
||||
@ -66,8 +65,8 @@ ReadCallback::Result SMTSolverCommand::solve(string const& _kind, string const&
|
||||
boost::process::std_out > pipe
|
||||
);
|
||||
|
||||
vector<string> data;
|
||||
string line;
|
||||
std::vector<std::string> data;
|
||||
std::string line;
|
||||
while (eld.running() && std::getline(pipe, line))
|
||||
if (!line.empty())
|
||||
data.push_back(line);
|
||||
|
||||
@ -44,20 +44,20 @@
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::yul;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
Json::Value formatError(
|
||||
Error::Type _type,
|
||||
string const& _component,
|
||||
string const& _message,
|
||||
string const& _formattedMessage = "",
|
||||
std::string const& _component,
|
||||
std::string const& _message,
|
||||
std::string const& _formattedMessage = "",
|
||||
Json::Value const& _sourceLocation = Json::Value(),
|
||||
Json::Value const& _secondarySourceLocation = Json::Value()
|
||||
)
|
||||
@ -75,7 +75,7 @@ Json::Value formatError(
|
||||
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};
|
||||
output["errors"] = Json::arrayValue;
|
||||
@ -114,22 +114,21 @@ Json::Value formatErrorWithException(
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
util::Exception const& _exception,
|
||||
Error::Type _type,
|
||||
string const& _component,
|
||||
string const& _message,
|
||||
optional<ErrorId> _errorId = nullopt
|
||||
std::string const& _component,
|
||||
std::string const& _message,
|
||||
std::optional<ErrorId> _errorId = std::nullopt
|
||||
)
|
||||
{
|
||||
string message;
|
||||
std::string message;
|
||||
// TODO: consider enabling color
|
||||
string formattedMessage = SourceReferenceFormatter::formatExceptionInformation(
|
||||
std::string formattedMessage = SourceReferenceFormatter::formatExceptionInformation(
|
||||
_exception,
|
||||
_type,
|
||||
_charStreamProvider,
|
||||
false, // colored
|
||||
false // _withErrorIds
|
||||
false // colored
|
||||
);
|
||||
|
||||
if (string const* description = _exception.comment())
|
||||
if (std::string const* description = _exception.comment())
|
||||
message = ((_message.length() > 0) ? (_message + ":") : "") + *description;
|
||||
else
|
||||
message = _message;
|
||||
@ -144,20 +143,20 @@ Json::Value formatErrorWithException(
|
||||
);
|
||||
|
||||
if (_errorId)
|
||||
error["errorCode"] = to_string(_errorId.value().error);
|
||||
error["errorCode"] = std::to_string(_errorId.value().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())
|
||||
{
|
||||
string key = (sourceName == "*") ? "" : sourceName;
|
||||
std::string key = (sourceName == "*") ? "" : sourceName;
|
||||
for (auto const& contractName: _outputSelection[sourceName].getMemberNames())
|
||||
{
|
||||
string value = (contractName == "*") ? "" : contractName;
|
||||
std::string value = (contractName == "*") ? "" : contractName;
|
||||
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.
|
||||
bool hashMatchesContent(string const& _hash, string const& _content)
|
||||
bool hashMatchesContent(std::string const& _hash, std::string const& _content)
|
||||
{
|
||||
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)
|
||||
{
|
||||
string const& selectedArtifact = selectedArtifactJson.asString();
|
||||
std::string const& selectedArtifact = selectedArtifactJson.asString();
|
||||
if (
|
||||
_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.
|
||||
///
|
||||
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())
|
||||
return false;
|
||||
|
||||
for (auto const& file: { _file, string("*") })
|
||||
for (auto const& file: { _file, std::string("*") })
|
||||
if (_outputSelection.isMember(file) && _outputSelection[file].isObject())
|
||||
{
|
||||
/// For SourceUnit-level targets (such as AST) only allow empty name, otherwise
|
||||
/// for Contract-level targets try both contract name and wildcard
|
||||
vector<string> contracts{ _contract };
|
||||
std::vector<std::string> contracts{ _contract };
|
||||
if (!_contract.empty())
|
||||
contracts.emplace_back("*");
|
||||
for (auto const& contract: contracts)
|
||||
@ -236,7 +235,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _fil
|
||||
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)
|
||||
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.
|
||||
vector<string> evmObjectComponents(string const& _objectKind)
|
||||
std::vector<std::string> evmObjectComponents(std::string const& _objectKind)
|
||||
{
|
||||
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")
|
||||
components.push_back(".immutableReferences");
|
||||
return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; });
|
||||
@ -261,7 +260,7 @@ bool isBinaryRequested(Json::Value const& _outputSelection)
|
||||
return false;
|
||||
|
||||
// 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",
|
||||
"evm.gasEstimates", "evm.legacyAssembly", "evm.assembly"
|
||||
@ -281,7 +280,7 @@ bool isEvmBytecodeRequested(Json::Value const& _outputSelection)
|
||||
if (!_outputSelection.isObject())
|
||||
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"
|
||||
} + evmObjectComponents("bytecode") + evmObjectComponents("deployedBytecode");
|
||||
@ -321,13 +320,13 @@ Json::Value formatLinkReferences(std::map<size_t, std::string> const& linkRefere
|
||||
|
||||
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
|
||||
// the whole string represents the library name.
|
||||
size_t colon = fullname.rfind(':');
|
||||
string file = (colon != string::npos ? fullname.substr(0, colon) : "");
|
||||
string name = (colon != string::npos ? fullname.substr(colon + 1) : fullname);
|
||||
std::string file = (colon != std::string::npos ? fullname.substr(0, colon) : "");
|
||||
std::string name = (colon != std::string::npos ? fullname.substr(colon + 1) : fullname);
|
||||
|
||||
Json::Value fileObject = ret.get(file, Json::objectValue);
|
||||
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;
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
@ -368,10 +367,10 @@ Json::Value formatImmutableReferences(map<u256, pair<string, vector<size_t>>> co
|
||||
Json::Value collectEVMObject(
|
||||
langutil::EVMVersion _evmVersion,
|
||||
evmasm::LinkerObject const& _object,
|
||||
string const* _sourceMap,
|
||||
std::string const* _sourceMap,
|
||||
Json::Value _generatedSources,
|
||||
bool _runtimeObject,
|
||||
function<bool(string)> const& _artifactRequested
|
||||
std::function<bool(std::string)> const& _artifactRequested
|
||||
)
|
||||
{
|
||||
Json::Value output{Json::objectValue};
|
||||
@ -392,7 +391,7 @@ Json::Value collectEVMObject(
|
||||
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())
|
||||
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)
|
||||
{
|
||||
static set<string> keys{"auxiliaryInput", "language", "settings", "sources"};
|
||||
static std::set<std::string> keys{"auxiliaryInput", "language", "settings", "sources"};
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@ -457,7 +456,7 @@ std::optional<Json::Value> checkOptimizerDetail(Json::Value const& _details, std
|
||||
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))
|
||||
{
|
||||
@ -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(":");
|
||||
_optimiserSetting = fullSequence.substr(0, delimiterPos);
|
||||
|
||||
if (delimiterPos != string::npos)
|
||||
if (delimiterPos != std::string::npos)
|
||||
_cleanupSetting = fullSequence.substr(delimiterPos + 1);
|
||||
else
|
||||
solAssert(_cleanupSetting == OptimiserSettings::DefaultYulOptimiserCleanupSteps);
|
||||
@ -500,11 +499,11 @@ std::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
|
||||
if (_input.isMember("useLiteralContent") && !_input["useLiteralContent"].isBool())
|
||||
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()))
|
||||
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");
|
||||
}
|
||||
|
||||
@ -646,7 +645,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
for (auto const& sourceName: sources.getMemberNames())
|
||||
{
|
||||
string hash;
|
||||
std::string hash;
|
||||
|
||||
if (auto result = checkSourceKeys(sources[sourceName], sourceName))
|
||||
return *result;
|
||||
@ -656,7 +655,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
|
||||
if (sources[sourceName]["content"].isString())
|
||||
{
|
||||
string content = sources[sourceName]["content"].asString();
|
||||
std::string content = sources[sourceName]["content"].asString();
|
||||
if (!hash.empty() && !hashMatchesContent(hash, content))
|
||||
ret.errors.append(formatError(
|
||||
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."
|
||||
);
|
||||
|
||||
vector<string> failures;
|
||||
std::vector<std::string> failures;
|
||||
bool found = false;
|
||||
|
||||
for (auto const& url: sources[sourceName]["urls"])
|
||||
@ -774,13 +773,6 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
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["viaIR"].isBool())
|
||||
@ -833,11 +825,11 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (!settings["debug"]["debugInfo"].isArray())
|
||||
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"])
|
||||
components.push_back(arrayValue.asString());
|
||||
|
||||
optional<DebugInfoSelection> debugInfoSelection = DebugInfoSelection::fromComponents(
|
||||
std::optional<DebugInfoSelection> debugInfoSelection = DebugInfoSelection::fromComponents(
|
||||
components,
|
||||
true /* _acceptWildcards */
|
||||
);
|
||||
@ -888,7 +880,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
if (!jsonSourceName[library].isString())
|
||||
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"))
|
||||
return formatFatalError(
|
||||
@ -970,7 +962,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (!sources.isObject() && !sources.isNull())
|
||||
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())
|
||||
{
|
||||
if (source.empty())
|
||||
@ -1139,14 +1131,14 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
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)
|
||||
{
|
||||
Json::Value ast;
|
||||
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[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.setViaIR(_inputsAndSettings.viaIR);
|
||||
compilerStack.setEVMVersion(_inputsAndSettings.evmVersion);
|
||||
compilerStack.setParserErrorRecovery(_inputsAndSettings.parserErrorRecovery);
|
||||
compilerStack.setRemappings(std::move(_inputsAndSettings.remappings));
|
||||
compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings));
|
||||
compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings);
|
||||
@ -1318,21 +1309,18 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (compilerStack.hasError() && !_inputsAndSettings.parserErrorRecovery)
|
||||
analysisPerformed = false;
|
||||
|
||||
// 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.
|
||||
bool analysisFailed = !analysisPerformed && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed;
|
||||
bool analysisFailed = !analysisSuccess && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisSuccessful;
|
||||
bool compilationFailed = !compilationSuccess && binariesRequested;
|
||||
|
||||
/// Inconsistent state - stop here to receive error reports from users
|
||||
if (
|
||||
(compilationFailed || !analysisPerformed) &&
|
||||
(errors.empty() && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed)
|
||||
(compilationFailed || analysisFailed || !parsingSuccess) &&
|
||||
errors.empty()
|
||||
)
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
bool const wildcardMatchesExperimental = false;
|
||||
|
||||
output["sources"] = Json::objectValue;
|
||||
unsigned sourceIndex = 0;
|
||||
if (parsingSuccess && !analysisFailed && (!compilerStack.hasError() || _inputsAndSettings.parserErrorRecovery))
|
||||
for (string const& sourceName: compilerStack.sourceNames())
|
||||
// NOTE: A case that will pass `parsingSuccess && !analysisFailed` but not `analysisSuccess` is
|
||||
// stopAfter: parsing with no parsing errors.
|
||||
if (parsingSuccess && !analysisFailed)
|
||||
for (std::string const& sourceName: compilerStack.sourceNames())
|
||||
{
|
||||
Json::Value sourceResult = Json::objectValue;
|
||||
sourceResult["id"] = sourceIndex++;
|
||||
@ -1360,12 +1350,12 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
}
|
||||
|
||||
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(':');
|
||||
solAssert(colon != string::npos, "");
|
||||
string file = contractName.substr(0, colon);
|
||||
string name = contractName.substr(colon + 1);
|
||||
solAssert(colon != std::string::npos, "");
|
||||
std::string file = contractName.substr(0, colon);
|
||||
std::string name = contractName.substr(colon + 1);
|
||||
|
||||
// ABI, storage layout, documentation and metadata
|
||||
Json::Value contractData(Json::objectValue);
|
||||
@ -1414,7 +1404,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
compilerStack.sourceMapping(contractName),
|
||||
compilerStack.generatedSources(contractName),
|
||||
false,
|
||||
[&](string const& _element) { return isArtifactRequested(
|
||||
[&](std::string const& _element) { return isArtifactRequested(
|
||||
_inputsAndSettings.outputSelection,
|
||||
file,
|
||||
name,
|
||||
@ -1436,7 +1426,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
compilerStack.runtimeSourceMapping(contractName),
|
||||
compilerStack.generatedSources(contractName, true),
|
||||
true,
|
||||
[&](string const& _element) { return isArtifactRequested(
|
||||
[&](std::string const& _element) { return isArtifactRequested(
|
||||
_inputsAndSettings.outputSelection,
|
||||
file,
|
||||
name,
|
||||
@ -1513,8 +1503,8 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
_inputsAndSettings.debugInfoSelection.value() :
|
||||
DebugInfoSelection::Default()
|
||||
);
|
||||
string const& sourceName = _inputsAndSettings.sources.begin()->first;
|
||||
string const& sourceContents = _inputsAndSettings.sources.begin()->second;
|
||||
std::string const& sourceName = _inputsAndSettings.sources.begin()->first;
|
||||
std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;
|
||||
|
||||
// Inconsistent state - stop here to receive error reports from users
|
||||
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
|
||||
@ -1531,7 +1521,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
{
|
||||
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(
|
||||
stack,
|
||||
@ -1544,7 +1534,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
return output;
|
||||
}
|
||||
|
||||
string contractName = stack.parserResult()->name.str();
|
||||
std::string contractName = stack.parserResult()->name.str();
|
||||
|
||||
bool const wildcardMatchesExperimental = true;
|
||||
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental))
|
||||
@ -1561,7 +1551,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
|
||||
MachineAssemblyObject object;
|
||||
MachineAssemblyObject deployedObject;
|
||||
tie(object, deployedObject) = stack.assembleWithDeployed();
|
||||
std::tie(object, deployedObject) = stack.assembleWithDeployed();
|
||||
|
||||
if (object.bytecode)
|
||||
object.bytecode->link(_inputsAndSettings.libraries);
|
||||
@ -1586,7 +1576,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
o.sourceMappings.get(),
|
||||
Json::arrayValue,
|
||||
isDeployed,
|
||||
[&, kind = kind](string const& _element) { return isArtifactRequested(
|
||||
[&, kind = kind](std::string const& _element) { return isArtifactRequested(
|
||||
_inputsAndSettings.outputSelection,
|
||||
sourceName,
|
||||
contractName,
|
||||
@ -1626,11 +1616,11 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
string errors;
|
||||
std::string errors;
|
||||
try
|
||||
{
|
||||
if (!util::jsonParseStrict(_input, input, &errors))
|
||||
@ -1671,7 +1661,7 @@ string StandardCompiler::compile(string const& _input) noexcept
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -72,7 +72,6 @@ private:
|
||||
{
|
||||
std::string language;
|
||||
Json::Value errors;
|
||||
bool parserErrorRecovery = false;
|
||||
CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful;
|
||||
std::map<std::string, std::string> sources;
|
||||
std::map<util::h256, std::string> smtLib2Responses;
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
@ -112,7 +111,7 @@ void StorageLayout::generate(Type const* _type)
|
||||
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))
|
||||
return TypeProvider::withLocationIfReference(refType->location(), _type)->richIdentifier();
|
||||
|
||||
@ -25,19 +25,17 @@
|
||||
|
||||
#include <solidity/BuildInfo.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
char const* solidity::frontend::VersionNumber = ETH_PROJECT_VERSION;
|
||||
|
||||
string const solidity::frontend::VersionString =
|
||||
string(solidity::frontend::VersionNumber) +
|
||||
(string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) +
|
||||
(string(SOL_VERSION_BUILDINFO).empty() ? "" : "+" + string(SOL_VERSION_BUILDINFO));
|
||||
std::string const solidity::frontend::VersionString =
|
||||
std::string(solidity::frontend::VersionNumber) +
|
||||
(std::string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + std::string(SOL_VERSION_PRERELEASE)) +
|
||||
(std::string(SOL_VERSION_BUILDINFO).empty() ? "" : "+" + std::string(SOL_VERSION_BUILDINFO));
|
||||
|
||||
string const solidity::frontend::VersionStringStrict =
|
||||
string(solidity::frontend::VersionNumber) +
|
||||
(string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) +
|
||||
(string(SOL_VERSION_COMMIT).empty() ? "" : "+" + string(SOL_VERSION_COMMIT));
|
||||
std::string const solidity::frontend::VersionStringStrict =
|
||||
std::string(solidity::frontend::VersionNumber) +
|
||||
(std::string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + std::string(SOL_VERSION_PRERELEASE)) +
|
||||
(std::string(SOL_VERSION_COMMIT).empty() ? "" : "+" + std::string(SOL_VERSION_COMMIT));
|
||||
|
||||
solidity::bytes const solidity::frontend::VersionCompactBytes = {
|
||||
ETH_PROJECT_VERSION_MAJOR,
|
||||
@ -45,4 +43,4 @@ solidity::bytes const solidity::frontend::VersionCompactBytes = {
|
||||
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();
|
||||
|
||||
@ -23,9 +23,6 @@
|
||||
|
||||
namespace solidity::lsp
|
||||
{
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace solidity::lsp;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -35,16 +32,16 @@ namespace
|
||||
|
||||
struct MarkdownBuilder
|
||||
{
|
||||
stringstream result;
|
||||
std::stringstream result;
|
||||
|
||||
MarkdownBuilder& solidityCode(string const& _code)
|
||||
MarkdownBuilder& solidityCode(std::string const& _code)
|
||||
{
|
||||
auto constexpr SolidityLanguageId = "solidity";
|
||||
result << "```" << SolidityLanguageId << '\n' << _code << "\n```\n\n";
|
||||
return *this;
|
||||
}
|
||||
|
||||
MarkdownBuilder& paragraph(string const& _text)
|
||||
MarkdownBuilder& paragraph(std::string const& _text)
|
||||
{
|
||||
if (!_text.empty())
|
||||
{
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::lsp;
|
||||
using namespace solidity::frontend;
|
||||
@ -54,11 +53,11 @@ void FileRepository::setIncludePaths(std::vector<boost::filesystem::path> _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))
|
||||
return inputPath;
|
||||
else
|
||||
@ -86,13 +85,13 @@ string FileRepository::sourceUnitNameToUri(string const& _sourceUnitName) const
|
||||
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://");
|
||||
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,
|
||||
// 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);
|
||||
|
||||
vector<boost::filesystem::path> candidates;
|
||||
vector<reference_wrapper<boost::filesystem::path const>> prefixes = {m_basePath};
|
||||
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path const>>>);
|
||||
std::vector<boost::filesystem::path> candidates;
|
||||
std::vector<std::reference_wrapper<boost::filesystem::path const>> prefixes = {m_basePath};
|
||||
prefixes += (m_includePaths | ranges::to<std::vector<std::reference_wrapper<boost::filesystem::path const>>>);
|
||||
auto const defaultInclude = m_basePath / "node_modules";
|
||||
if (m_includePaths.empty())
|
||||
prefixes.emplace_back(defaultInclude);
|
||||
@ -148,7 +147,7 @@ Result<boost::filesystem::path> FileRepository::tryResolvePath(std::string const
|
||||
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(
|
||||
_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile),
|
||||
@ -161,7 +160,7 @@ frontend::ReadCallback::Result FileRepository::readFile(string const& _kind, str
|
||||
if (m_sourceCodes.count(_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);
|
||||
if (!resolvedPath.message().empty())
|
||||
return ReadCallback::Result{false, resolvedPath.message()};
|
||||
|
||||
@ -30,7 +30,6 @@
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::lsp;
|
||||
using namespace std;
|
||||
|
||||
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);
|
||||
|
||||
vector<SourceLocation> locations;
|
||||
std::vector<SourceLocation> locations;
|
||||
if (auto const* expression = dynamic_cast<Expression const*>(sourceNode))
|
||||
{
|
||||
// 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;
|
||||
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;
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::lsp;
|
||||
using namespace solidity::util;
|
||||
using namespace std;
|
||||
|
||||
Json::Value HandlerBase::toRange(SourceLocation const& _location) const
|
||||
{
|
||||
@ -52,10 +51,10 @@ Json::Value HandlerBase::toJson(SourceLocation const& _location) const
|
||||
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();
|
||||
string const sourceUnitName = fileRepository().uriToSourceUnitName(uri);
|
||||
std::string const uri = _args["textDocument"]["uri"].asString();
|
||||
std::string const sourceUnitName = fileRepository().uriToSourceUnitName(uri);
|
||||
if (!fileRepository().sourceUnits().count(sourceUnitName))
|
||||
BOOST_THROW_EXCEPTION(
|
||||
RequestError(ErrorCode::RequestFailed) <<
|
||||
|
||||
@ -46,7 +46,6 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::string_literals;
|
||||
using namespace std::placeholders;
|
||||
|
||||
@ -109,7 +108,7 @@ Json::Value semanticTokensLegend()
|
||||
tokenTypes.append("operator");
|
||||
tokenTypes.append("parameter");
|
||||
tokenTypes.append("property");
|
||||
tokenTypes.append("string");
|
||||
tokenTypes.append("std::string");
|
||||
tokenTypes.append("struct");
|
||||
tokenTypes.append("type");
|
||||
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 */}},
|
||||
{"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }},
|
||||
{"initialize", bind(&LanguageServer::handleInitialize, this, _1, _2)},
|
||||
{"initialized", bind(&LanguageServer::handleInitialized, this, _1, _2)},
|
||||
{"initialize", std::bind(&LanguageServer::handleInitialize, this, _1, _2)},
|
||||
{"initialized", std::bind(&LanguageServer::handleInitialized, this, _1, _2)},
|
||||
{"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }},
|
||||
{"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }},
|
||||
{"textDocument/definition", GotoDefinition(*this) },
|
||||
{"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
|
||||
{"textDocument/didChange", bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
|
||||
{"textDocument/didClose", bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
|
||||
{"textDocument/didOpen", std::bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
|
||||
{"textDocument/didChange", std::bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
|
||||
{"textDocument/didClose", std::bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
|
||||
{"textDocument/hover", DocumentHoverHandler(*this) },
|
||||
{"textDocument/rename", RenameSymbol(*this) },
|
||||
{"textDocument/implementation", GotoDefinition(*this) },
|
||||
{"textDocument/semanticTokens/full", bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
|
||||
{"workspace/didChangeConfiguration", bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
|
||||
{"textDocument/semanticTokens/full", std::bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
|
||||
{"workspace/didChangeConfiguration", std::bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
|
||||
},
|
||||
m_fileRepository("/" /* basePath */, {} /* no search paths */),
|
||||
m_compilerStack{m_fileRepository.reader()}
|
||||
@ -196,7 +195,7 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
|
||||
int typeFailureCount = 0;
|
||||
if (jsonIncludePaths.isArray())
|
||||
{
|
||||
vector<boost::filesystem::path> includePaths;
|
||||
std::vector<boost::filesystem::path> includePaths;
|
||||
for (Json::Value const& jsonPath: jsonIncludePaths)
|
||||
{
|
||||
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
|
||||
// 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.
|
||||
|
||||
FileRepository oldRepository(m_fileRepository.basePath(), m_fileRepository.includePaths());
|
||||
swap(oldRepository, m_fileRepository);
|
||||
std::swap(oldRepository, m_fileRepository);
|
||||
|
||||
// Load all solidity files from project.
|
||||
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.
|
||||
for (string const& fileName: m_openFiles)
|
||||
for (std::string const& fileName: m_openFiles)
|
||||
m_fileRepository.setSourceByUri(
|
||||
fileName,
|
||||
oldRepository.sourceUnits().at(oldRepository.uriToSourceUnitName(fileName))
|
||||
@ -266,7 +265,7 @@ void LanguageServer::compile()
|
||||
|
||||
m_compilerStack.reset(false);
|
||||
m_compilerStack.setSources(m_fileRepository.sourceUnits());
|
||||
m_compilerStack.compile(CompilerStack::State::AnalysisPerformed);
|
||||
m_compilerStack.compile(CompilerStack::State::AnalysisSuccessful);
|
||||
}
|
||||
|
||||
void LanguageServer::compileAndUpdateDiagnostics()
|
||||
@ -275,13 +274,13 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
||||
|
||||
// These are the source units we will sent diagnostics to the client for sure,
|
||||
// even if it is just to clear previous diagnostics.
|
||||
map<string, Json::Value> diagnosticsBySourceUnit;
|
||||
for (string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys)
|
||||
std::map<std::string, Json::Value> diagnosticsBySourceUnit;
|
||||
for (std::string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys)
|
||||
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
|
||||
for (string const& sourceUnitName: m_nonemptyDiagnostics)
|
||||
for (std::string const& sourceUnitName: m_nonemptyDiagnostics)
|
||||
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();
|
||||
if (!location || !location->sourceName)
|
||||
@ -292,8 +291,8 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
||||
jsonDiag["source"] = "solc";
|
||||
jsonDiag["severity"] = toDiagnosticSeverity(error->type());
|
||||
jsonDiag["code"] = Json::UInt64{error->errorId().error};
|
||||
string message = Error::formatErrorType(error->type()) + ":";
|
||||
if (string const* comment = error->comment())
|
||||
std::string message = Error::formatErrorType(error->type()) + ":";
|
||||
if (std::string const* comment = error->comment())
|
||||
message += " " + *comment;
|
||||
jsonDiag["message"] = std::move(message);
|
||||
jsonDiag["range"] = toRange(*location);
|
||||
@ -314,7 +313,7 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
||||
{
|
||||
Json::Value extra;
|
||||
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();
|
||||
@ -336,13 +335,13 @@ bool LanguageServer::run()
|
||||
MessageID id;
|
||||
try
|
||||
{
|
||||
optional<Json::Value> const jsonMessage = m_client.receive();
|
||||
std::optional<Json::Value> const jsonMessage = m_client.receive();
|
||||
if (!jsonMessage)
|
||||
continue;
|
||||
|
||||
if ((*jsonMessage)["method"].isString())
|
||||
{
|
||||
string const methodName = (*jsonMessage)["method"].asString();
|
||||
std::string const methodName = (*jsonMessage)["method"].asString();
|
||||
id = (*jsonMessage)["id"];
|
||||
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
|
||||
// should not matter.
|
||||
string rootPath("/");
|
||||
std::string rootPath("/");
|
||||
if (Json::Value uri = _args["rootUri"])
|
||||
{
|
||||
rootPath = uri.asString();
|
||||
@ -414,7 +413,7 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
|
||||
|
||||
Json::Value replyArgs;
|
||||
replyArgs["serverInfo"]["name"] = "solc";
|
||||
replyArgs["serverInfo"]["version"] = string(VersionNumber);
|
||||
replyArgs["serverInfo"]["version"] = std::string(VersionNumber);
|
||||
replyArgs["capabilities"]["definitionProvider"] = true;
|
||||
replyArgs["capabilities"]["implementationProvider"] = true;
|
||||
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();
|
||||
|
||||
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);
|
||||
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.
|
||||
return;
|
||||
|
||||
string const stringValue = _args.asString();
|
||||
std::string const stringValue = _args.asString();
|
||||
if (stringValue == "off")
|
||||
m_client.setTrace(TraceValue::Off);
|
||||
else if (stringValue == "messages")
|
||||
@ -484,8 +483,8 @@ void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args)
|
||||
"Text document parameter missing."
|
||||
);
|
||||
|
||||
string text = _args["textDocument"]["text"].asString();
|
||||
string uri = _args["textDocument"]["uri"].asString();
|
||||
std::string text = _args["textDocument"]["text"].asString();
|
||||
std::string uri = _args["textDocument"]["uri"].asString();
|
||||
m_openFiles.insert(uri);
|
||||
m_fileRepository.setSourceByUri(uri, std::move(text));
|
||||
compileAndUpdateDiagnostics();
|
||||
@ -495,7 +494,7 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
|
||||
{
|
||||
requireServerInitialized();
|
||||
|
||||
string const uri = _args["textDocument"]["uri"].asString();
|
||||
std::string const uri = _args["textDocument"]["uri"].asString();
|
||||
|
||||
for (Json::Value jsonContentChange: _args["contentChanges"])
|
||||
{
|
||||
@ -505,24 +504,24 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
|
||||
"Invalid content reference."
|
||||
);
|
||||
|
||||
string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri);
|
||||
std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri);
|
||||
lspRequire(
|
||||
m_fileRepository.sourceUnits().count(sourceUnitName),
|
||||
ErrorCode::RequestFailed,
|
||||
"Unknown file: " + uri
|
||||
);
|
||||
|
||||
string text = jsonContentChange["text"].asString();
|
||||
std::string text = jsonContentChange["text"].asString();
|
||||
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(
|
||||
change && change->hasText(),
|
||||
ErrorCode::RequestFailed,
|
||||
"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));
|
||||
text = std::move(buffer);
|
||||
}
|
||||
@ -542,7 +541,7 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
|
||||
"Text document parameter missing."
|
||||
);
|
||||
|
||||
string uri = _args["textDocument"]["uri"].asString();
|
||||
std::string uri = _args["textDocument"]["uri"].asString();
|
||||
m_openFiles.erase(uri);
|
||||
|
||||
compileAndUpdateDiagnostics();
|
||||
@ -550,17 +549,17 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
|
||||
|
||||
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};
|
||||
if (!m_fileRepository.sourceUnits().count(_sourceUnitName))
|
||||
return {nullptr, -1};
|
||||
|
||||
optional<int> sourcePos = m_compilerStack.charStream(_sourceUnitName).translateLineColumnToPosition(_filePos);
|
||||
std::optional<int> sourcePos = m_compilerStack.charStream(_sourceUnitName).translateLineColumnToPosition(_filePos);
|
||||
if (!sourcePos)
|
||||
return {nullptr, -1};
|
||||
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::lsp;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -51,8 +50,8 @@ CallableDeclaration const* extractCallableDeclaration(FunctionCall const& _funct
|
||||
void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
||||
{
|
||||
auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
|
||||
string const newName = _args["newName"].asString();
|
||||
string const uri = _args["textDocument"]["uri"].asString();
|
||||
std::string const newName = _args["newName"].asString();
|
||||
std::string const uri = _args["textDocument"]["uri"].asString();
|
||||
|
||||
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_locations.clear();
|
||||
|
||||
optional<int> cursorBytePosition = charStreamProvider()
|
||||
std::optional<int> cursorBytePosition = charStreamProvider()
|
||||
.charStream(sourceUnitName)
|
||||
.translateLineColumnToPosition(lineColumn);
|
||||
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())
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_sourceUnits.insert(&sourceUnit);
|
||||
@ -101,8 +100,8 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
||||
solAssert(i->isValid());
|
||||
|
||||
// Replace in our file repository
|
||||
string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName);
|
||||
string buffer = fileRepository().sourceUnits().at(*i->sourceName);
|
||||
std::string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName);
|
||||
std::string buffer = fileRepository().sourceUnits().at(*i->sourceName);
|
||||
buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName);
|
||||
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))
|
||||
extractNameAndDeclaration(*inlineAssembly, _cursorBytePosition);
|
||||
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));
|
||||
}
|
||||
@ -297,7 +296,7 @@ void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node)
|
||||
{
|
||||
for (auto&& [identifier, externalReference]: _node.annotation().externalReferences)
|
||||
{
|
||||
string identifierName = identifier->name.str();
|
||||
std::string identifierName = identifier->name.str();
|
||||
if (!externalReference.suffix.empty())
|
||||
identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1);
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
@ -33,10 +32,10 @@ namespace solidity::lsp
|
||||
namespace
|
||||
{
|
||||
|
||||
optional<SemanticTokenType> semanticTokenTypeForType(frontend::Type const* _type)
|
||||
std::optional<SemanticTokenType> semanticTokenTypeForType(frontend::Type const* _type)
|
||||
{
|
||||
if (!_type)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
|
||||
switch (_type->category())
|
||||
{
|
||||
@ -119,7 +118,7 @@ void SemanticTokensBuilder::encode(
|
||||
auto const [line, startChar] = m_charStream->translatePositionToLineColumn(_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);
|
||||
if (line == m_lastLine)
|
||||
|
||||
@ -37,34 +37,33 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::lsp;
|
||||
|
||||
// {{{ Transport
|
||||
optional<Json::Value> Transport::receive()
|
||||
std::optional<Json::Value> Transport::receive()
|
||||
{
|
||||
auto const headers = parseHeaders();
|
||||
if (!headers)
|
||||
{
|
||||
error({}, ErrorCode::ParseError, "Could not parse RPC headers.");
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!headers->count("content-length"))
|
||||
{
|
||||
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;
|
||||
string jsonParsingErrors;
|
||||
std::string jsonParsingErrors;
|
||||
solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors);
|
||||
if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject())
|
||||
{
|
||||
error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors);
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -93,18 +92,18 @@ optional<map<string, string>> Transport::parseHeaders()
|
||||
break;
|
||||
|
||||
auto const delimiterPos = line.find(':');
|
||||
if (delimiterPos == string::npos)
|
||||
return nullopt;
|
||||
if (delimiterPos == std::string::npos)
|
||||
return std::nullopt;
|
||||
|
||||
auto const name = boost::to_lower_copy(line.substr(0, delimiterPos));
|
||||
auto const value = line.substr(delimiterPos + 1);
|
||||
if (!headers.emplace(boost::trim_copy(name), boost::trim_copy(value)).second)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
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["method"] = std::move(_method);
|
||||
@ -119,7 +118,7 @@ void Transport::reply(MessageID _id, Json::Value _message)
|
||||
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["error"]["code"] = static_cast<int>(_code);
|
||||
@ -135,7 +134,7 @@ void Transport::send(Json::Value _json, MessageID _id)
|
||||
_json["id"] = _id;
|
||||
|
||||
// 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(jsonString);
|
||||
@ -144,7 +143,7 @@ void Transport::send(Json::Value _json, MessageID _id)
|
||||
// }}}
|
||||
|
||||
// {{{ IOStreamTransport
|
||||
IOStreamTransport::IOStreamTransport(istream& _in, ostream& _out):
|
||||
IOStreamTransport::IOStreamTransport(std::istream& _in, std::ostream& _out):
|
||||
m_input{_in},
|
||||
m_output{_out}
|
||||
{
|
||||
@ -162,7 +161,7 @@ std::string IOStreamTransport::readBytes(size_t _length)
|
||||
|
||||
std::string IOStreamTransport::getline()
|
||||
{
|
||||
string line;
|
||||
std::string line;
|
||||
std::getline(m_input, line);
|
||||
return line;
|
||||
}
|
||||
|
||||
@ -30,21 +30,20 @@ namespace solidity::lsp
|
||||
|
||||
using namespace frontend;
|
||||
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())
|
||||
return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()};
|
||||
else
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Json::Value toJson(LineColumn const& _pos)
|
||||
{
|
||||
Json::Value json = Json::objectValue;
|
||||
json["line"] = max(_pos.line, 0);
|
||||
json["character"] = max(_pos.column, 0);
|
||||
json["line"] = std::max(_pos.line, 0);
|
||||
json["character"] = std::max(_pos.column, 0);
|
||||
|
||||
return json;
|
||||
}
|
||||
@ -70,10 +69,10 @@ Declaration const* referencedDeclaration(Expression const* _expression)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
optional<SourceLocation> declarationLocation(Declaration const* _declaration)
|
||||
std::optional<SourceLocation> declarationLocation(Declaration const* _declaration)
|
||||
{
|
||||
if (!_declaration)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
|
||||
if (_declaration->nameLocation().isValid())
|
||||
return _declaration->nameLocation();
|
||||
@ -81,43 +80,43 @@ optional<SourceLocation> declarationLocation(Declaration const* _declaration)
|
||||
if (_declaration->location().isValid())
|
||||
return _declaration->location();
|
||||
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
optional<SourceLocation> parsePosition(
|
||||
std::optional<SourceLocation> parsePosition(
|
||||
FileRepository const& _fileRepository,
|
||||
string const& _sourceUnitName,
|
||||
std::string const& _sourceUnitName,
|
||||
Json::Value const& _position
|
||||
)
|
||||
{
|
||||
if (!_fileRepository.sourceUnits().count(_sourceUnitName))
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
|
||||
if (optional<LineColumn> lineColumn = parseLineColumn(_position))
|
||||
if (optional<int> const offset = CharStream::translateLineColumnToPosition(
|
||||
if (std::optional<LineColumn> lineColumn = parseLineColumn(_position))
|
||||
if (std::optional<int> const offset = CharStream::translateLineColumnToPosition(
|
||||
_fileRepository.sourceUnits().at(_sourceUnitName),
|
||||
*lineColumn
|
||||
))
|
||||
return SourceLocation{*offset, *offset, make_shared<string>(_sourceUnitName)};
|
||||
return nullopt;
|
||||
return SourceLocation{*offset, *offset, std::make_shared<std::string>(_sourceUnitName)};
|
||||
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())
|
||||
return nullopt;
|
||||
optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]);
|
||||
optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]);
|
||||
return std::nullopt;
|
||||
std::optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]);
|
||||
std::optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]);
|
||||
if (!start || !end)
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
solAssert(*start->sourceName == *end->sourceName);
|
||||
start->end = end->end;
|
||||
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))
|
||||
return _path.substr(8);
|
||||
if (_path.find("file://") == 0)
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include <range/v3/algorithm/find_if_not.hpp>
|
||||
#include <range/v3/view/subrange.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
@ -36,17 +35,17 @@ using namespace solidity::frontend;
|
||||
namespace
|
||||
{
|
||||
|
||||
string::const_iterator skipLineOrEOS(
|
||||
string::const_iterator _nlPos,
|
||||
string::const_iterator _end
|
||||
std::string::const_iterator skipLineOrEOS(
|
||||
std::string::const_iterator _nlPos,
|
||||
std::string::const_iterator _end
|
||||
)
|
||||
{
|
||||
return (_nlPos == _end) ? _end : ++_nlPos;
|
||||
}
|
||||
|
||||
string::const_iterator firstNonIdentifier(
|
||||
string::const_iterator _pos,
|
||||
string::const_iterator _end
|
||||
std::string::const_iterator firstNonIdentifier(
|
||||
std::string::const_iterator _pos,
|
||||
std::string::const_iterator _end
|
||||
)
|
||||
{
|
||||
auto currPos = _pos;
|
||||
@ -58,18 +57,18 @@ string::const_iterator firstNonIdentifier(
|
||||
return currPos;
|
||||
}
|
||||
|
||||
string::const_iterator firstWhitespaceOrNewline(
|
||||
string::const_iterator _pos,
|
||||
string::const_iterator _end
|
||||
std::string::const_iterator firstWhitespaceOrNewline(
|
||||
std::string::const_iterator _pos,
|
||||
std::string::const_iterator _end
|
||||
)
|
||||
{
|
||||
return ranges::find_first_of(ranges::make_subrange(_pos, _end), " \t\n");
|
||||
}
|
||||
|
||||
|
||||
string::const_iterator skipWhitespace(
|
||||
string::const_iterator _pos,
|
||||
string::const_iterator _end
|
||||
std::string::const_iterator skipWhitespace(
|
||||
std::string::const_iterator _pos,
|
||||
std::string::const_iterator _end
|
||||
)
|
||||
{
|
||||
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_docTags = {};
|
||||
@ -96,7 +95,7 @@ multimap<string, DocTag> DocStringParser::parse()
|
||||
{
|
||||
// we found a tag
|
||||
iter tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
|
||||
string tagName{tagPos + 1, tagNameEndPos};
|
||||
std::string tagName{tagPos + 1, tagNameEndPos};
|
||||
iter tagDataPos = (tagNameEndPos != end) ? tagNameEndPos + 1 : tagNameEndPos;
|
||||
currPos = parseDocTag(tagDataPos, end, tagName);
|
||||
}
|
||||
@ -141,7 +140,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
||||
return _end;
|
||||
}
|
||||
auto nameEndPos = firstNonIdentifier(nameStartPos, _end);
|
||||
auto paramName = string(nameStartPos, nameEndPos);
|
||||
auto paramName = std::string(nameStartPos, nameEndPos);
|
||||
|
||||
auto descStartPos = skipWhitespace(nameEndPos, _end);
|
||||
auto nlPos = find(descStartPos, _end, '\n');
|
||||
@ -152,7 +151,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
||||
return _end;
|
||||
}
|
||||
|
||||
auto paramDesc = string(descStartPos, nlPos);
|
||||
auto paramDesc = std::string(descStartPos, nlPos);
|
||||
newTag("param");
|
||||
m_lastTag->paramName = paramName;
|
||||
m_lastTag->content = paramDesc;
|
||||
@ -160,7 +159,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _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
|
||||
// for all cases.
|
||||
@ -178,7 +177,7 @@ DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, string
|
||||
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;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user