diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index c7f4c15e2..000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-arm_container:
- image: gcc:latest
-
-check_task:
- check_script:
- # the gcc image ships an outdated CMake, so fetch a recent prebuilt binary
- # instead of compiling CMake from source
- - wget -q https://github.com/Kitware/CMake/releases/download/v4.3.4/cmake-4.3.4-linux-aarch64.tar.gz
- - tar xfz cmake-4.3.4-linux-aarch64.tar.gz
- - export PATH="$(pwd)/cmake-4.3.4-linux-aarch64/bin:$PATH"
- - cmake --version
- - mkdir build
- - cd build
- - cmake .. -DJSON_FastTests=ON
- - make -j4
- - cd tests
- - ctest -j4
diff --git a/.clang-tidy b/.clang-tidy
index 29b3e9302..a16136785 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,12 +1,9 @@
-# TODO: The first three checks are only removed to get the CI going. They have to be addressed at some point.
-# TODO: portability-avoid-pragma-once: should be fixed eventually
+# portability-avoid-pragma-once: kept disabled on purpose. #pragma once is accepted
+# by every supported compiler, and tools/amalgamate/amalgamate.py strips it from
+# single_include, so there is nothing left to fix here.
Checks: '*,
- -portability-template-virtual-member-function,
- -bugprone-use-after-move,
- -hicpp-invalid-access-moved,
-
-altera-id-dependent-backward-branch,
-altera-struct-pack-align,
-altera-unroll-loops,
@@ -37,7 +34,6 @@ Checks: '*,
-google-readability-function-size,
-google-runtime-float,
-google-runtime-int,
- -google-runtime-references,
-hicpp-avoid-goto,
-hicpp-explicit-conversions,
-hicpp-function-size,
@@ -71,6 +67,7 @@ Checks: '*,
-readability-magic-numbers,
-readability-redundant-access-specifiers,
-readability-redundant-parentheses,
+ -readability-redundant-typename,
-readability-simplify-boolean-expr,
-readability-uppercase-literal-suffix,
-readability-use-concise-preprocessor-directives'
@@ -78,8 +75,11 @@ Checks: '*,
CheckOptions:
- key: hicpp-special-member-functions.AllowSoleDefaultDtor
value: 1
+ # clang-tidy 22.1 extended this check to classes and enums; the test files
+ # define many such helper types at namespace scope, which is harmless
+ - key: misc-use-internal-linkage.AnalyzeTypes
+ value: false
WarningsAsErrors: '*'
-#HeaderFilterRegex: '.*nlohmann.*'
HeaderFilterRegex: '.*hpp$'
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 4125b066a..6f3d0bef3 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -142,6 +142,16 @@ The documentation will then be available at . See the do
[mkdocs](https://www.mkdocs.org) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) for more
information.
+Before opening a pull request, check the documentation like the CI does:
+
+```shell
+make build -C docs/mkdocs # strict build: fails on broken links, anchors, and structure problems
+make check_mermaid -C docs/mkdocs # checks the Mermaid diagrams (requires Node.js)
+```
+
+A new API page also needs an entry in [`docs/docset/docSet.sql`](https://github.com/nlohmann/json/blob/develop/docs/docset/docSet.sql),
+the search index of the docset; `make build` reports missing entries.
+
### Amalgamate the source code
The single-header files
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index ef1432591..5336d0df5 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -18,12 +18,27 @@ updates:
cooldown:
default-days: 7
+ - package-ecosystem: npm
+ directory: /docs/mkdocs/scripts/mermaid
+ schedule:
+ interval: daily
+ cooldown:
+ default-days: 7
+ ignore:
+ # Material for MkDocs loads mermaid@11; keep the checker on the same major version
+ - dependency-name: mermaid
+ update-types: ["version-update:semver-major"]
+
- package-ecosystem: pip
directory: /tools/astyle
schedule:
interval: daily
cooldown:
default-days: 7
+ ignore:
+ # astyle is deliberately pinned (see tools/astyle/requirements.txt): newer versions
+ # reformat the code, and the pinned version defines the formatting CI enforces
+ - dependency-name: astyle
- package-ecosystem: pip
directory: /tools/generate_natvis
diff --git a/.github/external_ci/appveyor.yml b/.github/external_ci/appveyor.yml
index 5c6b47a34..805195742 100644
--- a/.github/external_ci/appveyor.yml
+++ b/.github/external_ci/appveyor.yml
@@ -30,14 +30,6 @@ environment:
CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 14 2015
- - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
- configuration: Release
- platform: x86
- name: with_win_header
- CXX_FLAGS: "/W4 /WX"
- CMAKE_OPTIONS: ""
- GENERATOR: Visual Studio 14 2015
-
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
configuration: Release
platform: x86
@@ -74,9 +66,6 @@ install:
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
before_build:
- # for with_win_header build, inject the inclusion of Windows.h to the single-header library
- - ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" }
- - ps: if ($env:name -Eq "with_win_header") { "#include `n" + (Get-Content $header_path | Out-String) | Set-Content $header_path }
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
build_script:
diff --git a/.github/workflows/cancel_closed_pr_runs.yml b/.github/workflows/cancel_closed_pr_runs.yml
new file mode 100644
index 000000000..4d8ee33e5
--- /dev/null
+++ b/.github/workflows/cancel_closed_pr_runs.yml
@@ -0,0 +1,53 @@
+name: "Cancel runs of closed pull requests"
+
+# The concurrency groups of the other workflows cancel superseded runs when a
+# pull request gets new commits, but nothing stops the runs of its last commit
+# once the pull request is merged or closed. They then keep the runners busy
+# for hours while the queue of the open pull requests waits.
+#
+# pull_request_target is needed to get a token that can cancel runs for pull
+# requests from forks. This is safe because the workflow never checks out or
+# runs code from the pull request; it only calls the API.
+on:
+ pull_request_target:
+ types: [closed]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+
+jobs:
+ cancel:
+ permissions:
+ actions: write
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
+ with:
+ egress-policy: audit
+
+ - name: Cancel unfinished runs of the pull request's head commit
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_REPO: ${{ github.repository }}
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
+ SELF: ${{ github.run_id }}
+ # only runs triggered by the pull request: when a branch is pushed to
+ # develop directly, its push runs share the head commit
+ run: |
+ gh api --paginate "repos/$GH_REPO/actions/runs?head_sha=$HEAD_SHA&per_page=100" \
+ --jq ".workflow_runs[]
+ | select(.status != \"completed\" and .id != $SELF)
+ | select(.event == \"pull_request\" or .event == \"pull_request_target\")
+ | \"\(.id) \(.name)\"" |
+ while read -r id name; do
+ echo "Cancelling run $id ($name)"
+ # a run may finish between listing and cancelling; that is not an error
+ gh run cancel "$id" || true
+ done
diff --git a/.github/workflows/check_amalgamation.yml b/.github/workflows/check_amalgamation.yml
index 670269cbb..2f234d8be 100644
--- a/.github/workflows/check_amalgamation.yml
+++ b/.github/workflows/check_amalgamation.yml
@@ -2,16 +2,23 @@ name: "Check amalgamation"
on:
pull_request:
+ # also check develop itself: a PR can be merged before its own run of this
+ # workflow completes (e.g. while it is still queued), leaving single_include
+ # stale on develop without any failing check
+ push:
+ branches:
+ - develop
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
- cancel-in-progress: true
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
save:
+ if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Harden Runner
@@ -35,6 +42,7 @@ jobs:
MAIN_DIR: ${{ github.workspace }}/main
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate
+ NATVIS_TOOL_DIR: ${{ github.workspace }}/tools/tools/generate_natvis
steps:
- name: Harden Runner
@@ -42,11 +50,11 @@ jobs:
with:
egress-policy: audit
- - name: Checkout pull request
+ - name: Checkout pull request or pushed commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: main
- ref: ${{ github.event.pull_request.head.sha }}
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Checkout tools
@@ -61,12 +69,55 @@ jobs:
python3 -mvenv venv
venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt
+ - name: Install generate_natvis dependencies
+ run: pip3 install -r $NATVIS_TOOL_DIR/requirements.txt
+
+ - name: Regenerate the tools/macro_builder tables in macro_scope.hpp
+ run: |
+ cd $MAIN_DIR
+
+ # Built from this PR's own tools/macro_builder/main.cpp, not a
+ # develop checkout: unlike amalgamate.py and generate_natvis.py,
+ # this tool has no other source of truth to check against (its
+ # own README documents that it must reproduce macro_scope.hpp
+ # byte for byte), so there is nothing to gain from checking out a
+ # separate copy, and doing so would make this step fail on a PR
+ # that adds support for a new dispatch table until that PR itself
+ # merges to develop, the same way generate_natvis.py's --version
+ # requirement briefly did.
+ TMPDIR=$(mktemp -d ./macro_builder_check.XXXXXX)
+ c++ -std=c++11 tools/macro_builder/main.cpp -o "$TMPDIR/macro_builder"
+ "$TMPDIR/macro_builder" > "$TMPDIR/paste.hpp"
+ "$TMPDIR/macro_builder" type_body > "$TMPDIR/type_body.hpp"
+
+ # Splice the (still unindented) generated blocks back into
+ # macro_scope.hpp; the astyle pass below indents their
+ # continuation lines the same way it does for the rest of
+ # include/, so a correctly regenerated file comes out unchanged.
+ awk -v newfile="$TMPDIR/paste.hpp" '
+ BEGIN { while ((getline line < newfile) > 0) { new = new line "\n" } }
+ /^#define NLOHMANN_JSON_EXPAND\( x \) x$/ { printf "%s", new; skip=1 }
+ skip && /^#define NLOHMANN_JSON_DOUBLE_PASTE63\(/ { skip=0; next }
+ skip { next }
+ { print }
+ ' include/nlohmann/detail/macro_scope.hpp > "$TMPDIR/macro_scope_1.hpp"
+ awk -v newfile="$TMPDIR/type_body.hpp" '
+ BEGIN { while ((getline line < newfile) > 0) { new = new line "\n" } }
+ /^#define NLOHMANN_JSON_TYPE_BODY\(Prefix, \.\.\.\)/ { printf "%s", new; skip=1 }
+ skip && /^[[:space:]]*NLOHMANN_JSON_TYPE_BODY_SENTINEL\)\)$/ { skip=0; next }
+ skip { next }
+ { print }
+ ' "$TMPDIR/macro_scope_1.hpp" > "$TMPDIR/macro_scope_2.hpp"
+ mv "$TMPDIR/macro_scope_2.hpp" include/nlohmann/detail/macro_scope.hpp
+ rm -rf "$TMPDIR"
+
- name: Regenerate amalgamation, formatting, and BUILD.bazel
run: |
cd $MAIN_DIR
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
+ cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
# the header list of the Bazel "json" target must match the files in include/
cmake -P cmake/scripts/gen_bazel_build_file.cmake
@@ -87,6 +138,19 @@ jobs:
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
$(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
+ - name: Regenerate nlohmann_json.natvis
+ run: |
+ cd $MAIN_DIR
+ # Pass --version explicitly so this step also works with the tool
+ # copy from develop before this repository's own generate_natvis.py
+ # learns to derive the version itself: the older script requires
+ # --version, and the newer one accepts it as an explicit override.
+ ABI_MACROS=include/nlohmann/detail/abi_macros.hpp
+ VERSION_MAJOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MAJOR' $ABI_MACROS | grep -o '[0-9]\+')
+ VERSION_MINOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MINOR' $ABI_MACROS | grep -o '[0-9]\+')
+ VERSION_PATCH=$(grep -m1 'define NLOHMANN_JSON_VERSION_PATCH' $ABI_MACROS | grep -o '[0-9]\+')
+ python3 $NATVIS_TOOL_DIR/generate_natvis.py --version "$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH" $MAIN_DIR
+
- name: Build patch and check for differences
id: diff
run: |
diff --git a/.github/workflows/check_docs_links.yml b/.github/workflows/check_docs_links.yml
new file mode 100644
index 000000000..342c96bff
--- /dev/null
+++ b/.github/workflows/check_docs_links.yml
@@ -0,0 +1,46 @@
+name: Check documentation links
+
+# check the links of the documentation weekly; external links break without any change in this repository
+on:
+ schedule:
+ - cron: '17 4 * * 1'
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: ${{ github.workflow }}
+ cancel-in-progress: true
+
+jobs:
+ check_docs_links:
+ if: github.repository == 'nlohmann/json'
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
+ with:
+ egress-policy: audit
+
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+
+ - name: Install virtual environment
+ run: make install_venv -C docs/mkdocs
+
+ - name: Check links
+ shell: bash # adds -o pipefail, so tee does not hide the exit code
+ run: make link_check -C docs/mkdocs 2>&1 | tee link_check.log
+
+ - name: Summarize broken links
+ if: failure()
+ run: |
+ {
+ echo '### Broken documentation links'
+ echo '```'
+ grep 'invalid url' link_check.log || true
+ echo '```'
+ } >> "$GITHUB_STEP_SUMMARY"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 74ecdfa91..9e86353c6 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -38,14 +38,14 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
+ uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
languages: c-cpp
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
+ uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
+ uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
diff --git a/.github/workflows/comment_check_amalgamation.yml b/.github/workflows/comment_check_amalgamation.yml
index 4667329d2..d5bd23fc8 100644
--- a/.github/workflows/comment_check_amalgamation.yml
+++ b/.github/workflows/comment_check_amalgamation.yml
@@ -10,7 +10,8 @@ permissions:
jobs:
comment:
- if: ${{ github.event.workflow_run.conclusion == 'failure' }}
+ # push runs on develop have no PR to comment on (and no "pr" artifact)
+ if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }}
runs-on: ubuntu-latest
permissions:
contents: read
diff --git a/.github/workflows/flawfinder.yml b/.github/workflows/flawfinder.yml
index 9f3b5562a..f37539a73 100644
--- a/.github/workflows/flawfinder.yml
+++ b/.github/workflows/flawfinder.yml
@@ -47,6 +47,6 @@ jobs:
output: 'flawfinder_results.sarif'
- name: Upload analysis results to GitHub Security tab
- uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
+ uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
diff --git a/.github/workflows/publish_documentation.yml b/.github/workflows/publish_documentation.yml
index 189d95419..5e39574bc 100644
--- a/.github/workflows/publish_documentation.yml
+++ b/.github/workflows/publish_documentation.yml
@@ -7,6 +7,16 @@ on:
- develop
paths:
- docs/mkdocs/**
+ # the site also embeds these files via pymdownx.snippets
+ # (mkdocs.yml sets restrict_base_path: false for this)
+ - .clang-tidy
+ - .github/CODE_OF_CONDUCT.md
+ - .github/CONTRIBUTING.md
+ - .github/SECURITY.md
+ - cmake/clang_flags.cmake
+ - cmake/gcc_flags.cmake
+ - tests/fmt_formatter/project/main.cpp
+ - tools/astyle/.astylerc
workflow_dispatch:
# we don't want to have concurrent jobs, and we don't want to cancel running jobs to avoid broken publications
@@ -23,7 +33,7 @@ jobs:
contents: write
if: github.repository == 'nlohmann/json'
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
@@ -31,6 +41,11 @@ jobs:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ # the git-revision-date-localized plugin needs the history for correct "last update" dates and so the
+ # strict build does not fail on a shallow clone
+ fetch-depth: 0
- name: Install virtual environment
run: make install_venv -C docs/mkdocs
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 5e4b0c315..bbf11dd28 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -80,6 +80,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
+ uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
sarif_file: results.sarif
diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
index 434e1f3bb..d8c717e83 100644
--- a/.github/workflows/semgrep.yml
+++ b/.github/workflows/semgrep.yml
@@ -65,7 +65,7 @@ jobs:
# Upload SARIF file generated in previous step
- name: Upload SARIF file
- uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
+ uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
sarif_file: semgrep.sarif
if: always()
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index d8c27c621..f5addb92e 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -52,6 +52,13 @@ jobs:
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_infer
+ - name: Archive Infer report
+ if: always()
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: infer-report
+ path: ${{ github.workspace }}/build/build_infer/infer-out/report.txt
+ if-no-files-found: ignore
ci_static_analysis_ubuntu:
runs-on: ubuntu-latest
@@ -78,7 +85,7 @@ jobs:
ci_static_analysis_clang:
runs-on: ubuntu-latest
- container: silkeh/clang:dev
+ container: silkeh/clang:22
strategy:
matrix:
target: [ci_test_clang, ci_clang_tidy, ci_test_clang_sanitizer, ci_clang_analyze, ci_single_binaries]
@@ -97,13 +104,13 @@ jobs:
ci_cmake_options:
runs-on: ubuntu-latest
- container: ubuntu:focal
+ container: ubuntu:24.04
strategy:
matrix:
- target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
+ target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
steps:
- name: Install build-essential
- run: apt-get update ; apt-get install -y build-essential unzip wget git libssl-dev
+ run: apt-get update ; apt-get install -y build-essential unzip wget git
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -346,6 +353,8 @@ jobs:
container: intel/oneapi-hpckit:latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake
@@ -358,6 +367,8 @@ jobs:
container: nvcr.io/nvidia/nvhpc:25.5-devel-cuda12.9-ubuntu22.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake
@@ -389,7 +400,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- target: [ci_test_examples, ci_test_build_documentation]
+ target: [ci_test_examples, ci_test_build_documentation, ci_test_documentation_mermaid]
steps:
- name: Harden Runner
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
@@ -399,7 +410,31 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
+ # the git-revision-date-localized plugin needs the history; a shallow clone makes the strict build fail
+ fetch-depth: ${{ matrix.target == 'ci_test_build_documentation' && '0' || '1' }}
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
+ if: matrix.target == 'ci_test_documentation_mermaid'
+ with:
+ node-version: 24
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
+
+ # Native Linux ARM64 runner with the latest GCC. The ubuntu-24.04-arm label is
+ # only available for public repositories.
+ ci_test_arm64:
+ runs-on: ubuntu-24.04-arm
+ container: gcc:latest
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+ - name: Get latest CMake and ninja
+ uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
+ - name: Check that the job runs natively on arm64
+ run: uname -m && test "$(uname -m)" = aarch64
+ - name: Run CMake
+ run: cmake -S . -B build -DJSON_CI=On
+ - name: Build
+ run: cmake --build build --target ci_test_compiler_default
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index ea742773f..65169eac4 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -87,6 +87,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Set extra CXX_FLAGS for latest std_version
@@ -123,6 +125,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Run CMake (Release)
run: cmake -S . -B build -G "Visual Studio 18 2026" -A ARM64 -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
if: matrix.build_type == 'Release'
diff --git a/.gitignore b/.gitignore
index 03fe8147e..474b62347 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,8 @@
/docs/docset/docSet.dsidx
/docs/mkdocs/.cache/
/docs/mkdocs/docs/__pycache__/
+/docs/mkdocs/hooks/__pycache__/
+/docs/mkdocs/scripts/mermaid/node_modules/
/docs/mkdocs/site/
/docs/mkdocs/venv/
diff --git a/.inferconfig b/.inferconfig
new file mode 100644
index 000000000..9a5a36873
--- /dev/null
+++ b/.inferconfig
@@ -0,0 +1,12 @@
+{
+ "_comment": "Used by the ci_infer CMake target (#5715 item 4b). fail-on-issue makes CI fail on Infer findings; disable-issue-type is a type-level baseline for the ~174 pre-existing findings (all PULSE_UNNECESSARY_COPY*/PULSE_RESOURCE_LEAK/PULSE_CONST_REFABLE, mostly in test code) triaged in run https://github.com/nlohmann/json/actions/runs/35829411620 on commit 1054b2097, so CI fails only on a NEW issue type. Remove an entry here once its findings have been fixed or explicitly accepted.",
+ "fail-on-issue": true,
+ "disable-issue-type": [
+ "PULSE_UNNECESSARY_COPY_ASSIGNMENT",
+ "PULSE_UNNECESSARY_COPY",
+ "PULSE_UNNECESSARY_COPY_INTERMEDIATE",
+ "PULSE_UNNECESSARY_COPY_OPTIONAL",
+ "PULSE_RESOURCE_LEAK",
+ "PULSE_CONST_REFABLE"
+ ]
+}
diff --git a/.reuse/dep5 b/.reuse/dep5
index ee3ae0b44..d12cb816c 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -23,10 +23,6 @@ Files: tests/thirdparty/fifo_map/*
Copyright: 2015-2017 Niels Lohmann
License: MIT
-Files: tests/thirdparty/Fuzzer/*
-Copyright: 2003-2022 LLVM Project.
-License: Apache-2.0
-
Files: tests/thirdparty/imapdl/*
Copyright: 2017 Georg Sauthoff
License: GPL-3.0-only
diff --git a/BUILD.bazel b/BUILD.bazel
index db59095cd..a9b09fd79 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -21,6 +21,7 @@ cc_library(
"include/nlohmann/adl_serializer.hpp",
"include/nlohmann/byte_container_with_subtype.hpp",
"include/nlohmann/detail/abi_macros.hpp",
+ "include/nlohmann/detail/bit_ops.hpp",
"include/nlohmann/detail/conversions/from_json.hpp",
"include/nlohmann/detail/conversions/to_chars.hpp",
"include/nlohmann/detail/conversions/to_json.hpp",
@@ -33,6 +34,7 @@ cc_library(
"include/nlohmann/detail/input/number_parse.hpp",
"include/nlohmann/detail/input/parser.hpp",
"include/nlohmann/detail/input/position_t.hpp",
+ "include/nlohmann/detail/input/pow5_table.hpp",
"include/nlohmann/detail/input/string_scan.hpp",
"include/nlohmann/detail/iterators/internal_iterator.hpp",
"include/nlohmann/detail/iterators/iter_impl.hpp",
@@ -51,7 +53,6 @@ cc_library(
"include/nlohmann/detail/meta/detected.hpp",
"include/nlohmann/detail/meta/identity_tag.hpp",
"include/nlohmann/detail/meta/is_sax.hpp",
- "include/nlohmann/detail/meta/logic.hpp",
"include/nlohmann/detail/meta/std_fs.hpp",
"include/nlohmann/detail/meta/type_traits.hpp",
"include/nlohmann/detail/meta/void_t.hpp",
@@ -65,6 +66,7 @@ cc_library(
"include/nlohmann/detail/value_t.hpp",
"include/nlohmann/json.hpp",
"include/nlohmann/json_fwd.hpp",
+ "include/nlohmann/json_literals.hpp",
"include/nlohmann/ordered_map.hpp",
"include/nlohmann/thirdparty/hedley/hedley.hpp",
"include/nlohmann/thirdparty/hedley/hedley_undef.hpp",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c43c23ff..b5092ae49 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,11 +55,13 @@ option(JSON_Diagnostic_Positions "Enable diagnostic positions." OFF)
option(JSON_GlobalUDLs "Place user-defined string literals in the global namespace." ON)
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF)
+option(JSON_DisableTupleReferenceConversion "Disable conversion from a one-element tuple of a JSON reference." OFF)
option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF)
option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." ON)
option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF)
option(JSON_StrictNulHandling "Build with strict NUL-byte handling enabled." OFF)
+option(JSON_StrictBinaryUTF8 "Build with UTF-8 checks in the CBOR, UBJSON, BJData, and BSON writers enabled." OFF)
if (JSON_CI)
include(ci)
@@ -101,6 +103,10 @@ if (JSON_DisableEnumSerialization)
message(STATUS "Enum integer serialization is disabled (JSON_DISABLE_ENUM_SERIALIZATION=1)")
endif()
+if (JSON_DisableTupleReferenceConversion)
+ message(STATUS "Tuple reference conversion is disabled (JSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1)")
+endif()
+
if (JSON_LegacyDiscardedValueComparison)
message(STATUS "Legacy discarded value comparison enabled (JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1)")
endif()
@@ -113,6 +119,10 @@ if (JSON_StrictNulHandling)
message(STATUS "Strict NUL-byte handling enabled (JSON_STRICT_NUL_HANDLING=1)")
endif()
+if (JSON_StrictBinaryUTF8)
+ message(STATUS "Strict UTF-8 checks in binary writers enabled (JSON_STRICT_BINARY_UTF8=1)")
+endif()
+
if (JSON_Diagnostic_Positions)
message(STATUS "Diagnostic positions enabled (JSON_DIAGNOSTIC_POSITIONS=1)")
endif()
@@ -143,10 +153,12 @@ target_compile_definitions(
$<$>:JSON_USE_GLOBAL_UDLS=0>
$<$>:JSON_USE_IMPLICIT_CONVERSIONS=0>
$<$:JSON_DISABLE_ENUM_SERIALIZATION=1>
+ $<$:JSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1>
$<$:JSON_DIAGNOSTICS=1>
$<$:JSON_DIAGNOSTIC_POSITIONS=1>
$<$:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
$<$:JSON_STRICT_NUL_HANDLING=1>
+ $<$:JSON_STRICT_BINARY_UTF8=1>
)
target_include_directories(
diff --git a/FILES.md b/FILES.md
index 263647146..d13be1238 100644
--- a/FILES.md
+++ b/FILES.md
@@ -33,17 +33,6 @@ Further documentation:
> [!IMPORTANT]
> The folder `.github/workflows` is predetermined by GitHub.
-### `.cirrus.yml`
-
-Configuration file for the pipeline at [Cirrus CI](https://cirrus-ci.com/github/nlohmann/json).
-
-Further documentation:
-
-- [Writing tasks](https://cirrus-ci.org/guide/writing-tasks/)
-
-> [!IMPORTANT]
-> The filename `.cirrus.yml` and position (root of the repository) are predetermined by Cirrus CI.
-
### `.github/external_ci/appveyor.yml`
Configuration for the pipelines at [AppVeyor](https://ci.appveyor.com/project/nlohmann/json).
diff --git a/Makefile b/Makefile
index 196f87243..3a7fa5c41 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel
+.PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check
##########################################################################
# configuration
@@ -21,6 +21,11 @@ TESTS_SRCS=$(shell find tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name
# the single headers (amalgamated from the source files)
AMALGAMATED_FILE=single_include/nlohmann/json.hpp
AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
+# json_literals.hpp only includes , so it is copied verbatim
+AMALGAMATED_LITERALS_FILE=single_include/nlohmann/json_literals.hpp
+
+# the header with the argument-counting macros generated by tools/macro_builder
+MACRO_SCOPE_HPP=include/nlohmann/detail/macro_scope.hpp
##########################################################################
@@ -29,18 +34,14 @@ AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
# main target
all:
- @echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd}.hpp from the include/nlohmann sources"
+ @echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd,_literals}.hpp from the include/nlohmann sources"
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
@echo "ChangeLog.md - generate ChangeLog file"
@echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date"
@echo "clean - remove built files"
- @echo "doctest - compile example files and check their output"
- @echo "fuzz_testing - prepare fuzz testing of the JSON parser"
- @echo "fuzz_testing_bon8 - prepare fuzz testing of the BON8 parser"
- @echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
- @echo "fuzz_testing_cbor - prepare fuzz testing of the CBOR parser"
- @echo "fuzz_testing_msgpack - prepare fuzz testing of the MessagePack parser"
- @echo "fuzz_testing_ubjson - prepare fuzz testing of the UBJSON parser"
+ @echo "fuzzing - see tests/fuzzing.md for how to build and run the fuzzers"
+ @echo "macro_builder_check - check that macro_scope.hpp matches tools/macro_builder's output"
+ @echo "natvis - regenerate nlohmann_json.natvis from the current ABI tags and version"
@echo "pretty - beautify code with Artistic Style"
@echo "run_benchmarks - build and run benchmarks"
@echo "update_hedley - download Hedley and regenerate hedley.hpp / hedley_undef.hpp"
@@ -59,74 +60,6 @@ run_benchmarks:
cd cmake-build-benchmarks ; ./json_benchmarks
-##########################################################################
-# fuzzing
-##########################################################################
-
-# the overall fuzz testing target
-fuzz_testing:
- rm -fr fuzz-testing
- mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
- $(MAKE) parse_afl_fuzzer -C tests CXX=afl-clang++
- mv tests/parse_afl_fuzzer fuzz-testing/fuzzer
- find tests/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases
- @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
-
-fuzz_testing_bon8:
- rm -fr fuzz-testing
- mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
- $(MAKE) parse_bon8_fuzzer -C tests CXX=afl-clang++
- mv tests/parse_bon8_fuzzer fuzz-testing/fuzzer
- find tests/data -size -5k -name *.bon8 | xargs -I{} cp "{}" fuzz-testing/testcases
- @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
-
-fuzz_testing_bson:
- rm -fr fuzz-testing
- mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
- $(MAKE) parse_bson_fuzzer -C tests CXX=afl-clang++
- mv tests/parse_bson_fuzzer fuzz-testing/fuzzer
- find tests/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases
- @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
-
-fuzz_testing_cbor:
- rm -fr fuzz-testing
- mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
- $(MAKE) parse_cbor_fuzzer -C tests CXX=afl-clang++
- mv tests/parse_cbor_fuzzer fuzz-testing/fuzzer
- find tests/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases
- @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
-
-fuzz_testing_msgpack:
- rm -fr fuzz-testing
- mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
- $(MAKE) parse_msgpack_fuzzer -C tests CXX=afl-clang++
- mv tests/parse_msgpack_fuzzer fuzz-testing/fuzzer
- find tests/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases
- @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
-
-fuzz_testing_ubjson:
- rm -fr fuzz-testing
- mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
- $(MAKE) parse_ubjson_fuzzer -C tests CXX=afl-clang++
- mv tests/parse_ubjson_fuzzer fuzz-testing/fuzzer
- find tests/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases
- @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
-
-fuzzing-start:
- afl-fuzz -S fuzzer1 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -S fuzzer2 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -S fuzzer3 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -S fuzzer4 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -S fuzzer5 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -S fuzzer6 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -S fuzzer7 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
- afl-fuzz -M fuzzer0 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer
-
-fuzzing-stop:
- -killall fuzzer
- -killall afl-fuzz
-
-
##########################################################################
# Static analysis
##########################################################################
@@ -154,14 +87,10 @@ install_astyle:
# call the Artistic Style pretty printer on all source files
pretty: install_astyle
- $(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/mkdocs/docs/examples/*.cpp
-
-# call the Clang-Format on all source files
-pretty_format:
- for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/mkdocs/docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
+ $(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) docs/mkdocs/docs/examples/*.cpp docs/mkdocs/docs/examples/*.hpp
# create single header files and pretty print
-amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
+amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE)
$(MAKE) pretty
# call the amalgamation tool for json.hpp
@@ -172,20 +101,50 @@ $(AMALGAMATED_FILE): $(SRCS)
$(AMALGAMATED_FWD_FILE): $(SRCS)
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_fwd.json -s . --verbose=yes
+# copy json_literals.hpp
+$(AMALGAMATED_LITERALS_FILE): include/nlohmann/json_literals.hpp
+ cp include/nlohmann/json_literals.hpp $(AMALGAMATED_LITERALS_FILE)
+
+# regenerate nlohmann_json.natvis from the ABI tags and version in include/nlohmann/detail/abi_macros.hpp
+natvis:
+ python3 tools/generate_natvis/generate_natvis.py .
+
+# regenerate the two tools/macro_builder blocks of $(MACRO_SCOPE_HPP) (see its README.md) and diff against the
+# checked-in header; phony, because it never writes $(MACRO_SCOPE_HPP) itself
+macro_builder_check:
+ @set -e; \
+ TMPDIR=$$(mktemp -d ./macro_builder_check.XXXXXX); \
+ trap 'rm -rf "$$TMPDIR"' EXIT; \
+ $(CXX) -std=c++11 tools/macro_builder/main.cpp -o "$$TMPDIR/macro_builder"; \
+ "$$TMPDIR/macro_builder" > "$$TMPDIR/paste.hpp"; \
+ "$$TMPDIR/macro_builder" type_body > "$$TMPDIR/type_body.hpp"; \
+ $(ASTYLE) --project=tools/astyle/.astylerc --suffix=none --quiet "$$TMPDIR/paste.hpp" "$$TMPDIR/type_body.hpp"; \
+ sed -n '/^#define NLOHMANN_JSON_EXPAND( x ) x$$/,/^#define NLOHMANN_JSON_DOUBLE_PASTE63(/p' $(MACRO_SCOPE_HPP) > "$$TMPDIR/paste_actual.hpp"; \
+ sed -n '/^#define NLOHMANN_JSON_TYPE_BODY(Prefix, \.\.\.)/,/^ NLOHMANN_JSON_TYPE_BODY_SENTINEL))$$/p' $(MACRO_SCOPE_HPP) > "$$TMPDIR/type_body_actual.hpp"; \
+ diff "$$TMPDIR/paste.hpp" "$$TMPDIR/paste_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_EXPAND..NLOHMANN_JSON_DOUBLE_PASTE63) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1); \
+ diff "$$TMPDIR/type_body.hpp" "$$TMPDIR/type_body_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_TYPE_BODY) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1)
+
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
-# Note: this target is called by Travis
check-amalgamation:
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
@mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
+ @mv $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~
@$(MAKE) amalgamate
@diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
@diff $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE) ; false)
+ @diff $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE) ; false)
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
@mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
+ @mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE)
@mv BUILD.bazel BUILD.bazel~
@$(MAKE) BUILD.bazel
@diff BUILD.bazel BUILD.bazel~ || (echo "===================================================================\n BUILD.bazel is out of date! Please run 'make BUILD.bazel'.\n===================================================================" ; mv BUILD.bazel~ BUILD.bazel ; false)
@mv BUILD.bazel~ BUILD.bazel
+ @mv nlohmann_json.natvis nlohmann_json.natvis~
+ @$(MAKE) natvis
+ @diff nlohmann_json.natvis nlohmann_json.natvis~ || (echo "===================================================================\n nlohmann_json.natvis is out of date! Please run 'make natvis'.\n===================================================================" ; mv nlohmann_json.natvis~ nlohmann_json.natvis ; false)
+ @mv nlohmann_json.natvis~ nlohmann_json.natvis
+ @$(MAKE) macro_builder_check
# generate the Bazel BUILD file; phony, because a removed header would not trigger a rebuild
BUILD.bazel:
@@ -222,7 +181,7 @@ json.tar.xz:
# We use `-X` to make the resulting ZIP file reproducible, see
# .
include.zip: BUILD.bazel
- zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
+ zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
# Create the files for a release and add signatures and hashes.
release: include.zip json.tar.xz
@@ -231,11 +190,13 @@ release: include.zip json.tar.xz
gpg --armor --detach-sig include.zip
gpg --armor --detach-sig $(AMALGAMATED_FILE)
gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE)
+ gpg --armor --detach-sig $(AMALGAMATED_LITERALS_FILE)
gpg --armor --detach-sig json.tar.xz
cp $(AMALGAMATED_FILE) release_files
cp $(AMALGAMATED_FWD_FILE) release_files
- mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
- cd release_files ; shasum -a 256 json.hpp include.zip json.tar.xz > hashes.txt
+ cp $(AMALGAMATED_LITERALS_FILE) release_files
+ mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc $(AMALGAMATED_LITERALS_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
+ cd release_files ; shasum -a 256 $$(find . -type f -not -name '*.asc' | sed 's|^\./||' | sort) > hashes.txt
##########################################################################
@@ -245,7 +206,6 @@ release: include.zip json.tar.xz
# clean up
clean:
rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM
- rm -fr benchmarks/files/numbers/*.json
rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files
$(MAKE) clean -Cdocs
diff --git a/README.md b/README.md
index cc3546686..ae0ad12d2 100644
--- a/README.md
+++ b/README.md
@@ -7,13 +7,11 @@
[](https://coveralls.io/github/nlohmann/json?branch=develop)
[](https://scan.coverity.com/projects/nlohmann-json)
[](https://app.codacy.com/gh/nlohmann/json/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
-[](https://cirrus-ci.com/github/nlohmann/json)
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
[](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
[](https://json.nlohmann.me)
[](https://raw.githubusercontent.com/nlohmann/json/develop/LICENSE.MIT)
[](https://github.com/nlohmann/json/releases)
-[](https://repology.org/project/nlohmann-json/versions)
[](https://github.com/nlohmann/json/releases)
[](https://github.com/nlohmann/json/issues)
[](https://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue")
@@ -1395,6 +1393,7 @@ THE SOFTWARE IS PROVIDED βAS ISβ, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
- The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
- The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
- The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
+- The class contains an adapted version of the Eisel-Lemire algorithm and its table of powers of five from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
diff --git a/cmake/ci.cmake b/cmake/ci.cmake
index f7695c36e..2aceb5afd 100644
--- a/cmake/ci.cmake
+++ b/cmake/ci.cmake
@@ -8,24 +8,24 @@ set(N 10)
include(FindPython3)
find_package(Python3 COMPONENTS Interpreter)
-find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
+find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-22 clang++-21 clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
message(STATUS "π Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
-find_program(CLANG_TIDY_TOOL NAMES clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
+find_program(CLANG_TIDY_TOOL NAMES clang-tidy-22 clang-tidy-21 clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
message(STATUS "π Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
message(STATUS "π CMake ${CMAKE_VERSION} (${CMAKE_COMMAND})")
-find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++ g++-15 g++-14 g++-13 g++-12 g++-11 g++-10)
+find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++ g++-16 g++-15 g++-14 g++-13 g++-12 g++-11 g++-10)
execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
message(STATUS "π GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
-find_program(GCOV_TOOL NAMES gcov-HEAD gcov gcov-15 gcov-14 gcov-13 gcov-12 gcov-11 gcov-10)
+find_program(GCOV_TOOL NAMES gcov-HEAD gcov gcov-16 gcov-15 gcov-14 gcov-13 gcov-12 gcov-11 gcov-10)
execute_process(COMMAND ${GCOV_TOOL} --version OUTPUT_VARIABLE GCOV_TOOL_VERSION ERROR_VARIABLE GCOV_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCOV_TOOL_VERSION "${GCOV_TOOL_VERSION}")
message(STATUS "π GCOV ${GCOV_TOOL_VERSION} (${GCOV_TOOL})")
@@ -40,6 +40,14 @@ execute_process(COMMAND ${IWYU_TOOL} --version OUTPUT_VARIABLE IWYU_TOOL_VERSION
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
message(STATUS "π include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
+# CMake's CXX_INCLUDE_WHAT_YOU_USE launcher runs IWYU during the normal compile step (useful to see
+# diagnostics inline), but CMake's own __run_co_compile wrapper does not propagate the launched
+# tool's exit code to the build, so IWYU's own "-Xiwyu --error" cannot fail that step (verified: a
+# deliberately-unused #include in a header still lets `cmake --build` finish with exit code 0).
+# iwyu_tool.py, which ships with IWYU, reads compile_commands.json and does return a non-zero exit
+# code for any analyzed file with findings; ci_single_binaries uses it to actually fail on findings.
+find_program(IWYU_TOOL_PY NAMES iwyu_tool iwyu_tool.py iwyu-tool)
+
find_program(INFER_TOOL NAMES infer)
execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
@@ -55,12 +63,6 @@ execute_process(COMMAND ${NINJA_TOOL} --version OUTPUT_VARIABLE NINJA_TOOL_VERSI
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
message(STATUS "π Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
-find_program(OCLINT_TOOL NAMES oclint-json-compilation-database)
-find_program(OCLINT_VERSION_TOOL NAMES oclint)
-execute_process(COMMAND ${OCLINT_VERSION_TOOL} --version OUTPUT_VARIABLE OCLINT_TOOL_VERSION ERROR_VARIABLE OCLINT_TOOL_VERSION)
-string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" OCLINT_TOOL_VERSION "${OCLINT_TOOL_VERSION}")
-message(STATUS "π OCLint ${OCLINT_TOOL_VERSION} (${OCLINT_TOOL})")
-
find_program(VALGRIND_TOOL NAMES valgrind)
execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
@@ -128,16 +130,16 @@ foreach(CXX_STANDARD 11 14 17 20 23 26)
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
)
+ # pass -stdlib=libc++ through CXXFLAGS: an explicit -DCMAKE_CXX_FLAGS would make CMake ignore CXXFLAGS
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
- COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
+ COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS};-stdlib=libc++" ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_FastTests=ON
-DJSON_TestStandards=${CXX_STANDARD}
- -DCMAKE_CXX_FLAGS="-stdlib=libc++"
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
- -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
- COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
- COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
+ -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
+ COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
+ COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
)
endforeach()
@@ -276,6 +278,20 @@ add_custom_target(ci_test_disableenumserialization
COMMENT "Compile and test with enum serialization disabled"
)
+###############################################################################
+# Disable conversion from a one-element tuple of a JSON reference.
+###############################################################################
+
+add_custom_target(ci_test_disabletuplereferenceconversion
+ COMMAND ${CMAKE_COMMAND}
+ -DCMAKE_BUILD_TYPE=Debug -GNinja
+ -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_DisableTupleReferenceConversion=ON
+ -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion
+ COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion
+ COMMAND cd ${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
+ COMMENT "Compile and test with tuple reference conversion disabled"
+)
+
###############################################################################
# Skip the multiple-inclusion library version check.
###############################################################################
@@ -362,20 +378,29 @@ add_custom_target(ci_test_clang_sanitizer
# Check if header is amalgamated and sources are properly indented.
###############################################################################
+# Same file set as .github/workflows/check_amalgamation.yml, so a direct push to develop/master/release/*
+# (which only this CMake target checks, not the pull_request-only workflow) is held to the same standard.
file(GLOB_RECURSE INDENT_FILES
- ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
- ${PROJECT_SOURCE_DIR}/tests/src/*.cpp
- ${PROJECT_SOURCE_DIR}/tests/src/*.hpp
- ${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
+ ${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
+ ${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cu
+ ${PROJECT_SOURCE_DIR}/include/*.hpp
+ ${PROJECT_SOURCE_DIR}/include/*.cpp
+ ${PROJECT_SOURCE_DIR}/include/*.cu
+ ${PROJECT_SOURCE_DIR}/tests/*.hpp
+ ${PROJECT_SOURCE_DIR}/tests/*.cpp
+ ${PROJECT_SOURCE_DIR}/tests/*.cu
)
+list(FILTER INDENT_FILES EXCLUDE REGEX "/tests/thirdparty/|/tests/abi/include/nlohmann/")
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
add_custom_target(ci_test_amalgamation
- COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~
+ COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
+ COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
+ COMMAND cp ${PROJECT_SOURCE_DIR}/BUILD.bazel ${PROJECT_SOURCE_DIR}/BUILD.bazel~
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
@@ -383,16 +408,20 @@ add_custom_target(ci_test_amalgamation
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
+ COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
+ COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
+ COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
+ COMMAND diff ${PROJECT_SOURCE_DIR}/BUILD.bazel~ ${PROJECT_SOURCE_DIR}/BUILD.bazel
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- COMMENT "Check amalgamation and indentation"
+ COMMENT "Check amalgamation, formatting, and BUILD.bazel"
)
###############################################################################
@@ -427,14 +456,14 @@ add_custom_target(ci_test_valgrind
# Check code with Clang Static Analyzer.
###############################################################################
-set(CLANG_ANALYZER_CHECKS "fuchsia.HandleChecker,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.mpi.MPI-Checker,optin.osx.OSObjectCStyleCast,optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,optin.osx.cocoa.localizability.NonLocalizedStringChecker,optin.performance.GCDAntipattern,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,osx.API,osx.MIG,osx.NumberObjectConversion,osx.OSObjectRetainCount,osx.ObjCProperty,osx.SecKeychainAPI,osx.cocoa.AtSync,osx.cocoa.AutoreleaseWrite,osx.cocoa.ClassRelease,osx.cocoa.Dealloc,osx.cocoa.IncompatibleMethodTypes,osx.cocoa.Loops,osx.cocoa.MissingSuperCall,osx.cocoa.NSAutoreleasePool,osx.cocoa.NSError,osx.cocoa.NilArg,osx.cocoa.NonNilReturnValue,osx.cocoa.ObjCGenerics,osx.cocoa.RetainCount,osx.cocoa.RunLoopAutoreleaseLeak,osx.cocoa.SelfInit,osx.cocoa.SuperDealloc,osx.cocoa.UnusedIvars,osx.cocoa.VariadicMethodTypes,osx.coreFoundation.CFError,osx.coreFoundation.CFNumber,osx.coreFoundation.CFRetainRelease,osx.coreFoundation.containers.OutOfBounds,osx.coreFoundation.containers.PointerSizedValues,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
+set(CLANG_ANALYZER_CHECKS "nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
add_custom_target(ci_clang_analyze
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
- COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} -analyze-headers -o ${PROJECT_BINARY_DIR}/report ninja
+ COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} --use-analyzer=${CLANG_TOOL} -analyze-headers --status-bugs -o ${PROJECT_BINARY_DIR}/report ninja
COMMENT "Check code with Clang Analyzer"
)
@@ -450,7 +479,7 @@ add_custom_target(ci_cppcheck
COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force
--std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
- --cppcheck-build-dir=cppcheck --check-level=exhaustive
+ --cppcheck-build-dir=cppcheck
-UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW
-DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON
COMMENT "Check code with Cppcheck"
@@ -468,34 +497,6 @@ add_custom_target(ci_cpplint
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
)
-###############################################################################
-# Check code with OCLint.
-###############################################################################
-
-file(COPY ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp DESTINATION ${PROJECT_BINARY_DIR}/src_single)
-file(RENAME ${PROJECT_BINARY_DIR}/src_single/json.hpp ${PROJECT_BINARY_DIR}/src_single/all.cpp)
-file(APPEND "${PROJECT_BINARY_DIR}/src_single/all.cpp" "\n\nint main()\n{}\n")
-
-add_executable(single_all ${PROJECT_BINARY_DIR}/src_single/all.cpp)
-target_compile_features(single_all PRIVATE cxx_std_11)
-
-add_custom_target(ci_oclint
- COMMAND ${CMAKE_COMMAND}
- -DCMAKE_BUILD_TYPE=Debug
- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- -DJSON_BuildTests=OFF -DJSON_CI=ON
- -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_oclint
- COMMAND ${OCLINT_TOOL} -i ${PROJECT_BINARY_DIR}/build_oclint/src_single/all.cpp -p ${PROJECT_BINARY_DIR}/build_oclint --
- -report-type html -enable-global-analysis --max-priority-1=0 --max-priority-2=1000 --max-priority-3=2000
- --disable-rule=MultipleUnaryOperator
- --disable-rule=DoubleNegative
- --disable-rule=ShortVariableName
- --disable-rule=GotoStatement
- --disable-rule=LongLine
- -o ${PROJECT_BINARY_DIR}/build_oclint/oclint_report.html
- COMMENT "Check code with OCLint"
-)
-
###############################################################################
# Check code with Clang-Tidy.
###############################################################################
@@ -510,29 +511,16 @@ add_custom_target(ci_clang_tidy
COMMENT "Check code with Clang-Tidy"
)
-###############################################################################
-# Check code with PVS-Studio Analyzer .
-###############################################################################
-
-add_custom_target(ci_pvs_studio
- COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
- -DCMAKE_BUILD_TYPE=Debug
- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- -DJSON_BuildTests=ON
- -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_pvs_studio
- COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PVS_STUDIO_ANALYZER_TOOL} analyze -j 10
- COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PLOG_CONVERTER_TOOL} -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
- COMMENT "Check code with PVS Studio"
-)
-
###############################################################################
# Check code with Infer static analyzer.
###############################################################################
+# .inferconfig (repository root) pins --fail-on-issue and the currently-triaged issue types that
+# are disabled until they are addressed separately; see #5715 item 4b.
add_custom_target(ci_infer
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
- COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make
+ COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run --project-root ${PROJECT_SOURCE_DIR} -- make
COMMENT "Check code with Infer"
)
@@ -588,7 +576,13 @@ add_custom_target(ci_reproducible_tests
# be compiled individually.
###############################################################################
-set(iwyu_path_and_options ${IWYU_TOOL} -Xiwyu --max_line_length=300)
+set(iwyu_options -Xiwyu --error -Xiwyu --max_line_length=300)
+set(iwyu_path_and_options ${IWYU_TOOL} ${iwyu_options})
+
+# CMake needs to know the exact flags used to compile each src_single/*.cpp below to hand them to
+# iwyu_tool.py; JSON_CI already implies a from-scratch configure, so enabling this project-wide has
+# no downside here.
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
foreach(SRC_FILE ${SRC_FILES})
# get relative path of the header file
@@ -602,15 +596,40 @@ foreach(SRC_FILE ${SRC_FILES})
add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp)
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
- set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
- # remember binary for ci_single_binaries target
+ if(RELATIVE_SRC_FILE STREQUAL "json")
+ # see below: report json.hpp's diagnostics without --error, so they do not fail the build
+ set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${IWYU_TOOL} -Xiwyu --max_line_length=300)
+ else()
+ set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
+ endif()
+ # remember binary for ci_single_binaries
list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
+ # json.hpp pulls together the whole library behind heavily templated, SFINAE-based code, and
+ # IWYU's suggestion for its one truly ambiguous symbol (a container-comparison "swap,
+ # operator!=") is not deterministic between runs (observed , , and