diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge
index 9d9ca32183944..e547afaeb722f 100755
--- a/.ci/generate-buildkite-pipeline-premerge
+++ b/.ci/generate-buildkite-pipeline-premerge
@@ -128,9 +128,8 @@ if [[ "${windows_projects}" != "" ]]; then
limit: 2
timeout_in_minutes: 150
env:
- CC: 'cl'
- CXX: 'cl'
- LD: 'link'
+ MAX_PARALLEL_COMPILE_JOBS: '16'
+ MAX_PARALLEL_LINK_JOBS: '4'
commands:
- 'C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64'
- 'bash .ci/monolithic-windows.sh "$(echo ${windows_projects} | tr ' ' ';')" "$(echo ${windows_check_targets})"'
diff --git a/.ci/metrics/metrics.py b/.ci/metrics/metrics.py
index 48d2aa2f330ec..70b787665a8b9 100644
--- a/.ci/metrics/metrics.py
+++ b/.ci/metrics/metrics.py
@@ -130,34 +130,6 @@ def get_per_workflow_metrics(
workflow_jobs = workflow_run.jobs()
if workflow_jobs.totalCount == 0:
continue
- if workflow_jobs.totalCount > 1:
- raise ValueError(
- f"Encountered an unexpected number of jobs: {workflow_jobs.totalCount}"
- )
-
- created_at = workflow_jobs[0].created_at
- started_at = workflow_jobs[0].started_at
- completed_at = workflow_jobs[0].completed_at
-
- job_result = int(workflow_jobs[0].conclusion == "success")
- if job_result:
- # We still might want to mark the job as a failure if one of the steps
- # failed. This is required due to use setting continue-on-error in
- # the premerge pipeline to prevent sending emails while we are
- # testing the infrastructure.
- # TODO(boomanaiden154): Remove this once the premerge pipeline is no
- # longer in a testing state and we can directly assert the workflow
- # result.
- for step in workflow_jobs[0].steps:
- if step.conclusion != "success":
- job_result = 0
- break
-
- queue_time = started_at - created_at
- run_time = completed_at - started_at
-
- if run_time.seconds == 0:
- continue
if (
workflows_to_track[workflow_run.name] is None
@@ -170,20 +142,45 @@ def get_per_workflow_metrics(
):
break
- # The timestamp associated with the event is expected by Grafana to be
- # in nanoseconds.
- created_at_ns = int(created_at.timestamp()) * 10**9
-
- workflow_metrics.append(
- JobMetrics(
- workflow_run.name,
- queue_time.seconds,
- run_time.seconds,
- job_result,
- created_at_ns,
- workflow_run.id,
+ for workflow_job in workflow_jobs:
+ created_at = workflow_job.created_at
+ started_at = workflow_job.started_at
+ completed_at = workflow_job.completed_at
+
+ job_result = int(workflow_job.conclusion == "success")
+ if job_result:
+ # We still might want to mark the job as a failure if one of the steps
+ # failed. This is required due to use setting continue-on-error in
+ # the premerge pipeline to prevent sending emails while we are
+ # testing the infrastructure.
+ # TODO(boomanaiden154): Remove this once the premerge pipeline is no
+ # longer in a testing state and we can directly assert the workflow
+ # result.
+ for step in workflow_job.steps:
+ if step.conclusion != "success":
+ job_result = 0
+ break
+
+ queue_time = started_at - created_at
+ run_time = completed_at - started_at
+
+ if run_time.seconds == 0:
+ continue
+
+ # The timestamp associated with the event is expected by Grafana to be
+ # in nanoseconds.
+ created_at_ns = int(created_at.timestamp()) * 10**9
+
+ workflow_metrics.append(
+ JobMetrics(
+ workflow_run.name + "-" + workflow_job.name,
+ queue_time.seconds,
+ run_time.seconds,
+ job_result,
+ created_at_ns,
+ workflow_run.id,
+ )
)
- )
return workflow_metrics
diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh
index 68303a3ea153a..57b276f3e1df0 100755
--- a/.ci/monolithic-windows.sh
+++ b/.ci/monolithic-windows.sh
@@ -50,6 +50,10 @@ echo "--- cmake"
pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt
pip install -q -r "${MONOREPO_ROOT}"/.ci/requirements.txt
+export CC=cl
+export CXX=cl
+export LD=link
+
# The CMAKE_*_LINKER_FLAGS to disable the manifest come from research
# on fixing a build reliability issue on the build server, please
# see https://github.com/llvm/llvm-project/pull/82393 and
@@ -72,8 +76,8 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
-D CMAKE_EXE_LINKER_FLAGS="/MANIFEST:NO" \
-D CMAKE_MODULE_LINKER_FLAGS="/MANIFEST:NO" \
-D CMAKE_SHARED_LINKER_FLAGS="/MANIFEST:NO" \
- -D LLVM_PARALLEL_COMPILE_JOBS=16 \
- -D LLVM_PARALLEL_LINK_JOBS=4
+ -D LLVM_PARALLEL_COMPILE_JOBS=${MAX_PARALLEL_COMPILE_JOBS} \
+ -D LLVM_PARALLEL_LINK_JOBS=${MAX_PARALLEL_LINK_JOBS}
echo "--- ninja"
# Targets are not escaped as they are passed as separate arguments.
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 484b947bda402..dd4116fa16bc5 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -131,7 +131,7 @@
/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci @yota9
# Bazel build system.
-/utils/bazel/ @rupprecht @keith
+/utils/bazel/ @rupprecht @keith @aaronmondal
# InstallAPI and TextAPI
/llvm/**/TextAPI/ @cyndyishida
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index 566308bb3df8d..9863ff087ca86 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -730,6 +730,9 @@ llvm:regalloc:
lldb:
- lldb/**
+lldb-dap:
+ - lldb/tools/lldb-dap/**
+
backend:AMDGPU:
- '**/*amdgpu*'
- '**/*AMDGPU*'
diff --git a/.github/workflows/build-ci-container.yml b/.github/workflows/build-ci-container.yml
index 8a81d47186469..8272c8f6e266f 100644
--- a/.github/workflows/build-ci-container.yml
+++ b/.github/workflows/build-ci-container.yml
@@ -20,24 +20,31 @@ on:
jobs:
build-ci-container:
if: github.repository_owner == 'llvm'
- runs-on: depot-ubuntu-22.04-16
- outputs:
- container-name: ${{ steps.vars.outputs.container-name }}
- container-name-agent: ${{ steps.vars.outputs.container-name-agent }}
- container-name-tag: ${{ steps.vars.outputs.container-name-tag }}
- container-name-agent-tag: ${{ steps.vars.outputs.container-name-agent-tag }}
- container-filename: ${{ steps.vars.outputs.container-filename }}
- container-agent-filename: ${{ steps.vars.outputs.container-agent-filename }}
+ runs-on: ${{ matrix.runs-on }}
+ strategy:
+ matrix:
+ include:
+ # The arch names should match the names used on dockerhub.
+ # See https://github.com/docker-library/official-images#architectures-other-than-amd64
+ - arch: amd64
+ runs-on: depot-ubuntu-22.04-16
+ - arch: arm64v8
+ runs-on: depot-ubuntu-22.04-arm-16
steps:
- name: Checkout LLVM
uses: actions/checkout@v4
with:
sparse-checkout: .github/workflows/containers/github-action-ci/
+ # podman is not installed by default on the ARM64 images.
+ - name: Install Podman
+ if: runner.arch == 'ARM64'
+ run: |
+ sudo apt-get install podman
- name: Write Variables
id: vars
run: |
- tag=`date +%s`
- container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/ci-ubuntu-22.04"
+ tag=$(git rev-parse --short=12 HEAD)
+ container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/${{ matrix.arch }}/ci-ubuntu-22.04"
echo "container-name=$container_name" >> $GITHUB_OUTPUT
echo "container-name-agent=$container_name-agent" >> $GITHUB_OUTPUT
echo "container-name-tag=$container_name:$tag" >> $GITHUB_OUTPUT
@@ -61,7 +68,7 @@ jobs:
- name: Upload container image
uses: actions/upload-artifact@v4
with:
- name: container
+ name: container-${{ matrix.arch }}
path: "*.tar"
retention-days: 14
@@ -84,18 +91,29 @@ jobs:
steps:
- name: Download container
uses: actions/download-artifact@v4
- with:
- name: container
- name: Push Container
run: |
- podman load -i ${{ needs.build-ci-container.outputs.container-filename }}
- podman tag ${{ needs.build-ci-container.outputs.container-name-tag }} ${{ needs.build-ci-container.outputs.container-name }}:latest
+ function push_container {
+ image_name=$1
+ latest_name=$(echo $image_name | sed 's/:[a-f0-9]\+$/:latest/g')
+ podman tag $image_name $latest_name
+ echo "Pushing $image_name ..."
+ podman push $image_name
+ echo "Pushing $latest_name ..."
+ podman push $latest_name
+ }
+
podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io
- podman push ${{ needs.build-ci-container.outputs.container-name-tag }}
- podman push ${{ needs.build-ci-container.outputs.container-name }}:latest
+ for f in $(find . -iname *.tar); do
+ image_name=$(podman load -q -i $f | sed 's/Loaded image: //g')
+ push_container $image_name
- podman load -i ${{ needs.build-ci-container.outputs.container-agent-filename }}
- podman tag ${{ needs.build-ci-container.outputs.container-name-agent-tag }} ${{ needs.build-ci-container.outputs.container-name-agent }}:latest
- podman push ${{ needs.build-ci-container.outputs.container-name-agent-tag }}
- podman push ${{ needs.build-ci-container.outputs.container-name-agent }}:latest
+ if echo $image_name | grep '/amd64/'; then
+ # For amd64, create an alias with the arch component removed.
+ # This matches the convention used on dockerhub.
+ default_image_name=$(echo $(dirname $(dirname $image_name))/$(basename $image_name))
+ podman tag $image_name $default_image_name
+ push_container $default_image_name
+ fi
+ done
diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml
deleted file mode 100644
index 2569ce19518e3..0000000000000
--- a/.github/workflows/clang-tests.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Clang Tests
-
-permissions:
- contents: read
-
-on:
- workflow_dispatch:
- push:
- branches:
- - 'release/**'
- paths:
- - 'clang/**'
- - '.github/workflows/clang-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!llvm/**'
- pull_request:
- branches:
- - 'release/**'
- paths:
- - 'clang/**'
- - '.github/workflows/clang-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!llvm/**'
-
-concurrency:
- # Skip intermediate builds: always.
- # Cancel intermediate builds: only if it is a pull request build.
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
-
-jobs:
- check_clang:
- if: github.repository_owner == 'llvm'
- name: Test clang,lldb,libclc
- uses: ./.github/workflows/llvm-project-tests.yml
- with:
- build_target: check-clang
- projects: clang;lldb;libclc
diff --git a/.github/workflows/commit-access-greeter.yml b/.github/workflows/commit-access-greeter.yml
new file mode 100644
index 0000000000000..29a1b578f8af8
--- /dev/null
+++ b/.github/workflows/commit-access-greeter.yml
@@ -0,0 +1,39 @@
+name: Commit Access Greeter
+
+on:
+ issues:
+ types:
+ - labeled
+
+permissions:
+ contents: read
+
+jobs:
+ commit-access-greeter:
+ permissions:
+ issues: write
+ if: >-
+ github.repository_owner == 'llvm' &&
+ github.event.label.name == 'infra:commit-access-request'
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+ with:
+ sparse-checkout: llvm/utils/git/
+
+ - name: Setup Automation Script
+ working-directory: ./llvm/utils/git/
+ run: |
+ pip install --require-hashes -r requirements.txt
+
+ - name: Add comments to issue
+ working-directory: ./llvm/utils/git/
+ env:
+ LABEL_NAME: ${{ github.event.label.name }}
+ GITHUB_TOKEN: ${{ github.token }}
+ ISSUE_NUMBER: ${{ github.event.issue.number }}
+ run: |
+ python3 ./github-automation.py \
+ --token $GITHUB_TOKEN \
+ commit-request-greeter \
+ --issue-number $ISSUE_NUMBER
diff --git a/.github/workflows/containers/github-action-ci-windows/Dockerfile b/.github/workflows/containers/github-action-ci-windows/Dockerfile
index 2295e39d62c30..9a1fab694c9df 100644
--- a/.github/workflows/containers/github-action-ci-windows/Dockerfile
+++ b/.github/workflows/containers/github-action-ci-windows/Dockerfile
@@ -108,7 +108,7 @@ RUN choco install -y handle
RUN pip3 install pywin32 buildbot-worker==2.8.4
-ARG RUNNER_VERSION=2.321.0
+ARG RUNNER_VERSION=2.322.0
ENV RUNNER_VERSION=$RUNNER_VERSION
RUN powershell -Command \
diff --git a/.github/workflows/containers/github-action-ci/Dockerfile b/.github/workflows/containers/github-action-ci/Dockerfile
index 35a0f1f6020dc..377b8f14402ee 100644
--- a/.github/workflows/containers/github-action-ci/Dockerfile
+++ b/.github/workflows/containers/github-action-ci/Dockerfile
@@ -96,7 +96,7 @@ WORKDIR /home/gha
FROM ci-container as ci-container-agent
-ENV GITHUB_RUNNER_VERSION=2.321.0
+ENV GITHUB_RUNNER_VERSION=2.322.0
RUN mkdir actions-runner && \
cd actions-runner && \
diff --git a/.github/workflows/libc-fullbuild-tests.yml b/.github/workflows/libc-fullbuild-tests.yml
index 2c88da653aae4..d93ac84116240 100644
--- a/.github/workflows/libc-fullbuild-tests.yml
+++ b/.github/workflows/libc-fullbuild-tests.yml
@@ -15,6 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
+ build_type: [Debug, Release, MinSizeRel]
include:
- os: ubuntu-24.04
ccache-variant: sccache
@@ -68,7 +69,7 @@ jobs:
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
- -DCMAKE_BUILD_TYPE=MinSizeRel
+ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-install-dir }}
diff --git a/.github/workflows/libc-overlay-tests.yml b/.github/workflows/libc-overlay-tests.yml
index 0a0916084b18c..de4b58c008ee4 100644
--- a/.github/workflows/libc-overlay-tests.yml
+++ b/.github/workflows/libc-overlay-tests.yml
@@ -16,6 +16,7 @@ jobs:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations.
fail-fast: false
matrix:
+ build_type: [Debug, Release, MinSizeRel]
include:
# TODO: add linux gcc when it is fixed
- os: ubuntu-24.04
@@ -95,7 +96,7 @@ jobs:
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.compiler.c_compiler }}
- -DCMAKE_BUILD_TYPE=MinSizeRel
+ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_POLICY_DEFAULT_CMP0141=NEW
diff --git a/.github/workflows/libclc-tests.yml b/.github/workflows/libclc-tests.yml
deleted file mode 100644
index 23192f776a985..0000000000000
--- a/.github/workflows/libclc-tests.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: libclc Tests
-
-permissions:
- contents: read
-
-on:
- workflow_dispatch:
- push:
- branches:
- - 'release/**'
- paths:
- - 'libclc/**'
- - '.github/workflows/libclc-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!clang/**'
- - '!llvm/**'
- pull_request:
- branches:
- - 'release/**'
- paths:
- - 'libclc/**'
- - '.github/workflows/libclc-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!clang/**'
- - '!llvm/**'
-
-concurrency:
- # Skip intermediate builds: always.
- # Cancel intermediate builds: only if it is a pull request build.
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
-
-jobs:
- check_libclc:
- if: github.repository_owner == 'llvm'
- name: Test libclc
- uses: ./.github/workflows/llvm-project-tests.yml
- with:
- projects: clang;libclc
diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml
index a28bf4d5daf6d..ee77e83363d37 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -48,8 +48,8 @@ jobs:
'generic-cxx26',
'generic-modules'
]
- cc: [ 'clang-19' ]
- cxx: [ 'clang++-19' ]
+ cc: [ 'clang-20' ]
+ cxx: [ 'clang++-20' ]
include:
- config: 'generic-gcc'
cc: 'gcc-14'
@@ -88,18 +88,18 @@ jobs:
'generic-cxx20',
'generic-cxx23'
]
- cc: [ 'clang-19' ]
- cxx: [ 'clang++-19' ]
+ cc: [ 'clang-20' ]
+ cxx: [ 'clang++-20' ]
include:
- config: 'generic-gcc-cxx11'
cc: 'gcc-14'
cxx: 'g++-14'
- config: 'generic-cxx23'
- cc: 'clang-17'
- cxx: 'clang++-17'
- - config: 'generic-cxx26'
cc: 'clang-18'
cxx: 'clang++-18'
+ - config: 'generic-cxx26'
+ cc: 'clang-19'
+ cxx: 'clang++-19'
steps:
- uses: actions/checkout@v4
- name: ${{ matrix.config }}
@@ -169,8 +169,8 @@ jobs:
- name: ${{ matrix.config }}
run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
env:
- CC: clang-19
- CXX: clang++-19
+ CC: clang-20
+ CXX: clang++-20
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
if: always()
with:
diff --git a/.github/workflows/libcxx-build-containers.yml b/.github/workflows/libcxx-build-containers.yml
index 2d040f712ce59..bb4bd8843772f 100644
--- a/.github/workflows/libcxx-build-containers.yml
+++ b/.github/workflows/libcxx-build-containers.yml
@@ -9,7 +9,6 @@ name: Build Docker images for libc++ CI
permissions:
contents: read
- packages: write
on:
push:
diff --git a/.github/workflows/lld-tests.yml b/.github/workflows/lld-tests.yml
deleted file mode 100644
index 599c0975fa685..0000000000000
--- a/.github/workflows/lld-tests.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: LLD Tests
-
-permissions:
- contents: read
-
-on:
- workflow_dispatch:
- push:
- branches:
- - 'release/**'
- paths:
- - 'lld/**'
- - '.github/workflows/lld-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!llvm/**'
- pull_request:
- branches:
- - 'release/**'
- paths:
- - 'lld/**'
- - '.github/workflows/lld-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!llvm/**'
-
-concurrency:
- # Skip intermediate builds: always.
- # Cancel intermediate builds: only if it is a pull request build.
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
-
-jobs:
- check_lld:
- if: github.repository_owner == 'llvm'
- name: Test lld
- uses: ./.github/workflows/llvm-project-tests.yml
- with:
- build_target: check-lld
- projects: lld
diff --git a/.github/workflows/lldb-tests.yml b/.github/workflows/lldb-tests.yml
deleted file mode 100644
index 6bb9721956258..0000000000000
--- a/.github/workflows/lldb-tests.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: lldb Tests
-
-permissions:
- contents: read
-
-on:
- workflow_dispatch:
- push:
- branches:
- - 'release/**'
- paths:
- - 'lldb/**'
- - '.github/workflows/lldb-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!clang/**'
- - '!llvm/**'
- pull_request:
- branches:
- - 'release/**'
- paths:
- - 'lldb/**'
- - '.github/workflows/lldb-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
- - '!clang/**'
- - '!llvm/**'
-
-concurrency:
- # Skip intermediate builds: always.
- # Cancel intermediate builds: only if it is a pull request build.
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
-
-jobs:
- build_lldb:
- if: github.repository_owner == 'llvm'
- name: Build lldb
- uses: ./.github/workflows/llvm-project-tests.yml
- with:
- projects: clang;lldb
diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml
index 4e570a7cb1455..9b3d49d4e99b9 100644
--- a/.github/workflows/llvm-tests.yml
+++ b/.github/workflows/llvm-tests.yml
@@ -11,14 +11,12 @@ on:
paths:
- 'llvm/**'
- '.github/workflows/llvm-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
pull_request:
branches:
- 'release/**'
paths:
- 'llvm/**'
- '.github/workflows/llvm-tests.yml'
- - '.github/workflows/llvm-project-tests.yml'
concurrency:
# Skip intermediate builds: always.
@@ -27,14 +25,6 @@ concurrency:
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
- check-all:
- if: github.repository_owner == 'llvm'
- name: Build and Test
- uses: ./.github/workflows/llvm-project-tests.yml
- with:
- build_target: check-all
- projects: clang;lld;libclc;lldb
-
abi-dump-setup:
if: github.repository_owner == 'llvm'
runs-on: ubuntu-latest
diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml
index 30f4fc807f3a5..178ab191a58be 100644
--- a/.github/workflows/premerge.yaml
+++ b/.github/workflows/premerge.yaml
@@ -5,19 +5,32 @@ permissions:
on:
pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # When a PR is closed, we still start this workflow, but then skip
+ # all the jobs, which makes it effectively a no-op. The reason to
+ # do this is that it allows us to take advantage of concurrency groups
+ # to cancel in progress CI jobs whenever the PR is closed.
+ - closed
paths:
- .github/workflows/premerge.yaml
push:
branches:
- 'main'
+ - 'release/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
jobs:
premerge-checks-linux:
- if: github.repository_owner == 'llvm'
+ if: >-
+ github.repository_owner == 'llvm' &&
+ (github.event_name != 'pull_request' || github.event.action != 'closed')
runs-on: llvm-premerge-linux-runners
- concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
- cancel-in-progress: true
steps:
- name: Checkout LLVM
uses: actions/checkout@v4
@@ -70,3 +83,132 @@ jobs:
export CXX=/opt/llvm/bin/clang++
./.ci/monolithic-linux.sh "$(echo ${linux_projects} | tr ' ' ';')" "$(echo ${linux_check_targets})" "$(echo ${linux_runtimes} | tr ' ' ';')" "$(echo ${linux_runtime_check_targets})"
+
+ premerge-checks-windows:
+ if: >-
+ github.repository_owner == 'llvm' &&
+ (github.event_name != 'pull_request' || github.event.action != 'closed')
+ runs-on: llvm-premerge-windows-runners
+ defaults:
+ run:
+ shell: bash
+ steps:
+ - name: Checkout LLVM
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+ - name: Setup ccache
+ uses: hendrikmuhs/ccache-action@v1.2.14
+ with:
+ variant: "sccache"
+ max-size: "2000M"
+ - name: Compute Projects
+ id: vars
+ run: |
+ modified_files=$(git diff --name-only HEAD~1...HEAD)
+ modified_dirs=$(echo "$modified_files" | cut -d'/' -f1 | sort | uniq)
+
+ echo $modified_files
+ echo $modified_dirs
+
+ . ./.ci/compute-projects.sh
+
+ all_projects="bolt clang clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl"
+ modified_projects="$(keep-modified-projects ${all_projects})"
+
+ windows_projects_to_test=$(exclude-windows $(compute-projects-to-test 1 ${modified_projects}))
+ windows_check_targets=$(check-targets ${windows_projects_to_test} | sort | uniq | tr -d '\r' | tr '\n' ' ')
+ windows_projects=$(add-dependencies ${windows_projects_to_test} | sort | uniq | tr -d '\r' | tr '\n' ';')
+
+ if [[ "${windows_projects}" == "" ]]; then
+ echo "No projects to build"
+ fi
+
+ echo "Building projects: ${windows_projects}"
+ echo "Running project checks targets: ${windows_check_targets}"
+
+ echo "windows-projects=${windows_projects}" >> $GITHUB_OUTPUT
+ echo "windows-check-targets=${windows_check_targets}" >> $GITHUB_OUTPUT
+ - name: Build and Test
+ # Mark the job as a success even if the step fails so that people do
+ # not get notified while the new premerge pipeline is in an
+ # experimental state.
+ # TODO(boomanaiden154): Remove this once the pipeline is stable and we
+ # are ready for people to start recieving notifications.
+ continue-on-error: true
+ if: ${{ steps.vars.outputs.windows-projects != '' }}
+ shell: cmd
+ run: |
+ set MAX_PARALLEL_COMPILE_JOBS=64
+ set MAX_PARALLEL_LINK_JOBS=64
+ call C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64
+ bash .ci/monolithic-windows.sh "${{ steps.vars.outputs.windows-projects }}" "${{ steps.vars.outputs.windows-check-targets }}"
+
+ permerge-check-macos:
+ runs-on: macos-14
+ if: >-
+ github.repository_owner == 'llvm' &&
+ (startswith(github.ref_name, 'release/') ||
+ startswith(github.base_ref, 'release/')) &&
+ (github.event_name != 'pull_request' || github.event.action != 'closed')
+ steps:
+ - name: Checkout LLVM
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+ - name: Setup ccache
+ uses: hendrikmuhs/ccache-action@v1.2.14
+ with:
+ max-size: "2000M"
+ - name: Install Ninja
+ uses: llvm/actions/install-ninja@main
+ - name: Build and Test
+ run: |
+ modified_files=$(git diff --name-only HEAD~1...HEAD)
+ modified_dirs=$(echo "$modified_files" | cut -d'/' -f1 | sort -u)
+
+ echo $modified_files
+ echo $modified_dirs
+
+ . ./.ci/compute-projects.sh
+
+ all_projects="clang clang-tools-extra lld lldb llvm mlir"
+ modified_projects="$(keep-modified-projects ${all_projects})"
+
+ # We have to disable the runtimes builds due to https://github.com/llvm/llvm-project/issues/90568
+ # and the lldb tests depend on libcxx, so we need to skip them.
+ mac_check_targets=$(check-targets ${modified_projects} | sort | uniq | tr '\n' ' ' | sed -e 's/check-lldb //g')
+ mac_projects=$(add-dependencies ${modified_projects} | sort | uniq | tr '\n' ' ')
+
+ mac_runtimes_to_test=$(compute-runtimes-to-test ${modified_projects})
+ mac_runtime_check_targets=$(check-targets ${mac_runtimes_to_test} | sort | uniq | tr '\n' ' ')
+ mac_runtimes=$(echo ${mac_runtimes_to_test} | tr ' ' '\n' | sort | uniq | tr '\n' ' ')
+
+ if [[ "${mac_projects}" == "" ]]; then
+ echo "No projects to build"
+ exit 0
+ fi
+
+ echo "Projects to test: ${modified_projects}"
+ echo "Runtimes to test: ${mac_runtimes_to_test}"
+ echo "Building projects: ${mac_projects}"
+ echo "Running project checks targets: ${mac_check_targets}"
+ echo "Building runtimes: ${mac_runtimes}"
+ echo "Running runtimes checks targets: ${mac_runtime_check_targets}"
+
+ # -DLLVM_DISABLE_ASSEMBLY_FILES=ON is for
+ # https://github.com/llvm/llvm-project/issues/81967
+ # Disable sharding in lit so that the LIT_XFAIL environment var works.
+ cmake -G Ninja \
+ -B build \
+ -S llvm \
+ -DLLVM_ENABLE_PROJECTS="$(echo ${mac_projects} | tr ' ' ';')" \
+ -DLLVM_DISABLE_ASSEMBLY_FILES=ON \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DLLDB_INCLUDE_TESTS=OFF \
+ -DLLVM_ENABLE_ASSERTIONS=ON \
+ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
+ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
+
+ # The libcxx tests fail, so we are skipping the runtime targets.
+ ninja -C build $mac_check_targets
diff --git a/.github/workflows/release-binaries-all.yml b/.github/workflows/release-binaries-all.yml
index d5b2d33286101..d18b9b0b5c2ff 100644
--- a/.github/workflows/release-binaries-all.yml
+++ b/.github/workflows/release-binaries-all.yml
@@ -83,6 +83,7 @@ jobs:
matrix:
runs-on:
- ubuntu-22.04
+ - ubuntu-22.04-arm
- macos-13
- macos-14
diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml
index f9a264e7cf48f..204ee6405382f 100644
--- a/.github/workflows/release-binaries.yml
+++ b/.github/workflows/release-binaries.yml
@@ -18,6 +18,7 @@ on:
type: choice
options:
- ubuntu-22.04
+ - ubuntu-22.04-arm
- macos-13
- macos-14
@@ -55,8 +56,8 @@ jobs:
ref: ${{ steps.vars.outputs.ref }}
upload: ${{ steps.vars.outputs.upload }}
target-cmake-flags: ${{ steps.vars.outputs.target-cmake-flags }}
+ ccache: ${{ steps.vars.outputs.ccache }}
build-flang: ${{ steps.vars.outputs.build-flang }}
- enable-pgo: ${{ steps.vars.outputs.enable-pgo }}
release-binary-basename: ${{ steps.vars.outputs.release-binary-basename }}
release-binary-filename: ${{ steps.vars.outputs.release-binary-filename }}
build-runs-on: ${{ steps.vars.outputs.build-runs-on }}
@@ -119,10 +120,15 @@ jobs:
echo "release-binary-basename=$release_binary_basename" >> $GITHUB_OUTPUT
echo "release-binary-filename=$release_binary_basename.tar.xz" >> $GITHUB_OUTPUT
- # Detect necessary CMake flags
target="$RUNNER_OS-$RUNNER_ARCH"
- echo "enable-pgo=false" >> $GITHUB_OUTPUT
- target_cmake_flags="-DLLVM_RELEASE_ENABLE_PGO=OFF"
+ # The hendrikmuhs/ccache-action action does not support installing sccache
+ # on arm64 Linux.
+ if [ "$target" = "Linux-ARM64" ]; then
+ echo ccache=ccache >> $GITHUB_OUTPUT
+ else
+ echo ccache=sccache >> $GITHUB_OUTPUT
+ fi
+
# The macOS builds try to cross compile some libraries so we need to
# add extra CMake args to disable them.
# See https://github.com/llvm/llvm-project/issues/99767
@@ -146,7 +152,7 @@ jobs:
echo "target-cmake-flags=$target_cmake_flags" >> $GITHUB_OUTPUT
echo "build-flang=$build_flang" >> $GITHUB_OUTPUT
case "${{ inputs.runs-on }}" in
- ubuntu-22.04)
+ ubuntu-22.04*)
build_runs_on="depot-${{ inputs.runs-on }}-16"
test_runs_on=$build_runs_on
;;
@@ -216,17 +222,11 @@ jobs:
id: setup-stage
uses: ./workflows-main/.github/workflows/release-binaries-setup-stage
- - name: Setup sccache
- uses: hendrikmuhs/ccache-action@ca3acd2731eef11f1572ccb126356c2f9298d35e # v1.2.9
- with:
- # Default to 2G to workaround: https://github.com/hendrikmuhs/ccache-action/issues/174
- max-size: 2G
- key: sccache-${{ runner.os }}-${{ runner.arch }}-release
- variant: sccache
-
- name: Configure
id: build
shell: bash
+ env:
+ CCACHE_BIN: ${{ needs.prepare.outputs.ccache }}
run: |
# There were some issues on the ARM64 MacOS runners with trying to build x86 object,
# so we need to set some extra cmake flags to disable this.
@@ -234,14 +234,14 @@ jobs:
${{ needs.prepare.outputs.target-cmake-flags }} \
-C clang/cmake/caches/Release.cmake \
-DBOOTSTRAP_LLVM_PARALLEL_LINK_JOBS=1 \
- -DBOOTSTRAP_CPACK_PACKAGE_FILE_NAME="${{ needs.prepare.outputs.release-binary-basename }}" \
- -DCMAKE_C_COMPILER_LAUNCHER=sccache \
- -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
+ -DBOOTSTRAP_BOOTSTRAP_CPACK_PACKAGE_FILE_NAME="${{ needs.prepare.outputs.release-binary-basename }}"
+
- name: Build
shell: bash
run: |
ninja -v -C ${{ steps.setup-stage.outputs.build-prefix }}/build stage2-package
- mv ${{ steps.setup-stage.outputs.build-prefix }}/build/tools/clang/stage2-bins/${{ needs.prepare.outputs.release-binary-filename }} .
+ release_dir=`find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname 'stage2-bins'`
+ mv $release_dir/${{ needs.prepare.outputs.release-binary-filename }} .
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
with:
@@ -256,7 +256,7 @@ jobs:
shell: bash
run: |
find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname ${{ needs.prepare.outputs.release-binary-filename }} -delete
- rm -Rf ${{ steps.setup-stage.outputs.build-prefix }}/build/tools/clang/stage2-bins/_CPack_Packages
+ find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname _CPack_Packages -prune -exec rm -r {} +
- name: Save Stage
uses: ./workflows-main/.github/workflows/release-binaries-save-stage
diff --git a/.github/workflows/release-tasks.yml b/.github/workflows/release-tasks.yml
index 780dd0ff6325c..52076ea1821b0 100644
--- a/.github/workflows/release-tasks.yml
+++ b/.github/workflows/release-tasks.yml
@@ -89,20 +89,10 @@ jobs:
needs:
- validate-tag
- release-create
- strategy:
- fail-fast: false
- matrix:
- runs-on:
- - ubuntu-22.04
- - windows-2022
- - macos-13
- - macos-14
-
- uses: ./.github/workflows/release-binaries.yml
+ uses: ./.github/workflows/release-binaries-all.yml
with:
release-version: ${{ needs.validate-tag.outputs.release-version }}
upload: true
- runs-on: ${{ matrix.runs-on }}
# Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use.
secrets:
RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }}
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index 94fe4aa8aa0e5..8bec1db70e25a 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -1435,6 +1435,17 @@ class BinaryContext {
bool PrintRelocations = false,
StringRef Endl = "\n") const;
+ /// Print data when embedded in the instruction stream keeping the format
+ /// similar to printInstruction().
+ void printData(raw_ostream &OS, ArrayRef Data,
+ uint64_t Offset) const;
+
+ /// Extract data from the binary corresponding to [Address, Address + Size)
+ /// range. Return an empty ArrayRef if the address range does not belong to
+ /// any section in the binary, crosses a section boundary, or falls into a
+ /// virtual section.
+ ArrayRef extractData(uint64_t Address, uint64_t Size) const;
+
/// Print a range of instructions.
template
uint64_t
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index e8b2757f7db21..942840a7621fd 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -2060,6 +2060,11 @@ class BinaryFunction {
return Islands ? Islands->getAlignment() : 1;
}
+ /// If there is a constant island in the range [StartOffset, EndOffset),
+ /// return its address.
+ std::optional getIslandInRange(uint64_t StartOffset,
+ uint64_t EndOffset) const;
+
uint64_t
estimateConstantIslandSize(const BinaryFunction *OnBehalfOf = nullptr) const {
if (!Islands)
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index 5d77e6faff2fc..c1460b2aac8a6 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -1426,11 +1426,12 @@ class MCPlusBuilder {
}
/// Creates an indirect call to the function within the \p DirectCall PLT
- /// stub. The function's memory location is pointed by the \p TargetLocation
+ /// stub. The function's address location is pointed by the \p TargetLocation
/// symbol.
+ /// Move instruction annotations from \p DirectCall to the indirect call.
virtual InstructionListType
- createIndirectPltCall(const MCInst &DirectCall,
- const MCSymbol *TargetLocation, MCContext *Ctx) {
+ createIndirectPLTCall(MCInst &&DirectCall, const MCSymbol *TargetLocation,
+ MCContext *Ctx) {
llvm_unreachable("not implemented");
return {};
}
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index f5e11358daaa3..f9fc536f3569a 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -1759,7 +1759,11 @@ void BinaryContext::preprocessDebugInfo() {
dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
if (std::optional DWOID = CU->getDWOId()) {
auto Iter = DWOCUs.find(*DWOID);
- assert(Iter != DWOCUs.end() && "DWO CU was not found.");
+ if (Iter == DWOCUs.end()) {
+ this->errs() << "BOLT-ERROR: DWO CU was not found for " << Name
+ << '\n';
+ exit(1);
+ }
Name = dwarf::toString(
Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
}
@@ -1942,6 +1946,43 @@ static void printDebugInfo(raw_ostream &OS, const MCInst &Instruction,
OS << " discriminator:" << Row.Discriminator;
}
+ArrayRef BinaryContext::extractData(uint64_t Address,
+ uint64_t Size) const {
+ ArrayRef Res;
+
+ const ErrorOr Section = getSectionForAddress(Address);
+ if (!Section || Section->isVirtual())
+ return Res;
+
+ if (!Section->containsRange(Address, Size))
+ return Res;
+
+ auto *Bytes =
+ reinterpret_cast(Section->getContents().data());
+ return ArrayRef(Bytes + Address - Section->getAddress(), Size);
+}
+
+void BinaryContext::printData(raw_ostream &OS, ArrayRef Data,
+ uint64_t Offset) const {
+ DataExtractor DE(Data, AsmInfo->isLittleEndian(),
+ AsmInfo->getCodePointerSize());
+ uint64_t DataOffset = 0;
+ while (DataOffset + 4 <= Data.size()) {
+ OS << format(" %08" PRIx64 ": \t.word\t0x", Offset + DataOffset);
+ const auto Word = DE.getUnsigned(&DataOffset, 4);
+ OS << Twine::utohexstr(Word) << '\n';
+ }
+ if (DataOffset + 2 <= Data.size()) {
+ OS << format(" %08" PRIx64 ": \t.short\t0x", Offset + DataOffset);
+ const auto Short = DE.getUnsigned(&DataOffset, 2);
+ OS << Twine::utohexstr(Short) << '\n';
+ }
+ if (DataOffset + 1 == Data.size()) {
+ OS << format(" %08" PRIx64 ": \t.byte\t0x%x\n", Offset + DataOffset,
+ Data[DataOffset]);
+ }
+}
+
void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction,
uint64_t Offset,
const BinaryFunction *Function,
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 1c5cd62a095b2..bc45caf3ec8b7 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -491,11 +491,27 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
// Offset of the instruction in function.
uint64_t Offset = 0;
+ auto printConstantIslandInRange = [&](uint64_t Start, uint64_t End) {
+ assert(Start <= End && "Invalid range");
+ std::optional IslandOffset = getIslandInRange(Start, End);
+
+ if (!IslandOffset)
+ return;
+
+ const size_t IslandSize = getSizeOfDataInCodeAt(*IslandOffset);
+ BC.printData(OS, BC.extractData(getAddress() + *IslandOffset, IslandSize),
+ *IslandOffset);
+ };
+
if (BasicBlocks.empty() && !Instructions.empty()) {
// Print before CFG was built.
+ uint64_t PrevOffset = 0;
for (const std::pair &II : Instructions) {
Offset = II.first;
+ // Print any constant islands inbeetween the instructions.
+ printConstantIslandInRange(PrevOffset, Offset);
+
// Print label if exists at this offset.
auto LI = Labels.find(Offset);
if (LI != Labels.end()) {
@@ -506,7 +522,12 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
}
BC.printInstruction(OS, II.second, Offset, this);
+
+ PrevOffset = Offset;
}
+
+ // Print any data at the end of the function.
+ printConstantIslandInRange(PrevOffset, getMaxSize());
}
StringRef SplitPointMsg = "";
@@ -795,7 +816,6 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
auto Begin = Instructions.begin();
if (BC.isAArch64()) {
- PreserveNops = BC.HasRelocations;
// Start at the last label as an approximation of the current basic block.
// This is a heuristic, since the full set of labels have yet to be
// determined
@@ -1049,6 +1069,19 @@ size_t BinaryFunction::getSizeOfDataInCodeAt(uint64_t Offset) const {
return getSize() - Offset;
}
+std::optional
+BinaryFunction::getIslandInRange(uint64_t StartOffset,
+ uint64_t EndOffset) const {
+ if (!Islands)
+ return std::nullopt;
+
+ auto Iter = llvm::lower_bound(Islands->DataOffsets, StartOffset);
+ if (Iter != Islands->DataOffsets.end() && *Iter < EndOffset)
+ return *Iter;
+
+ return std::nullopt;
+}
+
bool BinaryFunction::isZeroPaddingAt(uint64_t Offset) const {
ArrayRef FunctionData = *getData();
uint64_t EndOfCode = getSize();
@@ -2300,6 +2333,10 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
<< *this << '\n';
}
+
+ if (BC.isAArch64())
+ PreserveNops = BC.HasRelocations;
+
// In relocation mode we want to keep processing the function but avoid
// optimizing it.
setSimple(false);
diff --git a/bolt/lib/Passes/PLTCall.cpp b/bolt/lib/Passes/PLTCall.cpp
index 2ed996fadbb99..31c2d92ebc204 100644
--- a/bolt/lib/Passes/PLTCall.cpp
+++ b/bolt/lib/Passes/PLTCall.cpp
@@ -70,8 +70,8 @@ Error PLTCall::runOnFunctions(BinaryContext &BC) {
const BinaryFunction *CalleeBF = BC.getFunctionForSymbol(CallSymbol);
if (!CalleeBF || !CalleeBF->isPLTFunction())
continue;
- const InstructionListType NewCode = BC.MIB->createIndirectPltCall(
- *II, CalleeBF->getPLTSymbol(), BC.Ctx.get());
+ const InstructionListType NewCode = BC.MIB->createIndirectPLTCall(
+ std::move(*II), CalleeBF->getPLTSymbol(), BC.Ctx.get());
II = BB.replaceInstruction(II, NewCode);
assert(!NewCode.empty() && "PLT Call replacement must be non-empty");
std::advance(II, NewCode.size() - 1);
diff --git a/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp b/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
index 336c6768a7f71..8f5719e84ecea 100644
--- a/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
+++ b/bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
@@ -18,6 +18,7 @@
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
#define DEBUG_TYPE "bolt-rtlib"
@@ -38,6 +39,23 @@ std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
}
llvm::sys::path::append(LibPath, LibFileName);
+ if (!llvm::sys::fs::exists(LibPath)) {
+ // If it is a symlink, check the directory that the symlink points to.
+ if (llvm::sys::fs::is_symlink_file(ToolPath)) {
+ SmallString<256> RealPath;
+ llvm::sys::fs::real_path(ToolPath, RealPath);
+ if (llvm::ErrorOr P =
+ llvm::sys::findProgramByName(RealPath)) {
+ outs() << "BOLT-INFO: library not found: " << LibPath << "\n"
+ << "BOLT-INFO: " << ToolPath << " is a symlink; will look up "
+ << LibFileName
+ << " at the target directory that the symlink points to\n";
+ return getLibPath(*P, LibFileName);
+ }
+ }
+ errs() << "BOLT-ERROR: library not found: " << LibPath << "\n";
+ exit(1);
+ }
return std::string(LibPath);
}
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 0b6f21527f0ac..4b21ff719b3ab 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -834,6 +834,8 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
/// # of this BB)
/// br x0 # Indirect jump instruction
///
+ /// Return true on successful jump table instruction sequence match, false
+ /// otherwise.
bool analyzeIndirectBranchFragment(
const MCInst &Inst,
DenseMap> &UDChain,
@@ -842,6 +844,8 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
// Expect AArch64 BR
assert(Inst.getOpcode() == AArch64::BR && "Unexpected opcode");
+ JumpTable = nullptr;
+
// Match the indirect branch pattern for aarch64
SmallVector &UsesRoot = UDChain[&Inst];
if (UsesRoot.size() == 0 || UsesRoot[0] == nullptr)
@@ -879,8 +883,8 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
// Parsed as ADDXrs reg:x8 reg:x8 reg:x12 imm:0
return false;
}
- assert(DefAdd->getOpcode() == AArch64::ADDXrx &&
- "Failed to match indirect branch!");
+ if (DefAdd->getOpcode() != AArch64::ADDXrx)
+ return false;
// Validate ADD operands
int64_t OperandExtension = DefAdd->getOperand(3).getImm();
@@ -897,8 +901,8 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
// ldr w7, [x6]
// add x6, x6, w7, sxtw => no shift amount
// br x6
- errs() << "BOLT-WARNING: "
- "Failed to match indirect branch: ShiftVAL != 2 \n";
+ LLVM_DEBUG(dbgs() << "BOLT-DEBUG: "
+ "failed to match indirect branch: ShiftVAL != 2\n");
return false;
}
@@ -909,7 +913,7 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
else if (ExtendType == AArch64_AM::SXTW)
ScaleValue = 4LL;
else
- llvm_unreachable("Failed to match indirect branch! (fragment 3)");
+ return false;
// Match an ADR to load base address to be used when addressing JT targets
SmallVector &UsesAdd = UDChain[DefAdd];
@@ -920,18 +924,15 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
return false;
}
MCInst *DefBaseAddr = UsesAdd[1];
- assert(DefBaseAddr->getOpcode() == AArch64::ADR &&
- "Failed to match indirect branch pattern! (fragment 3)");
+ if (DefBaseAddr->getOpcode() != AArch64::ADR)
+ return false;
PCRelBase = DefBaseAddr;
// Match LOAD to load the jump table (relative) target
const MCInst *DefLoad = UsesAdd[2];
- assert(mayLoad(*DefLoad) &&
- "Failed to match indirect branch load pattern! (1)");
- assert((ScaleValue != 1LL || isLDRB(*DefLoad)) &&
- "Failed to match indirect branch load pattern! (2)");
- assert((ScaleValue != 2LL || isLDRH(*DefLoad)) &&
- "Failed to match indirect branch load pattern! (3)");
+ if (!mayLoad(*DefLoad) || (ScaleValue == 1LL && !isLDRB(*DefLoad)) ||
+ (ScaleValue == 2LL && !isLDRH(*DefLoad)))
+ return false;
// Match ADD that calculates the JumpTable Base Address (not the offset)
SmallVector &UsesLoad = UDChain[DefLoad];
@@ -941,7 +942,6 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
isRegToRegMove(*DefJTBaseAdd, From, To)) {
// Sometimes base address may have been defined in another basic block
// (hoisted). Return with no jump table info.
- JumpTable = nullptr;
return true;
}
@@ -953,24 +953,27 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
// adr x12, 0x247b30 <__gettextparse+0x5b0>
// add x13, x12, w13, sxth #2
// br x13
- errs() << "BOLT-WARNING: Failed to match indirect branch: "
- "nop/adr instead of adrp/add \n";
+ LLVM_DEBUG(dbgs() << "BOLT-DEBUG: failed to match indirect branch: "
+ "nop/adr instead of adrp/add\n");
return false;
}
- assert(DefJTBaseAdd->getOpcode() == AArch64::ADDXri &&
- "Failed to match jump table base address pattern! (1)");
+ if (DefJTBaseAdd->getOpcode() != AArch64::ADDXri) {
+ LLVM_DEBUG(dbgs() << "BOLT-DEBUG: failed to match jump table base "
+ "address pattern! (1)\n");
+ return false;
+ }
if (DefJTBaseAdd->getOperand(2).isImm())
Offset = DefJTBaseAdd->getOperand(2).getImm();
SmallVector &UsesJTBaseAdd = UDChain[DefJTBaseAdd];
const MCInst *DefJTBasePage = UsesJTBaseAdd[1];
if (DefJTBasePage == nullptr || isLoadFromStack(*DefJTBasePage)) {
- JumpTable = nullptr;
return true;
}
- assert(DefJTBasePage->getOpcode() == AArch64::ADRP &&
- "Failed to match jump table base page pattern! (2)");
+ if (DefJTBasePage->getOpcode() != AArch64::ADRP)
+ return false;
+
if (DefJTBasePage->getOperand(1).isExpr())
JumpTable = DefJTBasePage->getOperand(1).getExpr();
return true;
@@ -1263,7 +1266,7 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
return true;
}
- InstructionListType createIndirectPltCall(const MCInst &DirectCall,
+ InstructionListType createIndirectPLTCall(MCInst &&DirectCall,
const MCSymbol *TargetLocation,
MCContext *Ctx) override {
const bool IsTailCall = isTailCall(DirectCall);
@@ -1297,8 +1300,7 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
MCInst InstCall;
InstCall.setOpcode(IsTailCall ? AArch64::BR : AArch64::BLR);
InstCall.addOperand(MCOperand::createReg(AArch64::X17));
- if (IsTailCall)
- setTailCall(InstCall);
+ moveAnnotations(std::move(DirectCall), InstCall);
Code.emplace_back(InstCall);
return Code;
diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
index 63086c06d74fd..465533ee71f2b 100644
--- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
+++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
@@ -1605,7 +1605,7 @@ class X86MCPlusBuilder : public MCPlusBuilder {
return true;
}
- InstructionListType createIndirectPltCall(const MCInst &DirectCall,
+ InstructionListType createIndirectPLTCall(MCInst &&DirectCall,
const MCSymbol *TargetLocation,
MCContext *Ctx) override {
assert((DirectCall.getOpcode() == X86::CALL64pcrel32 ||
diff --git a/bolt/test/AArch64/data-in-code.s b/bolt/test/AArch64/data-in-code.s
new file mode 100644
index 0000000000000..8d3179a0c3350
--- /dev/null
+++ b/bolt/test/AArch64/data-in-code.s
@@ -0,0 +1,31 @@
+## Check that llvm-bolt prints data embedded in code.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -fno-PIC -no-pie %t.o -o %t.exe -nostdlib \
+# RUN: -fuse-ld=lld -Wl,-q
+
+## Check disassembly of BOLT input.
+# RUN: llvm-objdump %t.exe -d | FileCheck %s
+
+# RUN: llvm-bolt %t.exe -o %t.bolt --print-disasm | FileCheck %s
+
+.text
+.balign 4
+
+.global _start
+.type _start, %function
+_start:
+ mov x0, #0x0
+ .word 0x4f82e010
+ ret
+ .byte 0x0, 0xff, 0x42
+# CHECK-LABEL: _start
+# CHECK: mov x0, #0x0
+# CHECK-NEXT: .word 0x4f82e010
+# CHECK-NEXT: ret
+# CHECK-NEXT: .short 0xff00
+# CHECK-NEXT: .byte 0x42
+.size _start, .-_start
+
+## Force relocation mode.
+ .reloc 0, R_AARCH64_NONE
diff --git a/bolt/test/AArch64/exceptions-plt.cpp b/bolt/test/AArch64/exceptions-plt.cpp
new file mode 100644
index 0000000000000..33c28406ca8d6
--- /dev/null
+++ b/bolt/test/AArch64/exceptions-plt.cpp
@@ -0,0 +1,23 @@
+// Verify that PLT optimization in BOLT preserves exception-handling info.
+
+// REQUIRES: system-linux
+
+// RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+// RUN: %clangxx %cxxflags -O1 -Wl,-q,-znow %s %t.so -o %t.exe
+// RUN: llvm-bolt %t.exe -o %t.bolt.exe --plt=all --print-only=.*main.* \
+// RUN: --print-finalized 2>&1 | FileCheck %s
+
+// CHECK-LABEL: Binary Function
+// CHECK: adrp {{.*}}__cxa_throw
+// CHECK-NEXT: ldr {{.*}}__cxa_throw
+// CHECK-NEXT: blr x17 {{.*}} handler: {{.*}} PLTCall:
+
+int main() {
+ try {
+ throw new int;
+ } catch (...) {
+ return 0;
+ }
+ return 1;
+}
diff --git a/bolt/test/AArch64/jump-table-heuristic-fail.s b/bolt/test/AArch64/jump-table-heuristic-fail.s
new file mode 100644
index 0000000000000..724171ac39925
--- /dev/null
+++ b/bolt/test/AArch64/jump-table-heuristic-fail.s
@@ -0,0 +1,29 @@
+## Verify that BOLT does not crash while encountering instruction sequence that
+## does not perfectly match jump table pattern.
+
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags --target=aarch64-unknown-linux %t.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg 2>&1 | FileCheck %s
+
+ .section .text
+ .align 4
+ .globl _start
+ .type _start, %function
+_start:
+ sub w0, w0, #0x4a
+## The address loaded into x22 is undefined. However, the instructions that
+## follow ldr, use the x22 address as a regular jump table.
+ ldr x22, [x29, #0x98]
+ ldrb w0, [x22, w0, uxtw]
+ adr x1, #12
+ add x0, x1, w0, sxtb #2
+ br x0
+# CHECK: br x0 # UNKNOWN
+.L0:
+ ret
+.size _start, .-_start
+
+## Force relocation mode.
+ .reloc 0, R_AARCH64_NONE
diff --git a/bolt/test/AArch64/pad-before-funcs.s b/bolt/test/AArch64/pad-before-funcs.s
index f3e8a23ddfdda..c1b92063d6fa4 100644
--- a/bolt/test/AArch64/pad-before-funcs.s
+++ b/bolt/test/AArch64/pad-before-funcs.s
@@ -15,7 +15,7 @@
# RUN: llvm-bolt %t.exe -o %t.bolt.4.4 --pad-funcs-before=_start:4 --pad-funcs=_start:4
# RUN: llvm-bolt %t.exe -o %t.bolt.4.8 --pad-funcs-before=_start:4 --pad-funcs=_start:8
-# RUN: not llvm-bolt %t.exe -o %t.bolt.8 --pad-funcs-before=_start:1 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGN %s
+# RUN: not llvm-bolt %t.exe -o %t.bolt.1 --pad-funcs-before=_start:1 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGN %s
# CHECK-BAD-ALIGN: user-requested 1 padding bytes before function _start(*2) is not a multiple of the minimum function alignment (4).
diff --git a/bolt/test/AArch64/plt-call.test b/bolt/test/AArch64/plt-call.test
index da307d4a6c01e..1fa62c4a36aaf 100644
--- a/bolt/test/AArch64/plt-call.test
+++ b/bolt/test/AArch64/plt-call.test
@@ -1,6 +1,8 @@
// Verify that PLTCall optimization works.
-RUN: %clang %cflags %p/../Inputs/plt-tailcall.c \
+RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+RUN: %clang %cflags %p/../Inputs/plt-tailcall.c %t.so \
RUN: -o %t -Wl,-q
RUN: llvm-bolt %t -o %t.bolt --plt=all --print-plt --print-only=foo | FileCheck %s
diff --git a/bolt/test/AArch64/remove-nops.s b/bolt/test/AArch64/remove-nops.s
new file mode 100644
index 0000000000000..0f02a4b273dda
--- /dev/null
+++ b/bolt/test/AArch64/remove-nops.s
@@ -0,0 +1,28 @@
+## Verify that llvm-bolt removes nop instructions from functions with indirect
+## branches that have defined control flow.
+
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags --target=aarch64-unknown-linux %t.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt --print-normalized 2>&1 | FileCheck %s
+# RUN: llvm-objdump -d --disassemble-symbols=_start %t.bolt \
+# RUN: | FileCheck %s --check-prefix=CHECK-OBJDUMP
+
+# CHECK-OBJDUMP-LABEL: _start
+# CHECK-OBJDUMP-NOT: nop
+
+ .section .text
+ .align 4
+ .globl _start
+ .type _start, %function
+_start:
+# CHECK-LABEL: Binary Function "_start"
+ nop
+# CHECK-NOT: nop
+ br x0
+# CHECK: br x0 # TAILCALL
+.size _start, .-_start
+
+## Force relocation mode.
+ .reloc 0, R_AARCH64_NONE
diff --git a/bolt/test/AArch64/test-indirect-branch.s b/bolt/test/AArch64/test-indirect-branch.s
index 168e50c8f47f5..1e16e76b11530 100644
--- a/bolt/test/AArch64/test-indirect-branch.s
+++ b/bolt/test/AArch64/test-indirect-branch.s
@@ -3,10 +3,11 @@
// clang-format off
-// REQUIRES: system-linux
+// REQUIRES: system-linux, asserts
+
// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
// RUN: %clang %cflags --target=aarch64-unknown-linux %t.o -o %t.exe -Wl,-q
-// RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg --strict\
+// RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg --strict --debug-only=mcplus \
// RUN: -v=1 2>&1 | FileCheck %s
// Pattern 1: there is no shift amount after the 'add' instruction.
@@ -39,7 +40,7 @@ _start:
// svc #0
// Pattern 1
-// CHECK: BOLT-WARNING: Failed to match indirect branch: ShiftVAL != 2
+// CHECK: BOLT-DEBUG: failed to match indirect branch: ShiftVAL != 2
.globl test1
.type test1, %function
test1:
@@ -57,7 +58,7 @@ test1_2:
ret
// Pattern 2
-// CHECK: BOLT-WARNING: Failed to match indirect branch: nop/adr instead of adrp/add
+// CHECK: BOLT-DEBUG: failed to match indirect branch: nop/adr instead of adrp/add
.globl test2
.type test2, %function
test2:
diff --git a/bolt/test/X86/callcont-fallthru.s b/bolt/test/X86/callcont-fallthru.s
index 31a7910d7fa3f..d76f869c971fd 100644
--- a/bolt/test/X86/callcont-fallthru.s
+++ b/bolt/test/X86/callcont-fallthru.s
@@ -1,7 +1,9 @@
## Ensures that a call continuation fallthrough count is set when using
## pre-aggregated perf data.
-# RUN: %clangxx %cxxflags %s -o %t -Wl,-q -nostdlib
+# RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+## Link against a DSO to ensure PLT entries.
+# RUN: %clangxx %cxxflags %s %t.so -o %t -Wl,-q -nostdlib
# RUN: link_fdata %s %t %t.pa1 PREAGG
# RUN: link_fdata %s %t %t.pa2 PREAGG2
# RUN: link_fdata %s %t %t.pa3 PREAGG3
diff --git a/bolt/test/X86/cfi-instrs-reordered.s b/bolt/test/X86/cfi-instrs-reordered.s
index c325aaf1ad8b1..5173fa6c3c7d0 100644
--- a/bolt/test/X86/cfi-instrs-reordered.s
+++ b/bolt/test/X86/cfi-instrs-reordered.s
@@ -3,7 +3,9 @@
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: llvm-strip --strip-unneeded %t.o
-# RUN: %clangxx %cflags %t.o -o %t.exe
+# RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+## Link against a DSO to ensure PLT entries.
+# RUN: %clangxx %cflags %t.o %t.so -o %t.exe
# RUN: llvm-bolt %t.exe -o %t --reorder-blocks=cache --print-after-lowering \
# RUN: --print-only=_Z10SolveCubicddddPiPd 2>&1 | FileCheck %s
#
diff --git a/bolt/test/X86/dynamic-relocs-on-entry.s b/bolt/test/X86/dynamic-relocs-on-entry.s
index 2a29a43c4939a..4ec8ba4ad4460 100644
--- a/bolt/test/X86/dynamic-relocs-on-entry.s
+++ b/bolt/test/X86/dynamic-relocs-on-entry.s
@@ -4,12 +4,12 @@
# RUN: %clang %cflags -fPIC -pie %s -o %t.exe -nostdlib -Wl,-q
# RUN: llvm-bolt %t.exe -o %t.bolt > %t.out.txt
-# RUN: readelf -r %t.bolt >> %t.out.txt
+# RUN: llvm-readelf -r %t.bolt >> %t.out.txt
# RUN: llvm-objdump --disassemble-symbols=chain %t.bolt >> %t.out.txt
# RUN: FileCheck %s --input-file=%t.out.txt
## Check if the new address in `chain` is correctly updated by BOLT
-# CHECK: Relocation section '.rela.dyn' at offset 0x{{.*}} contains 1 entry:
+# CHECK: Relocation section '.rela.dyn' at offset 0x{{.*}} contains 1 entries:
# CHECK: {{.*}} R_X86_64_RELATIVE [[#%x,ADDR:]]
# CHECK: [[#ADDR]]: c3 retq
.text
@@ -29,4 +29,4 @@ _start:
.data
.Lfoo:
- .quad Label
\ No newline at end of file
+ .quad Label
diff --git a/bolt/test/X86/plt-call.test b/bolt/test/X86/plt-call.test
index e6ae86c179d27..aeee3024ac170 100644
--- a/bolt/test/X86/plt-call.test
+++ b/bolt/test/X86/plt-call.test
@@ -1,6 +1,8 @@
// Verify that PLTCall optimization works.
-RUN: %clang %cflags %p/../Inputs/plt-tailcall.c \
+RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+RUN: %clang %cflags %p/../Inputs/plt-tailcall.c %t.so \
RUN: -o %t -Wl,-q
RUN: llvm-bolt %t -o %t.bolt --plt=all --print-plt --print-only=foo | FileCheck %s
diff --git a/bolt/test/runtime/exceptions-plt.cpp b/bolt/test/runtime/exceptions-plt.cpp
new file mode 100644
index 0000000000000..3d8e7a5133e2c
--- /dev/null
+++ b/bolt/test/runtime/exceptions-plt.cpp
@@ -0,0 +1,18 @@
+// Verify that PLT optimization in BOLT preserves exception-handling info.
+
+// REQUIRES: system-linux
+
+// RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+// RUN: %clangxx %cxxflags -O1 -Wl,-q,-znow %s %t.so -o %t.exe
+// RUN: llvm-bolt %t.exe -o %t.bolt.exe --plt=all
+// RUN: %t.bolt.exe
+
+int main() {
+ try {
+ throw new int;
+ } catch (...) {
+ return 0;
+ }
+ return 1;
+}
diff --git a/bolt/test/runtime/plt-lld.test b/bolt/test/runtime/plt-lld.test
index b505a191f90ab..3432e18bf4daf 100644
--- a/bolt/test/runtime/plt-lld.test
+++ b/bolt/test/runtime/plt-lld.test
@@ -1,14 +1,15 @@
// This test checks that the pointers to PLT are properly updated.
-// The test is using lld linker.
+// The test uses lld and links against a DSO to ensure PLT entries.
+RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
// Non-PIE:
-RUN: %clang %cflags -no-pie %p/../Inputs/plt.c -fuse-ld=lld \
+RUN: %clang %cflags -no-pie %p/../Inputs/plt.c %t.so -fuse-ld=lld \
RUN: -o %t.lld.exe -Wl,-q
RUN: llvm-bolt %t.lld.exe -o %t.lld.bolt.exe --use-old-text=0 --lite=0
RUN: %t.lld.bolt.exe | FileCheck %s
// PIE:
-RUN: %clang %cflags -fPIC -pie %p/../Inputs/plt.c -fuse-ld=lld \
+RUN: %clang %cflags -fPIC -pie %p/../Inputs/plt.c %t.so -fuse-ld=lld \
RUN: -o %t.lld.pie.exe -Wl,-q
RUN: llvm-bolt %t.lld.pie.exe -o %t.lld.bolt.pie.exe --use-old-text=0 --lite=0
RUN: %t.lld.bolt.pie.exe | FileCheck %s
diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
index e3532559a32fc..18a0de826630c 100644
--- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -494,18 +494,31 @@ genReferencesBlock(const std::vector &References,
static std::unique_ptr
writeFileDefinition(const Location &L,
std::optional RepositoryUrl = std::nullopt) {
- if (!L.IsFileInRootDir || !RepositoryUrl)
+ if (!L.IsFileInRootDir && !RepositoryUrl)
return std::make_unique(
HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) +
" of file " + L.Filename);
SmallString<128> FileURL(*RepositoryUrl);
- llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename);
+ llvm::sys::path::append(
+ FileURL, llvm::sys::path::Style::posix,
+ // If we're on Windows, the file name will be in the wrong format, and
+ // append won't convert the full path being appended to the correct
+ // format, so we need to do that here.
+ llvm::sys::path::convert_to_slash(
+ L.Filename,
+ // The style here is the current style of the path, not the one we're
+ // targeting. If the string is already in the posix style, it will do
+ // nothing.
+ llvm::sys::path::Style::windows));
auto Node = std::make_unique(HTMLTag::TAG_P);
Node->Children.emplace_back(std::make_unique("Defined at line "));
auto LocNumberNode =
std::make_unique(HTMLTag::TAG_A, std::to_string(L.LineNumber));
// The links to a specific line in the source code use the github /
// googlesource notation so it won't work for all hosting pages.
+ // FIXME: we probably should have a configuration setting for line number
+ // rendering in the HTML. For example, GitHub uses #L22, while googlesource
+ // uses #22 for line numbers.
LocNumberNode->Attributes.emplace_back(
"href", (FileURL + "#" + std::to_string(L.LineNumber)).str());
Node->Children.emplace_back(std::move(LocNumberNode));
@@ -964,7 +977,7 @@ HTMLGenerator::generateDocs(StringRef RootDir,
for (const auto &Group : FileToInfos) {
std::error_code FileErr;
llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr,
- llvm::sys::fs::OF_None);
+ llvm::sys::fs::OF_Text);
if (FileErr) {
return llvm::createStringError(FileErr, "Error opening file '%s'",
Group.getKey().str().c_str());
@@ -1047,7 +1060,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
llvm::SmallString<128> FilePath;
llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
llvm::sys::path::append(FilePath, "index_json.js");
- llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr != OK) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating index file: " +
@@ -1108,7 +1121,7 @@ static llvm::Error genIndex(const ClangDocContext &CDCtx) {
llvm::SmallString<128> IndexPath;
llvm::sys::path::native(CDCtx.OutDirectory, IndexPath);
llvm::sys::path::append(IndexPath, "index.html");
- llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr != OK) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating main index: " +
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 28b645cf021dd..7bef2c0db04d8 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -300,7 +300,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
llvm::SmallString<128> FilePath;
llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
llvm::sys::path::append(FilePath, "all_files.md");
- llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating index file: " +
@@ -323,7 +323,7 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
llvm::SmallString<128> FilePath;
llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
llvm::sys::path::append(FilePath, "index.md");
- llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating index file: " +
@@ -407,7 +407,7 @@ MDGenerator::generateDocs(StringRef RootDir,
for (const auto &Group : FileToInfos) {
std::error_code FileErr;
llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr,
- llvm::sys::fs::OF_None);
+ llvm::sys::fs::OF_Text);
if (FileErr) {
return llvm::createStringError(FileErr, "Error opening file '%s'",
Group.getKey().str().c_str());
diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
index b612380a3cfa7..ffabd2fd82229 100644
--- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -347,7 +347,7 @@ YAMLGenerator::generateDocs(StringRef RootDir,
}
std::error_code FileErr;
- llvm::raw_fd_ostream InfoOS(Path, FileErr, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream InfoOS(Path, FileErr, llvm::sys::fs::OF_Text);
if (FileErr) {
return llvm::createStringError(FileErr, "Error opening file '%s'",
Path.c_str());
diff --git a/clang-tools-extra/clang-include-fixer/FuzzySymbolIndex.cpp b/clang-tools-extra/clang-include-fixer/FuzzySymbolIndex.cpp
index 91e2a9396a559..98987ad380196 100644
--- a/clang-tools-extra/clang-include-fixer/FuzzySymbolIndex.cpp
+++ b/clang-tools-extra/clang-include-fixer/FuzzySymbolIndex.cpp
@@ -131,7 +131,7 @@ FuzzySymbolIndex::queryRegexp(const std::vector &Tokens) {
llvm::Expected>
FuzzySymbolIndex::createFromYAML(StringRef FilePath) {
- auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
+ auto Buffer = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
if (!Buffer)
return llvm::errorCodeToError(Buffer.getError());
return std::make_unique(
diff --git a/clang-tools-extra/clang-include-fixer/YamlSymbolIndex.cpp b/clang-tools-extra/clang-include-fixer/YamlSymbolIndex.cpp
index 4271d9aa4e677..7f570ee917197 100644
--- a/clang-tools-extra/clang-include-fixer/YamlSymbolIndex.cpp
+++ b/clang-tools-extra/clang-include-fixer/YamlSymbolIndex.cpp
@@ -22,7 +22,7 @@ namespace include_fixer {
llvm::ErrorOr>
YamlSymbolIndex::createFromFile(llvm::StringRef FilePath) {
- auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
+ auto Buffer = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
if (!Buffer)
return Buffer.getError();
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
index 298b02e77cb0a..6bac717bbb013 100644
--- a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -95,7 +95,7 @@ bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
// Parse YAML files in parallel.
Pool.async(
[&AddSymbols](std::string Path) {
- auto Buffer = llvm::MemoryBuffer::getFile(Path);
+ auto Buffer = llvm::MemoryBuffer::getFile(Path, /*IsText=*/true);
if (!Buffer) {
llvm::errs() << "Can't open " << Path << "\n";
return;
@@ -114,7 +114,7 @@ bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
}
}
- llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_Text);
if (EC) {
llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message()
<< '\n';
diff --git a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
index 3a11a22def194..6e51f25a66407 100644
--- a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
+++ b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
@@ -415,7 +415,7 @@ int includeFixerMain(int argc, const char **argv) {
llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n";
return 1;
}
- auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
+ auto Buffer = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
if (!Buffer) {
errs() << "Couldn't open file: " + FilePath.str() + ": "
<< Buffer.getError().message() + "\n";
diff --git a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
index 8ae4351ac2830..d1902b658061b 100644
--- a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
@@ -82,7 +82,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
cxxConstructExpr(
hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
- hasArgument(0, hasType(qualType(isInteger()))),
+ argumentCountIs(2), hasArgument(0, hasType(qualType(isInteger()))),
hasArgument(1, hasType(qualType(isInteger()))),
anyOf(
// Detect the expression: string('x', 40);
@@ -102,7 +102,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
cxxConstructExpr(
hasDeclaration(cxxConstructorDecl(ofClass(
cxxRecordDecl(hasAnyName(removeNamespaces(StringNames)))))),
- hasArgument(0, hasType(CharPtrType)),
+ argumentCountIs(2), hasArgument(0, hasType(CharPtrType)),
hasArgument(1, hasType(isInteger())),
anyOf(
// Detect the expression: string("...", 0);
@@ -114,7 +114,34 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
// Detect the expression: string("lit", 5)
allOf(hasArgument(0, ConstStrLiteral.bind("literal-with-length")),
hasArgument(1, ignoringParenImpCasts(
- integerLiteral().bind("int"))))))
+ integerLiteral().bind("length"))))))
+ .bind("constructor"),
+ this);
+
+ // Check the literal string constructor with char pointer, start position and
+ // length parameters. [i.e. string (const char* s, size_t pos, size_t count);]
+ Finder->addMatcher(
+ cxxConstructExpr(
+ hasDeclaration(cxxConstructorDecl(ofClass(
+ cxxRecordDecl(hasAnyName(removeNamespaces(StringNames)))))),
+ argumentCountIs(3), hasArgument(0, hasType(CharPtrType)),
+ hasArgument(1, hasType(qualType(isInteger()))),
+ hasArgument(2, hasType(qualType(isInteger()))),
+ anyOf(
+ // Detect the expression: string("...", 1, 0);
+ hasArgument(2, ZeroExpr.bind("empty-string")),
+ // Detect the expression: string("...", -4, 1);
+ hasArgument(1, NegativeExpr.bind("negative-pos")),
+ // Detect the expression: string("...", 0, -4);
+ hasArgument(2, NegativeExpr.bind("negative-length")),
+ // Detect the expression: string("lit", 0, 0x1234567);
+ hasArgument(2, LargeLengthExpr.bind("large-length")),
+ // Detect the expression: string("lit", 1, 5)
+ allOf(hasArgument(0, ConstStrLiteral.bind("literal-with-length")),
+ hasArgument(
+ 1, ignoringParenImpCasts(integerLiteral().bind("pos"))),
+ hasArgument(2, ignoringParenImpCasts(
+ integerLiteral().bind("length"))))))
.bind("constructor"),
this);
@@ -155,14 +182,27 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
diag(Loc, "constructor creating an empty string");
} else if (Result.Nodes.getNodeAs("negative-length")) {
diag(Loc, "negative value used as length parameter");
+ } else if (Result.Nodes.getNodeAs("negative-pos")) {
+ diag(Loc, "negative value used as position of the "
+ "first character parameter");
} else if (Result.Nodes.getNodeAs("large-length")) {
if (WarnOnLargeLength)
diag(Loc, "suspicious large length parameter");
} else if (Result.Nodes.getNodeAs("literal-with-length")) {
const auto *Str = Result.Nodes.getNodeAs("str");
- const auto *Lit = Result.Nodes.getNodeAs("int");
- if (Lit->getValue().ugt(Str->getLength())) {
+ const auto *Length = Result.Nodes.getNodeAs("length");
+ if (Length->getValue().ugt(Str->getLength())) {
diag(Loc, "length is bigger than string literal size");
+ return;
+ }
+ if (const auto *Pos = Result.Nodes.getNodeAs("pos")) {
+ if (Pos->getValue().uge(Str->getLength())) {
+ diag(Loc, "position of the first character parameter is bigger than "
+ "string literal character range");
+ } else if (Length->getValue().ugt(
+ (Str->getLength() - Pos->getValue()).getZExtValue())) {
+ diag(Loc, "length is bigger than remaining string literal size");
+ }
}
} else if (const auto *Ptr = Result.Nodes.getNodeAs("from-ptr")) {
Expr::EvalResult ConstPtr;
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
index 604a7cac0e490..a45949314a4ca 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
@@ -256,13 +256,32 @@ void UnsafeFunctionsCheck::registerMatchers(MatchFinder *Finder) {
.bind(CustomFunctionNamesId)))
.bind(DeclRefId),
this);
+ // C++ member calls do not contain a DeclRefExpr to the function decl.
+ // Instead, they contain a MemberExpr that refers to the decl.
+ Finder->addMatcher(memberExpr(member(functionDecl(CustomFunctionsMatcher)
+ .bind(CustomFunctionNamesId)))
+ .bind(DeclRefId),
+ this);
}
}
void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *DeclRef = Result.Nodes.getNodeAs(DeclRefId);
- const auto *FuncDecl = cast(DeclRef->getDecl());
- assert(DeclRef && FuncDecl && "No valid matched node in check()");
+ const Expr *SourceExpr;
+ const FunctionDecl *FuncDecl;
+
+ if (const auto *DeclRef = Result.Nodes.getNodeAs(DeclRefId)) {
+ SourceExpr = DeclRef;
+ FuncDecl = cast(DeclRef->getDecl());
+ } else if (const auto *Member =
+ Result.Nodes.getNodeAs(DeclRefId)) {
+ SourceExpr = Member;
+ FuncDecl = cast(Member->getMemberDecl());
+ } else {
+ llvm_unreachable("No valid matched node in check()");
+ return;
+ }
+
+ assert(SourceExpr && FuncDecl && "No valid matched node in check()");
// Only one of these are matched at a time.
const auto *AnnexK = Result.Nodes.getNodeAs(
@@ -286,14 +305,15 @@ void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
Entry.Reason.empty() ? "is marked as unsafe" : Entry.Reason.c_str();
if (Entry.Replacement.empty()) {
- diag(DeclRef->getExprLoc(), "function %0 %1; it should not be used")
+ diag(SourceExpr->getExprLoc(),
+ "function %0 %1; it should not be used")
<< FuncDecl << Reason << Entry.Replacement
- << DeclRef->getSourceRange();
+ << SourceExpr->getSourceRange();
} else {
- diag(DeclRef->getExprLoc(),
+ diag(SourceExpr->getExprLoc(),
"function %0 %1; '%2' should be used instead")
<< FuncDecl << Reason << Entry.Replacement
- << DeclRef->getSourceRange();
+ << SourceExpr->getSourceRange();
}
return;
@@ -323,9 +343,9 @@ void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
if (!ReplacementFunctionName)
return;
- diag(DeclRef->getExprLoc(), "function %0 %1; '%2' should be used instead")
+ diag(SourceExpr->getExprLoc(), "function %0 %1; '%2' should be used instead")
<< FuncDecl << getRationaleFor(FunctionName)
- << ReplacementFunctionName.value() << DeclRef->getSourceRange();
+ << ReplacementFunctionName.value() << SourceExpr->getSourceRange();
}
void UnsafeFunctionsCheck::registerPPCallbacks(
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h
index 63058c326ef29..9b2ec990be01f 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h
@@ -43,7 +43,7 @@ class UnsafeFunctionsCheck : public ClangTidyCheck {
private:
const std::vector CustomFunctions;
- // If true, the default set of functions are reported.
+ /// If true, the default set of functions are reported.
const bool ReportDefaultFunctions;
/// If true, additional functions from widely used API-s (such as POSIX) are
/// added to the list of reported functions.
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
index fc35bc22c52e0..c249244b1a1b2 100644
--- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
return cast(Left)->getOpcode() ==
cast(Right)->getOpcode();
case Stmt::UnaryExprOrTypeTraitExprClass:
- const auto *LeftUnaryExpr =
- cast(Left);
- const auto *RightUnaryExpr =
- cast(Right);
+ const auto *LeftUnaryExpr = cast(Left);
+ const auto *RightUnaryExpr = cast(Right);
if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType())
return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() &&
LeftUnaryExpr->getArgumentType() ==
@@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr(
Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0);
OperandExpr = OverloadedOperatorExpr;
- Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator());
+ Opcode = BinaryOperator::getOverloadedOpcode(
+ OverloadedOperatorExpr->getOperator());
if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr))
return false;
@@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr(
}
// Checks for expressions like (X == 4) && (Y != 9)
-static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
+static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp,
+ const ASTContext *AstCtx) {
const auto *LhsBinOp = dyn_cast(BinOp->getLHS());
const auto *RhsBinOp = dyn_cast(BinOp->getRHS());
@@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A
return false;
}
+static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant(
+ const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
+ if (areSidesBinaryConstExpressions(BinOp, AstCtx))
+ return true;
+
+ const Expr *Lhs = BinOp->getLHS();
+ const Expr *Rhs = BinOp->getRHS();
+
+ if (!Lhs || !Rhs)
+ return false;
+
+ auto IsDefineExpr = [AstCtx](const Expr *E) {
+ const SourceRange Lsr = E->getSourceRange();
+ if (!Lsr.getBegin().isMacroID() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(*AstCtx))
+ return false;
+ return true;
+ };
+
+ return IsDefineExpr(Lhs) || IsDefineExpr(Rhs);
+}
+
// Retrieves integer constant subexpressions from binary operator expressions
// that have two equivalent sides.
// E.g.: from (X == 5) && (X == 5) retrieves 5 and 5.
@@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp,
}
static bool isSameRawIdentifierToken(const Token &T1, const Token &T2,
- const SourceManager &SM) {
+ const SourceManager &SM) {
if (T1.getKind() != T2.getKind())
return false;
if (T1.isNot(tok::raw_identifier))
@@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr,
const ASTContext *AstCtx) {
if (!LhsExpr || !RhsExpr)
return false;
- SourceRange Lsr = LhsExpr->getSourceRange();
- SourceRange Rsr = RhsExpr->getSourceRange();
+ const SourceRange Lsr = LhsExpr->getSourceRange();
+ const SourceRange Rsr = RhsExpr->getSourceRange();
if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID())
return false;
@@ -847,11 +869,83 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr,
if (!LhsExpr || !RhsExpr)
return false;
- SourceLocation LhsLoc = LhsExpr->getExprLoc();
- SourceLocation RhsLoc = RhsExpr->getExprLoc();
+ const SourceLocation LhsLoc = LhsExpr->getExprLoc();
+ const SourceLocation RhsLoc = RhsExpr->getExprLoc();
return LhsLoc.isMacroID() != RhsLoc.isMacroID();
}
+
+static bool areStringsSameIgnoreSpaces(const llvm::StringRef Left,
+ const llvm::StringRef Right) {
+ if (Left == Right)
+ return true;
+
+ // Do running comparison ignoring spaces
+ llvm::StringRef L = Left.trim();
+ llvm::StringRef R = Right.trim();
+ while (!L.empty() && !R.empty()) {
+ L = L.ltrim();
+ R = R.ltrim();
+ if (L.empty() && R.empty())
+ return true;
+ // If symbol compared are different ==> strings are not the same
+ if (L.front() != R.front())
+ return false;
+ L = L.drop_front();
+ R = R.drop_front();
+ }
+ return L.empty() && R.empty();
+}
+
+static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp,
+ const ASTContext *Context) {
+
+ if (!BinOp)
+ return false;
+
+ const Expr *Lhs = BinOp->getLHS();
+ const Expr *Rhs = BinOp->getRHS();
+ const SourceManager &SM = Context->getSourceManager();
+
+ const SourceRange Lsr = Lhs->getSourceRange();
+ const SourceRange Rsr = Rhs->getSourceRange();
+ if (Lsr.getBegin().isMacroID()) {
+ // Left is macro so right macro too
+ if (Rsr.getBegin().isMacroID()) {
+ // Both sides are macros so they are same macro or literal
+ const llvm::StringRef L = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Lsr), SM, Context->getLangOpts(), 0);
+ const llvm::StringRef R = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Rsr), SM, Context->getLangOpts(), 0);
+ return areStringsSameIgnoreSpaces(L, R);
+ }
+ // Left is macro but right is not so they are not same macro or literal
+ return false;
+ }
+ const auto *Lil = dyn_cast(Lhs);
+ const auto *Ril = dyn_cast(Rhs);
+ if (Lil && Ril)
+ return Lil->getValue() == Ril->getValue();
+
+ const auto *LStrl = dyn_cast(Lhs);
+ const auto *RStrl = dyn_cast(Rhs);
+ if (Lil && Ril) {
+ const llvm::StringRef L = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(LStrl->getBeginLoc()), SM,
+ Context->getLangOpts(), 0);
+ const llvm::StringRef R = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(RStrl->getBeginLoc()), SM,
+ Context->getLangOpts(), 0);
+ return L.compare(R) == 0;
+ }
+
+ const auto *Lbl = dyn_cast(Lhs);
+ const auto *Rbl = dyn_cast(Rhs);
+ if (Lbl && Rbl)
+ return Lbl->getValue() == Rbl->getValue();
+
+ return false;
+}
} // namespace
void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -1089,7 +1183,6 @@ static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0);
}
-
void RedundantExpressionCheck::checkBitwiseExpr(
const MatchFinder::MatchResult &Result) {
if (const auto *ComparisonOperator = Result.Nodes.getNodeAs(
@@ -1134,8 +1227,8 @@ void RedundantExpressionCheck::checkBitwiseExpr(
ConstExpr))
return;
- if((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
- return;
+ if ((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
+ return;
SourceLocation Loc = IneffectiveOperator->getOperatorLoc();
@@ -1276,19 +1369,23 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
return;
}
- if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {
+ if (areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant(
+ BinOp, Result.Context)) {
const Expr *LhsConst = nullptr, *RhsConst = nullptr;
BinaryOperatorKind MainOpcode{}, SideOpcode{};
-
- if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,
- LhsConst, RhsConst, Result.Context))
- return;
-
- if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
- areExprsMacroAndNonMacro(LhsConst, RhsConst))
- return;
+ if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {
+ if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,
+ LhsConst, RhsConst, Result.Context))
+ return;
+
+ if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
+ areExprsMacroAndNonMacro(LhsConst, RhsConst))
+ return;
+ } else {
+ if (!areExprsSameMacroOrLiteral(BinOp, Result.Context))
+ return;
+ }
}
-
diag(BinOp->getOperatorLoc(), "both sides of operator are equivalent");
}
diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp
index a59d1e7ac8409..28bb994a9e99a 100644
--- a/clang-tools-extra/clangd/Diagnostics.cpp
+++ b/clang-tools-extra/clangd/Diagnostics.cpp
@@ -577,7 +577,17 @@ std::vector StoreDiags::take(const clang::tidy::ClangTidyContext *Tidy) {
for (auto &Diag : Output) {
if (const char *ClangDiag = getDiagnosticCode(Diag.ID)) {
// Warnings controlled by -Wfoo are better recognized by that name.
- StringRef Warning = DiagnosticIDs::getWarningOptionForDiag(Diag.ID);
+ StringRef Warning = [&] {
+ if (OrigSrcMgr) {
+ return OrigSrcMgr->getDiagnostics()
+ .getDiagnosticIDs()
+ ->getWarningOptionForDiag(Diag.ID);
+ }
+ if (!DiagnosticIDs::IsCustomDiag(Diag.ID))
+ return DiagnosticIDs{}.getWarningOptionForDiag(Diag.ID);
+ return StringRef{};
+ }();
+
if (!Warning.empty()) {
Diag.Name = ("-W" + Warning).str();
} else {
@@ -894,20 +904,23 @@ void StoreDiags::flushLastDiag() {
Output.push_back(std::move(*LastDiag));
}
-bool isBuiltinDiagnosticSuppressed(unsigned ID,
- const llvm::StringSet<> &Suppress,
- const LangOptions &LangOpts) {
+bool isDiagnosticSuppressed(const clang::Diagnostic &Diag,
+ const llvm::StringSet<> &Suppress,
+ const LangOptions &LangOpts) {
// Don't complain about header-only stuff in mainfiles if it's a header.
// FIXME: would be cleaner to suppress in clang, once we decide whether the
// behavior should be to silently-ignore or respect the pragma.
- if (ID == diag::pp_pragma_sysheader_in_main_file && LangOpts.IsHeaderFile)
+ if (Diag.getID() == diag::pp_pragma_sysheader_in_main_file &&
+ LangOpts.IsHeaderFile)
return true;
- if (const char *CodePtr = getDiagnosticCode(ID)) {
+ if (const char *CodePtr = getDiagnosticCode(Diag.getID())) {
if (Suppress.contains(normalizeSuppressedCode(CodePtr)))
return true;
}
- StringRef Warning = DiagnosticIDs::getWarningOptionForDiag(ID);
+ StringRef Warning =
+ Diag.getDiags()->getDiagnosticIDs()->getWarningOptionForDiag(
+ Diag.getID());
if (!Warning.empty() && Suppress.contains(Warning))
return true;
return false;
diff --git a/clang-tools-extra/clangd/Diagnostics.h b/clang-tools-extra/clangd/Diagnostics.h
index d4c0478c63a5c..c45d8dc3aa6ce 100644
--- a/clang-tools-extra/clangd/Diagnostics.h
+++ b/clang-tools-extra/clangd/Diagnostics.h
@@ -181,11 +181,11 @@ class StoreDiags : public DiagnosticConsumer {
};
/// Determine whether a (non-clang-tidy) diagnostic is suppressed by config.
-bool isBuiltinDiagnosticSuppressed(unsigned ID,
- const llvm::StringSet<> &Suppressed,
- const LangOptions &);
+bool isDiagnosticSuppressed(const clang::Diagnostic &Diag,
+ const llvm::StringSet<> &Suppressed,
+ const LangOptions &);
/// Take a user-specified diagnostic code, and convert it to a normalized form
-/// stored in the config and consumed by isBuiltinDiagnosticsSuppressed.
+/// stored in the config and consumed by isDiagnosticsSuppressed.
///
/// (This strips err_ and -W prefix so we can match with or without them.)
llvm::StringRef normalizeSuppressedCode(llvm::StringRef);
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp
index 89d6f26d0f150..3f63daaf400db 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -342,7 +342,7 @@ void applyWarningOptions(llvm::ArrayRef ExtraArgs,
if (Enable) {
if (Diags.getDiagnosticLevel(ID, SourceLocation()) <
DiagnosticsEngine::Warning) {
- auto Group = DiagnosticIDs::getGroupForDiag(ID);
+ auto Group = Diags.getDiagnosticIDs()->getGroupForDiag(ID);
if (!Group || !EnabledGroups(*Group))
continue;
Diags.setSeverity(ID, diag::Severity::Warning, SourceLocation());
@@ -585,8 +585,8 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) {
if (Cfg.Diagnostics.SuppressAll ||
- isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress,
- Clang->getLangOpts()))
+ isDiagnosticSuppressed(Info, Cfg.Diagnostics.Suppress,
+ Clang->getLangOpts()))
return DiagnosticsEngine::Ignored;
auto It = OverriddenSeverity.find(Info.getID());
diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index ce88ec0eb88c1..b247e608eece3 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -622,8 +622,8 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
PreambleDiagnostics.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) {
if (Cfg.Diagnostics.SuppressAll ||
- isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress,
- CI.getLangOpts()))
+ isDiagnosticSuppressed(Info, Cfg.Diagnostics.Suppress,
+ CI.getLangOpts()))
return DiagnosticsEngine::Ignored;
switch (Info.getID()) {
case diag::warn_no_newline_eof:
diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
index 179960a02cade..c3e484a1a79c4 100644
--- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
@@ -298,20 +298,41 @@ TEST_F(ConfigCompileTests, DiagnosticSuppression) {
"unreachable-code", "unused-variable",
"typecheck_bool_condition",
"unexpected_friend", "warn_alloca"));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
- diag::warn_unreachable, Conf.Diagnostics.Suppress, LangOptions()));
+ clang::DiagnosticsEngine DiagEngine(new DiagnosticIDs, nullptr,
+ new clang::IgnoringDiagConsumer);
+
+ using Diag = clang::Diagnostic;
+ {
+ auto D = DiagEngine.Report(diag::warn_unreachable);
+ EXPECT_TRUE(isDiagnosticSuppressed(
+ Diag{&DiagEngine, D}, Conf.Diagnostics.Suppress, LangOptions()));
+ }
// Subcategory not respected/suppressed.
- EXPECT_FALSE(isBuiltinDiagnosticSuppressed(
- diag::warn_unreachable_break, Conf.Diagnostics.Suppress, LangOptions()));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
- diag::warn_unused_variable, Conf.Diagnostics.Suppress, LangOptions()));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::err_typecheck_bool_condition,
- Conf.Diagnostics.Suppress,
- LangOptions()));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
- diag::err_unexpected_friend, Conf.Diagnostics.Suppress, LangOptions()));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
- diag::warn_alloca, Conf.Diagnostics.Suppress, LangOptions()));
+ {
+ auto D = DiagEngine.Report(diag::warn_unreachable_break);
+ EXPECT_FALSE(isDiagnosticSuppressed(
+ Diag{&DiagEngine, D}, Conf.Diagnostics.Suppress, LangOptions()));
+ }
+ {
+ auto D = DiagEngine.Report(diag::warn_unused_variable);
+ EXPECT_TRUE(isDiagnosticSuppressed(
+ Diag{&DiagEngine, D}, Conf.Diagnostics.Suppress, LangOptions()));
+ }
+ {
+ auto D = DiagEngine.Report(diag::err_typecheck_bool_condition);
+ EXPECT_TRUE(isDiagnosticSuppressed(
+ Diag{&DiagEngine, D}, Conf.Diagnostics.Suppress, LangOptions()));
+ }
+ {
+ auto D = DiagEngine.Report(diag::err_unexpected_friend);
+ EXPECT_TRUE(isDiagnosticSuppressed(
+ Diag{&DiagEngine, D}, Conf.Diagnostics.Suppress, LangOptions()));
+ }
+ {
+ auto D = DiagEngine.Report(diag::warn_alloca);
+ EXPECT_TRUE(isDiagnosticSuppressed(
+ Diag{&DiagEngine, D}, Conf.Diagnostics.Suppress, LangOptions()));
+ }
Frag.Diagnostics.Suppress.emplace_back("*");
EXPECT_TRUE(compileAndApply());
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index cc5f64a3f9fa3..6b8fe22242417 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -43,21 +43,12 @@ infrastructure are described first, followed by tool-specific sections.
Major New Features
------------------
-- The ``clang-pseudo`` tool is incomplete and does not have active maintainers,
- so it has been removed. See
- `the RFC `_ for
- more details.
-
-...
-
Improvements to clangd
----------------------
Inlay hints
^^^^^^^^^^^
-- Added `DefaultArguments` Inlay Hints option.
-
Diagnostics
^^^^^^^^^^^
@@ -73,16 +64,9 @@ Hover
Code completion
^^^^^^^^^^^^^^^
-- Added completion for C++20 keywords.
-
Code actions
^^^^^^^^^^^^
-- Added `Swap operands` tweak for certain binary operators.
-
-- Improved the extract-to-function code action to allow extracting statements
- with overloaded operators like ``<<`` of ``std::ostream``.
-
Signature help
^^^^^^^^^^^^^^
@@ -95,312 +79,36 @@ Objective-C
Miscellaneous
^^^^^^^^^^^^^
-- The DefineOutline tweak now handles member functions of class templates.
-
Improvements to clang-doc
-------------------------
Improvements to clang-query
---------------------------
-- Added `set enable-profile true/false` command for basic matcher profiling.
-
Improvements to clang-tidy
--------------------------
-- Improved :program:`clang-tidy-diff.py` script. Add the `-only-check-in-db`
- option to exclude files not present in the compilation database, avoiding
- false-negative results.
-
-- Improved :program:`run-clang-tidy.py` script. Fixed minor shutdown noise
- happening on certain platforms when interrupting the script.
-
-- Improved :program:`clang-tidy`:
-
- - add support for `--verify-config` flag to check the configuration options of
- the `Clang Static Analyzer Checks `_.
- - accept parameters file in command line.
- - fix incorrect configuration file path resolving when file paths contain ``..``.
- - remove global options for most of checks. All options are changed to local
- options except `IncludeStyle`, `StrictMode` and `IgnoreMacros`. Global scoped
- `StrictMode` and `IgnoreMacros` are deprecated and will be removed in further
- releases.
-
-.. csv-table::
- :header: "Check", "Options removed from global option"
-
- :doc:`bugprone-reserved-identifier `, AggressiveDependentMemberLookup
- :doc:`bugprone-unchecked-optional-access `, IgnoreSmartPointerDereference
- :doc:`cppcoreguidelines-pro-type-member-init `, UseAssignment
- :doc:`cppcoreguidelines-rvalue-reference-param-not-moved `, AllowPartialMove; IgnoreUnnamedParams; IgnoreNonDeducedTemplateTypes
- :doc:`misc-include-cleaner `, IgnoreHeaders; DeduplicateFindings
- :doc:`performance-inefficient-vector-operation `, EnableProto
- :doc:`readability-identifier-naming `, AggressiveDependentMemberLookup
- :doc:`readability-inconsistent-declaration-parameter-name `, Strict
- :doc:`readability-redundant-access-specifiers `, CheckFirstDeclaration
- :doc:`readability-redundant-casting `, IgnoreTypeAliases
-
New checks
^^^^^^^^^^
-- New :doc:`bugprone-bitwise-pointer-cast
- ` check.
-
- Warns about code that tries to cast between pointers by means of
- ``std::bit_cast`` or ``memcpy``.
-
-- New :doc:`bugprone-incorrect-enable-shared-from-this
- ` check.
-
- Detect classes or structs that do not publicly inherit from
- ``std::enable_shared_from_this``, because unintended behavior will
- otherwise occur when calling ``shared_from_this``.
-
-- New :doc:`bugprone-nondeterministic-pointer-iteration-order
- `
- check.
-
- Finds nondeterministic usages of pointers in unordered containers.
-
-- New :doc:`bugprone-tagged-union-member-count
- ` check.
-
- Gives warnings for tagged unions, where the number of tags is
- different from the number of data members inside the union.
-
-- New :doc:`modernize-use-integer-sign-comparison
- ` check.
-
- Replace comparisons between signed and unsigned integers with their safe
- C++20 ``std::cmp_*`` alternative, if available.
-
-- New :doc:`portability-template-virtual-member-function
- ` check.
-
- Finds cases when an uninstantiated virtual member function in a template class
- causes cross-compiler incompatibility.
-
New check aliases
^^^^^^^^^^^^^^^^^
-- New alias :doc:`cert-arr39-c ` to
- :doc:`bugprone-sizeof-expression
- ` was added.
-
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Improved :doc:`altera-id-dependent-backward-branch
- ` check by fixing
- crashes from invalid code.
-
-- Improved :doc:`bugprone-branch-clone
- ` check to improve detection of
- branch clones by now detecting duplicate inner and outer if statements.
-
-- Improved :doc:`bugprone-casting-through-void
- ` check to suggest replacing
- the offending code with ``reinterpret_cast``, to more clearly express intent.
-
-- Improved :doc:`bugprone-dangling-handle
- ` check to treat ``std::span`` as a
- handle class.
-
-- Improved :doc:`bugprone-exception-escape
- ` by fixing false positives
- when a consteval function with throw statements.
-
-- Improved :doc:`bugprone-forwarding-reference-overload
- ` check by fixing
- a crash when determining if an ``enable_if[_t]`` was found.
-
-- Improve :doc:`bugprone-narrowing-conversions
- ` to avoid incorrect check
- results when floating point type is not ``float``, ``double`` and
- ``long double``.
-
-- Improved :doc:`bugprone-optional-value-conversion
- ` to support detecting
- conversion directly by ``std::make_unique`` and ``std::make_shared``.
-
-- Improved :doc:`bugprone-posix-return
- ` check to support integer literals
- as LHS and posix call as RHS of comparison.
-
-- Improved :doc:`bugprone-return-const-ref-from-parameter
- ` check to
- diagnose potential dangling references when returning a ``const &`` parameter
- by using the conditional operator ``cond ? var1 : var2`` and fixing false
- positives for functions which contain lambda and ignore parameters
- with ``[[clang::lifetimebound]]`` attribute.
-
-- Improved :doc:`bugprone-sizeof-expression
- ` check to find suspicious
- usages of ``sizeof()``, ``alignof()``, and ``offsetof()`` when adding or
- subtracting from a pointer directly or when used to scale a numeric value and
- fix false positive when sizeof expression with template types.
-
-- Improved :doc:`bugprone-throw-keyword-missing
- ` by fixing a false positive
- when using non-static member initializers and a constructor.
-
-- Improved :doc:`bugprone-unchecked-optional-access
- ` to support
- ``bsl::optional`` and ``bdlb::NullableValue`` from
- _.
-
-- Improved :doc:`bugprone-unhandled-self-assignment
- ` check by fixing smart
- pointer check against std::unique_ptr type.
+- Improved :doc:`bugprone-string-constructor
+ ` check to find suspicious
+ calls of ``std::string`` constructor with char pointer, start position and
+ length parameters.
- Improved :doc:`bugprone-unsafe-functions
` check to allow specifying
- additional functions to match.
-
-- Improved :doc:`bugprone-unused-local-non-trivial-variable
- ` check to avoid
- false positives when using name-independent variables after C++26.
-
-- Improved :doc:`bugprone-use-after-move
- ` to avoid triggering on
- ``reset()`` calls on moved-from ``std::optional`` and ``std::any`` objects,
- similarly to smart pointers.
-
-- Improved :doc:`cert-flp30-c ` check to
- fix false positive that floating point variable is only used in increment
- expression.
-
-- Improved :doc:`cppcoreguidelines-avoid-const-or-ref-data-members
- ` check to
- avoid false positives when detecting a templated class with inheritance.
-
-- Improved :doc:`cppcoreguidelines-init-variables
- ` check by fixing the
- insertion location for function pointers.
-
-- Improved :doc:`cppcoreguidelines-prefer-member-initializer
- ` check to
- avoid false positive when member initialization depends on a structured
- binding variable.
-
-- Fixed :doc:`cppcoreguidelines-pro-type-union-access
- ` check to
- report a location even when the member location is not valid.
-
-- Improved :doc:`misc-definitions-in-headers
- ` check by rewording the
- diagnostic note that suggests adding ``inline``.
+ additional C++ member functions to match.
- Improved :doc:`misc-redundant-expression
- ` check by extending the
- checker to detect floating point and integer literals in redundant
- expressions.
-
-- Improved :doc:`misc-unconventional-assign-operator
- ` check to avoid
- false positive for C++23 deducing this.
-
-- Improved :doc:`misc-use-internal-linkage
- ` check to insert ``static``
- keyword before type qualifiers such as ``const`` and ``volatile``. Also, fix
- false positives for function declaration without body, C++20 consteval
- functions, C++20 export declarations, and global scoped
- overloaded ``operator new`` and ``operator delete``.
-
-- Improved :doc:`modernize-avoid-c-arrays
- ` check to suggest using
- ``std::span`` as a replacement for parameters of incomplete C array type in
- C++20 and ``std::array`` or ``std::vector`` before C++20.
-
-- Improved :doc:`modernize-loop-convert
- ` check to fix false positive when
- using loop variable in initializer of lambda capture.
-
-- Improved :doc:`modernize-min-max-use-initializer-list
- ` check by fixing
- a false positive when only an implicit conversion happened inside an
- initializer list.
-
-- Improved :doc:`modernize-raw-string-literal
- ` check to fix incorrect
- fix-it when the string contains a user-defined suffix.
-
-- Improved :doc:`modernize-use-designated-initializers
- ` check to fix a
- crash when a class is declared but not defined.
-
-- Improved :doc:`modernize-use-integer-sign-comparison
- ` check to
- add an option ``EnableQtSupport``, that makes C++17 ``q20::cmp_*`` alternative
- available for Qt-based applications.
-
-- Improved :doc:`modernize-use-nullptr
- ` check to also recognize
- ``NULL``/``__null`` (but not ``0``) when used with a templated type.
-
-- Improved :doc:`modernize-use-starts-ends-with
- ` check to handle two new
- cases from ``rfind`` and ``compare`` to ``ends_with``, and one new case from
- ``substr`` to ``starts_with``, and a small adjustment to the diagnostic message.
-
-- Improved :doc:`modernize-use-std-format
- ` check to support replacing
- member function calls too and to only expand macros starting with ``PRI``
- and ``__PRI`` from ```` in the format string.
-
-- Improved :doc:`modernize-use-std-print
- ` check to support replacing
- member function calls too and to only expand macros starting with ``PRI``
- and ``__PRI`` from ```` in the format string.
-
-- Improved :doc:`modernize-use-using
- ` check by not expanding macros.
-
-- Improved :doc:`performance-avoid-endl
- ` check to use ``std::endl`` as
- placeholder when lexer cannot get source text.
-
-- Improved :doc:`performance-move-const-arg
- ` check to fix a crash when
- an argument type is declared but not defined.
-
-- Improved :doc:`performance-unnecessary-copy-initialization
- ` check
- to consider static member functions the same way as free functions.
-
-- Improved :doc:`readability-container-contains
- ` check to let it work on
- any class that has a ``contains`` method. Fix some false negatives in the
- ``find()`` case.
-
-- Improved :doc:`readability-enum-initial-value
- ` check by only issuing
- diagnostics for the definition of an ``enum``, by not emitting a redundant
- file path for anonymous enums in the diagnostic, and by fixing a typo in the
- diagnostic.
-
-- Improved :doc:`readability-identifier-naming
- ` check to
- validate ``namespace`` aliases.
-
-- Improved :doc:`readability-implicit-bool-conversion
- ` check
- by adding the option `UseUpperCaseLiteralSuffix` to select the
- case of the literal suffix in fixes and fixing false positive for implicit
- conversion of comparison result in C23.
-
-- Improved :doc:`readability-redundant-casting
- ` check
- by addressing a false positive in aggregate initialization through
- parenthesized list.
-
-- Improved :doc:`readability-redundant-smartptr-get
- ` check to
- remove ``->``, when redundant ``get()`` is removed.
-
-- Improved :doc:`readability-use-std-min-max
- ` check to use correct template
- type in ``std::min`` and ``std::max`` when operand is integer literal.
+ ` check by providing additional
+ examples and fixing some macro related false positives.
Removed checks
^^^^^^^^^^^^^^
@@ -408,13 +116,6 @@ Removed checks
Miscellaneous
^^^^^^^^^^^^^
-- The :doc:`bugprone-narrowing-conversions `
- check is no longer an alias of :doc:`cppcoreguidelines-narrowing-conversions
- `. Instead,
- :doc:`cppcoreguidelines-narrowing-conversions
- ` is now an alias
- of :doc:`bugprone-narrowing-conversions `.
-
Improvements to include-fixer
-----------------------------
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst
index 8ba84ff61c6a9..1355afae92e4f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assert-side-effect.rst
@@ -26,8 +26,8 @@ Options
A semicolon-separated list of the names of functions or methods to be
considered as not having side-effects. Regular expressions are accepted,
- e.g. `[Rr]ef(erence)?$` matches every type with suffix `Ref`, `ref`,
- `Reference` and `reference`. The default is empty. If a name in the list
- contains the sequence `::` it is matched against the qualified typename
- (i.e. `namespace::Type`, otherwise it is matched against only
- the type name (i.e. `Type`).
+ e.g. ``[Rr]ef(erence)?$`` matches every type with suffix ``Ref``, ``ref``,
+ ``Reference`` and ``reference``. The default is empty. If a name in the list
+ contains the sequence `::` it is matched against the qualified type name
+ (i.e. ``namespace::Type``), otherwise it is matched against only
+ the type name (i.e. ``Type``).
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
index b45c2ef4a9312..a0bd1d7c5bc15 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
@@ -21,6 +21,7 @@ Examples:
.. code-block:: c++
std::string("test", 200); // Will include random characters after "test".
+ std::string("test", 2, 5); // Will include random characters after "st".
std::string_view("test", 200);
Creating an empty string from constructors with parameters is considered
@@ -31,8 +32,19 @@ Examples:
.. code-block:: c++
std::string("test", 0); // Creation of an empty string.
+ std::string("test", 1, 0);
std::string_view("test", 0);
+Passing an invalid first character position parameter to constructor will
+cause ``std::out_of_range`` exception at runtime.
+
+Examples:
+
+.. code-block:: c++
+
+ std::string("test", -1, 10); // Negative first character position.
+ std::string("test", 10, 10); // First character position is bigger than string literal character range".
+
Options
-------
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
index fb070627e31b1..317db9c5564e2 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
@@ -114,6 +114,17 @@ qualified name (i.e. ``std::original``), otherwise the regex is matched against
If the regular expression starts with `::` (or `^::`), it is matched against the
fully qualified name (``::std::original``).
+.. note::
+
+ Fully qualified names can contain template parameters on certain C++ classes, but not on C++ functions.
+ Type aliases are resolved before matching.
+
+ As an example, the member function ``open`` in the class ``std::ifstream``
+ has a fully qualified name of ``::std::basic_ifstream::open``.
+
+ The example could also be matched with the regex ``::std::basic_ifstream<[^>]*>::open``, which matches all potential
+ template parameters, but does not match nested template classes.
+
Options
-------
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/redundant-expression.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/redundant-expression.rst
index 44f0772d0bedf..cea998d39bd73 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc/redundant-expression.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc/redundant-expression.rst
@@ -19,12 +19,14 @@ Examples:
.. code-block:: c++
- ((x+1) | (x+1)) // (x+1) is redundant
- (p->x == p->x) // always true
- (p->x < p->x) // always false
- (speed - speed + 1 == 12) // speed - speed is always zero
- int b = a | 4 | a // identical expr on both sides
- ((x=1) | (x=1)) // expression is identical
+ ((x+1) | (x+1)) // (x+1) is redundant
+ (p->x == p->x) // always true
+ (p->x < p->x) // always false
+ (speed - speed + 1 == 12) // speed - speed is always zero
+ int b = a | 4 | a // identical expr on both sides
+ ((x=1) | (x=1)) // expression is identical
+ (DEFINE_1 | DEFINE_1) // same macro on the both sides
+ ((DEF_1 + DEF_2) | (DEF_1+DEF_2)) // expressions differ in spaces only
Floats are handled except in the case that NaNs are checked like so:
diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/for-range-copy.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/for-range-copy.rst
index 01fde9580e2a0..d740984029482 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/performance/for-range-copy.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/for-range-copy.rst
@@ -23,14 +23,15 @@ Options
.. option:: WarnOnAllAutoCopies
- When `true`, warns on any use of `auto` as the type of the range-based for
+ When `true`, warns on any use of ``auto`` as the type of the range-based for
loop variable. Default is `false`.
.. option:: AllowedTypes
A semicolon-separated list of names of types allowed to be copied in each
- iteration. Regular expressions are accepted, e.g. `[Rr]ef(erence)?$` matches
- every type with suffix `Ref`, `ref`, `Reference` and `reference`. The default
- is empty. If a name in the list contains the sequence `::` it is matched
- against the qualified typename (i.e. `namespace::Type`, otherwise it is
- matched against only the type name (i.e. `Type`).
+ iteration. Regular expressions are accepted, e.g. ``[Rr]ef(erence)?$``
+ matches every type with suffix ``Ref``, ``ref``, ``Reference`` and
+ ``reference``. The default is empty. If a name in the list contains the
+ sequence `::`, it is matched against the qualified type name
+ (i.e. ``namespace::Type``), otherwise it is matched against only the
+ type name (i.e. ``Type``).
diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst
index 837283811ddcc..bb4f42c88d62f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst
@@ -42,11 +42,11 @@ Options
.. option:: AllowedTypes
A semicolon-separated list of names of types allowed to be initialized by
- copying. Regular expressions are accepted, e.g. `[Rr]ef(erence)?$` matches
- every type with suffix `Ref`, `ref`, `Reference` and `reference`. The default
- is empty. If a name in the list contains the sequence `::` it is matched
- against the qualified typename (i.e. `namespace::Type`, otherwise it is
- matched against only the type name (i.e. `Type`).
+ copying. Regular expressions are accepted, e.g. ``[Rr]ef(erence)?$`` matches
+ every type with suffix ``Ref``, ``ref``, ``Reference`` and ``reference``.
+ The default is empty. If a name in the list contains the sequence `::`, it
+ is matched against the qualified type name (i.e. ``namespace::Type``),
+ otherwise it is matched against only the type name (i.e. ``Type``).
.. option:: ExcludedContainerTypes
diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst
index cc5e1ae73508c..d13c53eea994e 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-value-param.rst
@@ -65,8 +65,8 @@ Options
.. option:: AllowedTypes
A semicolon-separated list of names of types allowed to be passed by value.
- Regular expressions are accepted, e.g. `[Rr]ef(erence)?$` matches every type
- with suffix `Ref`, `ref`, `Reference` and `reference`. The default is
- empty. If a name in the list contains the sequence `::` it is matched against
- the qualified typename (i.e. `namespace::Type`, otherwise it is matched
- against only the type name (i.e. `Type`).
+ Regular expressions are accepted, e.g. ``[Rr]ef(erence)?$`` matches every
+ type with suffix ``Ref``, ``ref``, ``Reference`` and ``reference``. The
+ default is empty. If a name in the list contains the sequence `::`, it is
+ matched against the qualified type name (i.e. ``namespace::Type``),
+ otherwise it is matched against only the type name (i.e. ``Type``).
diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index aae3eda519ffd..7a140c991925c 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/STLExtras.h"
@@ -32,6 +33,11 @@
namespace clang::include_cleaner {
namespace {
+bool isOperatorNewDelete(OverloadedOperatorKind OpKind) {
+ return OpKind == OO_New || OpKind == OO_Delete || OpKind == OO_Array_New ||
+ OpKind == OO_Array_Delete;
+}
+
using DeclCallback =
llvm::function_ref;
@@ -158,7 +164,15 @@ class ASTWalker : public RecursiveASTVisitor {
// the container decl instead, which is preferred as it'll handle
// aliases/exports properly.
if (!FD->isCXXClassMember() && !llvm::isa(FD)) {
- report(DRE->getLocation(), FD);
+ // Global operator new/delete [] is available implicitly in every
+ // translation unit, even without including any explicit headers. So treat
+ // those as ambigious to not force inclusion in TUs that transitively
+ // depend on those.
+ RefType RT =
+ isOperatorNewDelete(FD->getDeclName().getCXXOverloadedOperator())
+ ? RefType::Ambiguous
+ : RefType::Explicit;
+ report(DRE->getLocation(), FD, RT);
return true;
}
// If the ref is without a qualifier, and is a member, ignore it. As it is
diff --git a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
index d2d137a0dfb42..74321c312cb71 100644
--- a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -397,6 +397,55 @@ TEST_F(AnalyzeTest, SpellingIncludesWithSymlinks) {
}
}
+// Make sure that the references to implicit operator new/delete are reported as
+// ambigious.
+TEST_F(AnalyzeTest, ImplicitOperatorNewDeleteNotMissing) {
+ ExtraFS = llvm::makeIntrusiveRefCnt();
+ ExtraFS->addFile("header.h",
+ /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBufferCopy(guard(R"cpp(
+ void* operator new(decltype(sizeof(int)));
+ )cpp")));
+ ExtraFS->addFile("wrapper.h",
+ /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBufferCopy(guard(R"cpp(
+ #include "header.h"
+ )cpp")));
+
+ Inputs.Code = R"cpp(
+ #include "wrapper.h"
+ void bar() {
+ operator new(3);
+ })cpp";
+ TestAST AST(Inputs);
+ std::vector DeclsInTU;
+ for (auto *D : AST.context().getTranslationUnitDecl()->decls())
+ DeclsInTU.push_back(D);
+ auto Results = analyze(DeclsInTU, {}, PP.Includes, &PI, AST.preprocessor());
+ EXPECT_THAT(Results.Missing, testing::IsEmpty());
+}
+
+TEST_F(AnalyzeTest, ImplicitOperatorNewDeleteNotUnused) {
+ ExtraFS = llvm::makeIntrusiveRefCnt();
+ ExtraFS->addFile("header.h",
+ /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBufferCopy(guard(R"cpp(
+ void* operator new(decltype(sizeof(int)));
+ )cpp")));
+
+ Inputs.Code = R"cpp(
+ #include "header.h"
+ void bar() {
+ operator new(3);
+ })cpp";
+ TestAST AST(Inputs);
+ std::vector DeclsInTU;
+ for (auto *D : AST.context().getTranslationUnitDecl()->decls())
+ DeclsInTU.push_back(D);
+ auto Results = analyze(DeclsInTU, {}, PP.Includes, &PI, AST.preprocessor());
+ EXPECT_THAT(Results.Unused, testing::IsEmpty());
+}
+
TEST(FixIncludes, Basic) {
llvm::StringRef Code = R"cpp(#include "d.h"
#include "a.h"
diff --git a/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Circle.cpp b/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Circle.cpp
index 823384a4d97e8..3ddb2fd9ff563 100644
--- a/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Circle.cpp
+++ b/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Circle.cpp
@@ -8,4 +8,5 @@ double Circle::area() const {
double Circle::perimeter() const {
return 3.141 * radius_;
-}
\ No newline at end of file
+}
+
diff --git a/clang-tools-extra/test/clang-doc/basic-project.test b/clang-tools-extra/test/clang-doc/basic-project.test
index 7c46c52bae687..1f5ba8bdc0703 100644
--- a/clang-tools-extra/test/clang-doc/basic-project.test
+++ b/clang-tools-extra/test/clang-doc/basic-project.test
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t/docs %t/build
// RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json
-// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json
+// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json --repository=https://repository.com
// RUN: FileCheck %s -input-file=%t/docs/index_json.js -check-prefix=JSON-INDEX
// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE
// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefix=HTML-CALC
@@ -54,130 +54,183 @@
// JSON-INDEX-NEXT: };
// JSON-INDEX-NEXT: }
-// HTML-SHAPE: class Shape
-// HTML-SHAPE: Defined at line 8 of file {{.*}}Shape.h
-// HTML-SHAPE: brief
-// HTML-SHAPE: Abstract base class for shapes.
-// HTML-SHAPE: Provides a common interface for different types of shapes.
-// HTML-SHAPE: Functions
-// HTML-SHAPE: area
-// HTML-SHAPE: public double area()
-// HTML-SHAPE: brief
-// HTML-SHAPE: Calculates the area of the shape.
-// HTML-SHAPE: perimeter
-// HTML-SHAPE: public double perimeter()
-// HTML-SHAPE: brief
-// HTML-SHAPE: Calculates the perimeter of the shape.
-// HTML-SHAPE: return
-// HTML-SHAPE: double The perimeter of the shape.
-// HTML-SHAPE: ~Shape
-// HTML-SHAPE: public void ~Shape()
-// HTML-SHAPE: Defined at line 13 of file {{.*}}Shape.h
-// HTML-SHAPE: brief
-// HTML-SHAPE: Virtual destructor.
+// HTML-SHAPE: class Shape
+// HTML-SHAPE-NEXT:
+// HTML-SHAPE-NEXT: Defined at line
+// HTML-SHAPE-NEXT: 8
+// HTML-SHAPE-NEXT: of file
+// HTML-SHAPE-NEXT: Shape.h
+// HTML-SHAPE-NEXT:
+// HTML-SHAPE: brief
+// HTML-SHAPE: Abstract base class for shapes.
+// HTML-SHAPE: Provides a common interface for different types of shapes.
+// HTML-SHAPE: Functions
+// HTML-SHAPE: area
+// HTML-SHAPE: public double area()
+// HTML-SHAPE: brief
+// HTML-SHAPE: Calculates the area of the shape.
+// HTML-SHAPE: perimeter
+// HTML-SHAPE: public double perimeter()
+// HTML-SHAPE: brief
+// HTML-SHAPE: Calculates the perimeter of the shape.
+// HTML-SHAPE: return
+// HTML-SHAPE: double The perimeter of the shape.
+// HTML-SHAPE: ~Shape
+// HTML-SHAPE: public void ~Shape()
+// HTML-SHAPE: Defined at line
+// HTML-SHAPE-NEXT: 13
+// HTML-SHAPE-NEXT: of file
+// HTML-SHAPE-NEXT: Shape.h
+// HTML-SHAPE: brief
+// HTML-SHAPE: Virtual destructor.
-// HTML-CALC: class Calculator
-// HTML-CALC: Defined at line 8 of file {{.*}}Calculator.h
-// HTML-CALC: brief
-// HTML-CALC: A simple calculator class.
-// HTML-CALC: Provides basic arithmetic operations.
-// HTML-CALC: Functions
-// HTML-CALC: add
-// HTML-CALC: public int add(int a, int b)
-// HTML-CALC: Defined at line 3 of file {{.*}}Calculator.cpp
-// HTML-CALC: brief
-// HTML-CALC: Adds two integers.
-// HTML-CALC: return
-// HTML-CALC: int The sum of a and b.
-// HTML-CALC: subtract
-// HTML-CALC: public int subtract(int a, int b)
-// HTML-CALC: Defined at line 7 of file {{.*}}Calculator.cpp
-// HTML-CALC: brief
-// HTML-CALC: Subtracts the second integer from the first.
-// HTML-CALC: return
-// HTML-CALC: int The result of a - b.
-// HTML-CALC: multiply
-// HTML-CALC: public int multiply(int a, int b)
-// HTML-CALC: Defined at line 11 of file {{.*}}Calculator.cpp
-// HTML-CALC: brief
-// HTML-CALC: Multiplies two integers.
-// HTML-CALC: return
-// HTML-CALC: int The product of a and b.
-// HTML-CALC: divide
-// HTML-CALC: public double divide(int a, int b)
-// HTML-CALC: Defined at line 15 of file {{.*}}Calculator.cpp
-// HTML-CALC: brief
-// HTML-CALC: Divides the first integer by the second.
-// HTML-CALC: return
-// HTML-CALC: double The result of a / b.
-// HTML-CALC: throw
-// HTML-CALC: if b is zero.
+// HTML-CALC: class Calculator
+// HTML-CALC-NEXT:
+// HTML-CALC-NEXT: Defined at line
+// HTML-CALC-NEXT: 8
+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: Calculator.h
+// HTML-CALC-NEXT:
+// HTML-CALC: brief
+// HTML-CALC: A simple calculator class.
+// HTML-CALC: Provides basic arithmetic operations.
+// HTML-CALC: Functions
+// HTML-CALC: add
+// HTML-CALC: public int add(int a, int b)
+// HTML-CALC: Defined at line
+// HTML-CALC-NEXT: 3
+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: Calculator.cpp
+// HTML-CALC: brief
+// HTML-CALC: Adds two integers.
+// HTML-CALC: return
+// HTML-CALC: int The sum of a and b.
+// HTML-CALC: subtract
+// HTML-CALC: public int subtract(int a, int b)
+// HTML-CALC: Defined at line
+// HTML-CALC-NEXT: 7
+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: Calculator.cpp
+// HTML-CALC: brief
+// HTML-CALC: Subtracts the second integer from the first.
+// HTML-CALC: return
+// HTML-CALC: int The result of a - b.
+// HTML-CALC: multiply
+// HTML-CALC: public int multiply(int a, int b)
+// HTML-CALC: Defined at line
+// HTML-CALC-NEXT: 11
+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: Calculator.cpp
+// HTML-CALC: brief
+// HTML-CALC: Multiplies two integers.
+// HTML-CALC: return
+// HTML-CALC: int The product of a and b.
+// HTML-CALC: divide
+// HTML-CALC: public double divide(int a, int b)
+// HTML-CALC: Defined at line
+// HTML-CALC-NEXT: 15
+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: Calculator.cpp
+// HTML-CALC: brief
+// HTML-CALC: Divides the first integer by the second.
+// HTML-CALC: return
+// HTML-CALC: double The result of a / b.
+// HTML-CALC: throw
+// HTML-CALC: if b is zero.
-// HTML-RECTANGLE: class Rectangle
-// HTML-RECTANGLE: Defined at line 10 of file {{.*}}Rectangle.h
-// HTML-RECTANGLE: Represents a rectangle with a given width and height.
-// HTML-RECTANGLE: Inherits from
-// HTML-RECTANGLE: Shape
-// HTML-RECTANGLE:
-// HTML-RECTANGLE: Members
-// HTML-RECTANGLE: Width of the rectangle.
-// HTML-RECTANGLE: private double width_
-// HTML-RECTANGLE: Height of the rectangle.
-// HTML-RECTANGLE: private double height_
-// HTML-RECTANGLE: Functions
-// HTML-RECTANGLE: Rectangle
-// HTML-RECTANGLE: public void Rectangle(double width, double height)
-// HTML-RECTANGLE: Defined at line 3 of file {{.*}}Rectangle.cpp
-// HTML-RECTANGLE: brief
-// HTML-RECTANGLE: Constructs a new Rectangle object.
-// HTML-RECTANGLE: area
-// HTML-RECTANGLE: public double area()
-// HTML-RECTANGLE: Defined at line 6 of file {{.*}}Rectangle.cpp
-// HTML-RECTANGLE: brief
-// HTML-RECTANGLE: Calculates the area of the rectangle.
-// HTML-RECTANGLE: return
-// HTML-RECTANGLE: double The area of the rectangle.
-// HTML-RECTANGLE: perimeter
-// HTML-RECTANGLE: public double perimeter()
-// HTML-RECTANGLE: Defined at line 10 of file {{.*}}Rectangle.cpp
-// HTML-RECTANGLE: brief
-// HTML-RECTANGLE: Calculates the perimeter of the rectangle.
-// HTML-RECTANGLE: return
-// HTML-RECTANGLE: double The perimeter of the rectangle.
+// HTML-RECTANGLE: class Rectangle
+// HTML-RECTANGLE-NEXT:
+// HTML-RECTANGLE-NEXT: Defined at line
+// HTML-RECTANGLE-NEXT: 10
+// HTML-RECTANGLE-NEXT: of file
+// HTML-RECTANGLE-NEXT: Rectangle.h
+// HTML-RECTANGLE-NEXT:
+// HTML-RECTANGLE: Represents a rectangle with a given width and height.
+// HTML-RECTANGLE:
+// HTML-RECTANGLE: Inherits from
+// HTML-RECTANGLE: Shape
+// HTML-RECTANGLE:
+// HTML-RECTANGLE: Members
+// HTML-RECTANGLE: Width of the rectangle.
+// HTML-RECTANGLE: private double width_
+// HTML-RECTANGLE: Height of the rectangle.
+// HTML-RECTANGLE: private double height_
+// HTML-RECTANGLE: Functions
+// HTML-RECTANGLE: Rectangle
+// HTML-RECTANGLE: public void Rectangle(double width, double height)
+// HTML-RECTANGLE: Defined at line
+// HTML-RECTANGLE-NEXT: 3
+// HTML-RECTANGLE-NEXT: of file
+// HTML-RECTANGLE-NEXT: Rectangle.cpp
+// HTML-RECTANGLE: brief
+// HTML-RECTANGLE: Constructs a new Rectangle object.
+// HTML-RECTANGLE: area
+// HTML-RECTANGLE: public double area()
+// HTML-RECTANGLE: Defined at line
+// HTML-RECTANGLE-NEXT: 6
+// HTML-RECTANGLE-NEXT: of file
+// HTML-RECTANGLE-NEXT: Rectangle.cpp
+// HTML-RECTANGLE: brief
+// HTML-RECTANGLE: Calculates the area of the rectangle.
+// HTML-RECTANGLE: return
+// HTML-RECTANGLE: double The area of the rectangle.
+// HTML-RECTANGLE: perimeter
+// HTML-RECTANGLE: public double perimeter()
+// HTML-RECTANGLE: Defined at line
+// HTML-RECTANGLE-NEXT: 10
+// HTML-RECTANGLE-NEXT: of file
+// HTML-RECTANGLE-NEXT: Rectangle.cpp
+// HTML-RECTANGLE: brief
+// HTML-RECTANGLE: Calculates the perimeter of the rectangle.
+// HTML-RECTANGLE: return
+// HTML-RECTANGLE: double The perimeter of the rectangle.
-// HTML-CIRCLE: class Circle
-// HTML-CIRCLE: Defined at line 10 of file {{.*}}Circle.h
-// HTML-CIRCLE: brief
-// HTML-CIRCLE: Circle class derived from Shape.
-// HTML-CIRCLE: Represents a circle with a given radius.
-// HTML-CIRCLE:
-// HTML-CIRCLE: Inherits from
-// HTML-CIRCLE: Shape
-// HTML-CIRCLE:
-// HTML-CIRCLE: Members
-// HTML-CIRCLE: Radius of the circle.
-// HTML-CIRCLE: private double radius_
-// HTML-CIRCLE: Functions
-// HTML-CIRCLE: Circle
-// HTML-CIRCLE: public void Circle(double radius)
-// HTML-CIRCLE: Defined at line 3 of file {{.*}}Circle.cpp
-// HTML-CIRCLE: brief
-// HTML-CIRCLE: Constructs a new Circle object.
-// HTML-CIRCLE: area
-// HTML-CIRCLE: public double area()
-// HTML-CIRCLE: Defined at line 5 of file {{.*}}Circle.cpp
-// HTML-CIRCLE: brief
-// HTML-CIRCLE: Calculates the area of the circle.
-// HTML-CIRCLE: return
-// HTML-CIRCLE: double The area of the circle.
-// HTML-CIRCLE: perimeter
-// HTML-CIRCLE: public double perimeter()
-// HTML-CIRCLE: Defined at line 9 of file {{.*}}Circle.cpp
-// HTML-CIRCLE: brief
-// HTML-CIRCLE: Calculates the perimeter of the circle.
-// HTML-CIRCLE: return
-// HTML-CIRCLE: double The perimeter of the circle.
+// HTML-CIRCLE: class Circle
+// HTML-CIRCLE-NEXT:
+// HTML-CIRCLE-NEXT: Defined at line
+// HTML-CIRCLE-NEXT: 10
+// HTML-CIRCLE-NEXT: of file
+// HTML-CIRCLE-NEXT: Circle.h
+// HTML-CIRCLE-NEXT:
+// HTML-CIRCLE: brief
+// HTML-CIRCLE: Circle class derived from Shape.
+// HTML-CIRCLE: Represents a circle with a given radius.
+// HTML-CIRCLE:
+// HTML-CIRCLE: Inherits from
+// HTML-CIRCLE: Shape
+// HTML-CIRCLE:
+// HTML-CIRCLE: Members
+// HTML-CIRCLE: Radius of the circle.
+// HTML-CIRCLE: private double radius_
+// HTML-CIRCLE: Functions
+// HTML-CIRCLE: Circle
+// HTML-CIRCLE: public void Circle(double radius)
+// HTML-CIRCLE: Defined at line
+// HTML-CIRCLE-NEXT: 3
+// HTML-CIRCLE-NEXT: of file
+// HTML-CIRCLE-NEXT: Circle.cpp
+// HTML-CIRCLE: brief
+// HTML-CIRCLE: Constructs a new Circle object.
+// HTML-CIRCLE: area
+// HTML-CIRCLE: public double area()
+// HTML-CIRCLE: Defined at line
+// HTML-CIRCLE-NEXT: 5
+// HTML-CIRCLE-NEXT: of file
+// HTML-CIRCLE-NEXT: Circle.cpp
+// HTML-CIRCLE: brief
+// HTML-CIRCLE: Calculates the area of the circle.
+// HTML-CIRCLE: return
+// HTML-CIRCLE: double The area of the circle.
+// HTML-CIRCLE: perimeter
+// HTML-CIRCLE: public double perimeter()
+// HTML-CIRCLE: Defined at line
+// HTML-CIRCLE-NEXT: 9
+// HTML-CIRCLE-NEXT: of file
+// HTML-CIRCLE-NEXT: Circle.cpp
+// HTML-CIRCLE: brief
+// HTML-CIRCLE: Calculates the perimeter of the circle.
+// HTML-CIRCLE: return
+// HTML-CIRCLE: double The perimeter of the circle.
// MD-CALC: # class Calculator
// MD-CALC: *Defined at .{{[\/]}}include{{[\/]}}Calculator.h#8*
@@ -286,4 +339,4 @@
// MD-ALL-FILES: ## [GlobalNamespace](GlobalNamespace{{[\/]}}index.md)
// MD-INDEX: # C/C++ Reference
-// MD-INDEX: * Namespace: [GlobalNamespace](GlobalNamespace)
\ No newline at end of file
+// MD-INDEX: * Namespace: [GlobalNamespace](GlobalNamespace)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
index a5b6b240ddc66..2576d19916250 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
@@ -11,6 +11,7 @@ struct basic_string {
basic_string(const C*, unsigned int size);
basic_string(const C *, const A &allocator = A());
basic_string(unsigned int size, C c);
+ basic_string(const C*, unsigned int pos, unsigned int size);
};
typedef basic_string string;
typedef basic_string wstring;
@@ -61,6 +62,21 @@ void Test() {
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructing string from nullptr is undefined behaviour
std::string q7 = 0;
// CHECK-MESSAGES: [[@LINE-1]]:20: warning: constructing string from nullptr is undefined behaviour
+
+ std::string r1("test", 1, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+ std::string r2("test", 0, -4);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as length parameter
+ std::string r3("test", -4, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as position of the first character parameter
+ std::string r4("test", 0, 0x1000000);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+ std::string r5("test", 0, 5);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than string literal size
+ std::string r6("test", 3, 2);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than remaining string literal size
+ std::string r7("test", 4, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: position of the first character parameter is bigger than string literal character range
}
void TestView() {
@@ -82,6 +98,17 @@ void TestView() {
// CHECK-MESSAGES: [[@LINE-1]]:25: warning: constructing string from nullptr is undefined behaviour
}
+void TestUnsignedArguments() {
+ std::string s0("test", 0u);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+ std::string s1(0x1000000ull, 'x');
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+ std::string s2("test", 3ull, 2u);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than remaining string literal size
+ std::string s3("test", 0u, 5ll);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than string literal size
+}
+
std::string StringFromZero() {
return 0;
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: constructing string from nullptr is undefined behaviour
@@ -101,6 +128,9 @@ void Valid() {
std::string s3("test");
std::string s4("test\000", 5);
std::string s6("te" "st", 4);
+ std::string s7("test", 0, 4);
+ std::string s8("test", 3, 1);
+ std::string s9("te" "st", 1, 2);
std::string_view emptyv();
std::string_view sv1("test", 4);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp
index fc97d1bc93bc5..ad0ba8739be2b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp
@@ -1,11 +1,19 @@
// RUN: %check_clang_tidy -check-suffix=NON-STRICT-REGEX %s bugprone-unsafe-functions %t --\
-// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '::name_match,replacement,is a qualname match;^::prefix_match,,is matched on qualname prefix'}}"
+// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '::name_match,replacement,is a qualname match;^::prefix_match,,is matched on qualname prefix;^::S::member_match_,,is matched on a C++ class member'}}"
// RUN: %check_clang_tidy -check-suffix=STRICT-REGEX %s bugprone-unsafe-functions %t --\
-// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '^name_match$,replacement,is matched on function name only;^::prefix_match$,,is a full qualname match'}}"
+// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '^name_match$,replacement,is matched on function name only;^::prefix_match$,,is a full qualname match;^::S::member_match_1$,,is matched on a C++ class member'}}"
void name_match();
void prefix_match();
+struct S {
+ static void member_match_1() {}
+ void member_match_2() {}
+};
+
+void member_match_1() {}
+void member_match_unmatched() {}
+
namespace regex_test {
void name_match();
void prefix_match();
@@ -42,3 +50,25 @@ void f1() {
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match_regex' is matched on qualname prefix; it should not be used
// no-warning STRICT-REGEX
}
+
+void f2() {
+ S s;
+
+ S::member_match_1();
+ // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
+ // CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
+
+ s.member_match_1();
+ // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:5: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
+ // CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:5: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
+
+ s.member_match_2();
+ // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:5: warning: function 'member_match_2' is matched on a C++ class member; it should not be used
+ // no-warning STRICT-REGEX
+
+ member_match_1();
+ // no-warning
+
+ member_match_unmatched();
+ // no-warning
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
index 7396d2dce76c4..95d8ecb15a4f1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
@@ -1,4 +1,5 @@
// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26
+// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26 -DTEST_MACRO
typedef __INT64_TYPE__ I64;
@@ -91,6 +92,223 @@ int TestSimpleEquivalent(int X, int Y) {
return 0;
}
+#ifndef TEST_MACRO
+#define VAL_1 2
+#define VAL_3 3
+#else
+#define VAL_1 3
+#define VAL_3 2
+#endif
+
+#define VAL_2 2
+
+#ifndef TEST_MACRO
+#define VAL_4 2 + 1
+#define VAL_6 3 + 1
+#else
+#define VAL_4 3 + 1
+#define VAL_6 2 + 1
+#endif
+
+#define VAL_5 2 + 1
+
+struct TestStruct
+{
+ int mA;
+ int mB;
+ int mC[10];
+};
+
+int TestDefineEquivalent() {
+
+ int int_val1 = 3;
+ int int_val2 = 4;
+ int int_val = 0;
+ const int cint_val2 = 4;
+
+ // Cases which should not be reported
+ if (VAL_1 != VAL_2) return 0;
+ if (VAL_3 != VAL_2) return 0;
+ if (VAL_1 == VAL_2) return 0;
+ if (VAL_3 == VAL_2) return 0;
+ if (VAL_1 >= VAL_2) return 0;
+ if (VAL_3 >= VAL_2) return 0;
+ if (VAL_1 <= VAL_2) return 0;
+ if (VAL_3 <= VAL_2) return 0;
+ if (VAL_1 < VAL_2) return 0;
+ if (VAL_3 < VAL_2) return 0;
+ if (VAL_1 > VAL_2) return 0;
+ if (VAL_3 > VAL_2) return 0;
+
+ if (VAL_4 != VAL_5) return 0;
+ if (VAL_6 != VAL_5) return 0;
+ if (VAL_6 == VAL_5) return 0;
+ if (VAL_4 >= VAL_5) return 0;
+ if (VAL_6 >= VAL_5) return 0;
+ if (VAL_4 <= VAL_5) return 0;
+ if (VAL_6 <= VAL_5) return 0;
+ if (VAL_4 > VAL_5) return 0;
+ if (VAL_6 > VAL_5) return 0;
+ if (VAL_4 < VAL_5) return 0;
+ if (VAL_6 < VAL_5) return 0;
+
+ if (VAL_1 != 2) return 0;
+ if (VAL_3 == 3) return 0;
+
+ if (VAL_1 >= VAL_1) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_2 <= VAL_2) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_3 > VAL_3) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_4 < VAL_4) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_6 == VAL_6) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_5 != VAL_5) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+
+ // Test prefixes
+ if (+VAL_6 == +VAL_6) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+ if (-VAL_6 == -VAL_6) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+ if ((+VAL_6) == (+VAL_6)) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: both sides of operator are equivalent
+ if ((-VAL_6) == (-VAL_6)) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: both sides of operator are equivalent
+
+ if (1 >= 1) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (0xFF <= 0xFF) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: both sides of operator are equivalent
+ if (042 > 042) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: both sides of operator are equivalent
+
+ int_val = (VAL_6 == VAL_6)?int_val1: int_val2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent
+ int_val = (042 > 042)?int_val1: int_val2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
+
+
+ // Ternary operator cases which should not be reported
+ int_val = (VAL_4 == VAL_5)? int_val1: int_val2;
+ int_val = (VAL_3 != VAL_2)? int_val1: int_val2;
+ int_val = (VAL_6 != 10)? int_val1: int_val2;
+ int_val = (VAL_6 != 3)? int_val1: int_val2;
+ int_val = (VAL_6 != 4)? int_val1: int_val2;
+ int_val = (VAL_6 == 3)? int_val1: int_val2;
+ int_val = (VAL_6 == 4)? int_val1: int_val2;
+
+ TestStruct tsVar1 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... VAL_2 - 2] = int_val + 1,
+ };
+
+ TestStruct tsVar2 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... cint_val2 - 2] = int_val + 1,
+ };
+
+ TestStruct tsVar3 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... VAL_3 - VAL_3] = int_val + 1,
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: both sides of operator are equivalent
+ };
+
+ TestStruct tsVar4 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... 5 - 5] = int_val + 1,
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: both sides of operator are equivalent
+ };
+
+ return 1 + int_val + sizeof(tsVar1) + sizeof(tsVar2) +
+ sizeof(tsVar3) + sizeof(tsVar4);
+}
+
+#define LOOP_DEFINE 1
+
+unsigned int testLoops(const unsigned int arr1[LOOP_DEFINE])
+{
+ unsigned int localIndex;
+ for (localIndex = LOOP_DEFINE - 1; localIndex > 0; localIndex--)
+ {
+ }
+ for (localIndex = LOOP_DEFINE - 1; 10 > 10; localIndex--)
+ // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: both sides of operator are equivalent
+ {
+ }
+
+ for (localIndex = LOOP_DEFINE - 1; LOOP_DEFINE > LOOP_DEFINE; localIndex--)
+ // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: both sides of operator are equivalent
+ {
+ }
+
+ return localIndex;
+}
+
+#define getValue(a) a
+#define getValueM(a) a
+
+int TestParamDefine() {
+ int ret = 0;
+
+ // Negative cases
+ ret += getValue(VAL_6) == getValue(2);
+ ret += getValue(VAL_6) == getValue(3);
+ ret += getValue(VAL_5) == getValue(2);
+ ret += getValue(VAL_5) == getValue(3);
+ ret += getValue(1) > getValue( 2);
+ ret += getValue(VAL_1) == getValue(VAL_2);
+ ret += getValue(VAL_1) != getValue(VAL_2);
+ ret += getValue(VAL_1) == getValueM(VAL_1);
+ ret += getValue(VAL_1 + VAL_2) == getValueM(VAL_1 + VAL_2);
+ ret += getValue(1) == getValueM(1);
+ ret += getValue(false) == getValueM(false);
+ ret += -getValue(1) > +getValue( 1);
+
+ // Positive cases
+ ret += (+getValue(1)) > (+getValue( 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent
+ ret += (-getValue(1)) > (-getValue( 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent
+
+ ret += +getValue(1) > +getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
+ ret += -getValue(1) > -getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
+
+ ret += getValue(1) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent
+ ret += getValue(1) > getValue( 1 );
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent
+ ret += getValue(1) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent
+ ret += getValue( 1) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: both sides of operator are equivalent
+ ret += getValue( 1 ) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: both sides of operator are equivalent
+ ret += getValue( VAL_5 ) > getValue(VAL_5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue( VAL_5 ) > getValue( VAL_5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue( VAL_5 ) > getValue( VAL_5 ) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue(VAL_5) > getValue( VAL_5 ) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
+ ret += getValue(VAL_1+VAL_2) > getValue(VAL_1 + VAL_2) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue(VAL_1)+getValue(VAL_2) > getValue(VAL_1) + getValue( VAL_2) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: both sides of operator are equivalent
+ ret += (getValue(VAL_1)+getValue(VAL_2)) > (getValue(VAL_1) + getValue( VAL_2) ) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: both sides of operator are equivalent
+ return ret;
+}
+
template
int TestSimpleEquivalentDependent() {
if (DX > 0 && DX > 0) return 1;
diff --git a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
index dfd31e6578714..97afa12cab6d3 100644
--- a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
@@ -319,7 +319,12 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) {
int
P)
- Defined at line 10 of file dir/test.cpp
+
+ Defined at line
+ 10
+ of file
+ test.cpp
+
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index b79e570667b2c..c3f30e2a8e9c0 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -331,6 +331,7 @@ if(NOT DEFINED CLANG_VERSION_SUFFIX)
set(CLANG_VERSION_SUFFIX ${LLVM_VERSION_SUFFIX})
endif()
set(CLANG_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCHLEVEL}${CLANG_VERSION_SUFFIX}")
+set(MAX_CLANG_ABI_COMPAT_VERSION "${LLVM_VERSION_MAJOR}")
message(STATUS "Clang version: ${CLANG_VERSION}")
# Configure the Version.inc file.
@@ -431,18 +432,16 @@ if(NOT LLVM_STATIC_LINK_CXX_STDLIB)
set(HAVE_CLANG_REPL_SUPPORT ON)
endif()
-option(CLANG_ENABLE_ARCMT "Build ARCMT." ON)
+option(CLANG_ENABLE_OBJC_REWRITER "Build the Objective-C rewriter tool" OFF)
+
option(CLANG_ENABLE_STATIC_ANALYZER
"Include static analyzer in clang binary." ON)
option(CLANG_ENABLE_PROTO_FUZZER "Build Clang protobuf fuzzer." OFF)
-if(NOT CLANG_ENABLE_STATIC_ANALYZER AND CLANG_ENABLE_ARCMT)
- message(FATAL_ERROR "Cannot disable static analyzer while enabling ARCMT or Z3")
-endif()
-
-if(CLANG_ENABLE_ARCMT)
- set(CLANG_ENABLE_OBJC_REWRITER ON)
+if (DEFINED CLANG_ENABLE_ARCMT)
+ set(CLANG_ENABLE_OBJC_REWRITER ${CLANG_ENABLE_ARCMT})
+ message(DEPRECATION "'CLANG_ENABLE_ARCMT' is deprecated as ARCMigrate has been removed from Clang. Please use 'CLANG_ENABLE_OBJC_REWRITER' instead to enable or disable the Objective-C rewriter.")
endif()
# This option is a stop-gap, we should commit to removing this as
@@ -872,58 +871,6 @@ if (CLANG_ENABLE_BOOTSTRAP)
endforeach()
endif()
-set(CLANG_BOLT OFF CACHE STRING "Apply BOLT optimization to Clang. \
- May be specified as Instrument or Perf or LBR to use a particular profiling \
- mechanism.")
-string(TOUPPER "${CLANG_BOLT}" CLANG_BOLT)
-
-if (CLANG_BOLT AND NOT LLVM_BUILD_INSTRUMENTED)
- set(CLANG_PATH ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
- set(CLANG_INSTRUMENTED ${LLVM_RUNTIME_OUTPUT_INTDIR}/${CLANG_BOLT_INSTRUMENTED})
- set(BOLT_FDATA ${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/prof.fdata)
-
- # Pass extra flag in no-LBR mode
- if (CLANG_BOLT STREQUAL "PERF")
- set(BOLT_NO_LBR "-nl")
- endif()
-
- if (CLANG_BOLT STREQUAL "INSTRUMENT")
- # Instrument clang with BOLT
- add_custom_target(clang-instrumented
- DEPENDS ${CLANG_INSTRUMENTED}
- )
- add_custom_command(OUTPUT ${CLANG_INSTRUMENTED}
- DEPENDS clang llvm-bolt
- COMMAND llvm-bolt ${CLANG_PATH} -o ${CLANG_INSTRUMENTED}
- -instrument --instrumentation-file-append-pid
- --instrumentation-file=${BOLT_FDATA}
- COMMENT "Instrumenting clang binary with BOLT"
- USES_TERMINAL
- VERBATIM
- )
- add_custom_target(clang-bolt-training-deps DEPENDS clang-instrumented)
- else() # perf or LBR
- add_custom_target(clang-bolt-training-deps DEPENDS clang)
- endif()
-
- # Optimize original (pre-bolt) Clang using the collected profile
- add_custom_target(clang-bolt
- DEPENDS clang-bolt-profile
- COMMAND ${CMAKE_COMMAND} -E rename $ ${CLANG_PATH}-prebolt
- COMMAND ${CMAKE_COMMAND} -E create_symlink ${CLANG_PATH}-prebolt ${CLANG_PATH}++-prebolt
- COMMAND llvm-bolt ${CLANG_PATH}-prebolt
- -o $
- -data ${BOLT_FDATA}
- -reorder-blocks=ext-tsp -reorder-functions=cdsort -split-functions
- -split-all-cold -split-eh -dyno-stats -use-gnu-stack
- -update-debug-sections
- ${BOLT_NO_LBR}
- COMMENT "Optimizing Clang with BOLT"
- USES_TERMINAL
- VERBATIM
- )
-endif()
-
if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION)
add_subdirectory(utils/ClangVisualizers)
endif()
diff --git a/clang/cmake/caches/Android.cmake b/clang/cmake/caches/Android.cmake
index d5ca6b50d4ada..c89e31f67cc9b 100644
--- a/clang/cmake/caches/Android.cmake
+++ b/clang/cmake/caches/Android.cmake
@@ -2,7 +2,6 @@
set(LLVM_TARGETS_TO_BUILD X86 CACHE STRING "")
-set(CLANG_ENABLE_ARCMT OFF CACHE BOOL "")
set(CLANG_ENABLE_STATIC_ANALYZER OFF CACHE BOOL "")
set(CLANG_TIDY_ENABLE_STATIC_ANALYZER OFF CACHE BOOL "")
set(CLANG_VENDOR Android CACHE STRING "")
diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake
index 1cbf691f29d58..99890b8246ad7 100644
--- a/clang/cmake/caches/Fuchsia-stage2.cmake
+++ b/clang/cmake/caches/Fuchsia-stage2.cmake
@@ -44,7 +44,6 @@ set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "")
set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
set(CLANG_DEFAULT_UNWINDLIB libunwind CACHE STRING "")
-set(CLANG_ENABLE_ARCMT OFF CACHE BOOL "")
set(CLANG_ENABLE_STATIC_ANALYZER ON CACHE BOOL "")
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
@@ -190,6 +189,10 @@ foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unkn
set(RUNTIMES_${target}_LLVM_TOOLS_DIR "${CMAKE_BINARY_DIR}/bin" CACHE BOOL "")
set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
+ # Enable FatLTO for Linux and baremetal runtimes
+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
+
# Use .build-id link.
list(APPEND RUNTIME_BUILD_ID_LINK "${target}")
endif()
@@ -272,6 +275,10 @@ if(FUCHSIA_SDK)
set(RUNTIMES_${target}+asan+noexcept_LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
set(RUNTIMES_${target}+asan+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
+ # Enable FatLTO for Fuchsia runtimes
+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
+
# Use .build-id link.
list(APPEND RUNTIME_BUILD_ID_LINK "${target}")
endforeach()
@@ -369,6 +376,10 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv7em-none-eabi;armv8m.main-n
set(RUNTIMES_${target}_LLVM_INCLUDE_TESTS OFF CACHE BOOL "")
set(RUNTIMES_${target}_LLVM_ENABLE_ASSERTIONS OFF CACHE BOOL "")
set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc;libcxx" CACHE STRING "")
+
+ # Enable FatLTO for baremetal runtimes
+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
endforeach()
foreach(target riscv32-unknown-elf)
@@ -420,6 +431,10 @@ foreach(target riscv32-unknown-elf)
set(RUNTIMES_${target}_LLVM_INCLUDE_TESTS OFF CACHE BOOL "")
set(RUNTIMES_${target}_LLVM_ENABLE_ASSERTIONS OFF CACHE BOOL "")
set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc;libcxx" CACHE STRING "")
+
+ # Enable FatLTO for baremetal runtimes
+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
endforeach()
set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "")
diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake
index 07637cd0ed08f..83336589da305 100644
--- a/clang/cmake/caches/Fuchsia.cmake
+++ b/clang/cmake/caches/Fuchsia.cmake
@@ -84,7 +84,6 @@ set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
set(CLANG_DEFAULT_OBJCOPY llvm-objcopy CACHE STRING "")
set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "")
set(CLANG_DEFAULT_UNWINDLIB libunwind CACHE STRING "")
-set(CLANG_ENABLE_ARCMT OFF CACHE BOOL "")
set(CLANG_ENABLE_STATIC_ANALYZER OFF CACHE BOOL "")
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
diff --git a/clang/docs/BoundsSafety.rst b/clang/docs/BoundsSafety.rst
index e24c69d8c7855..cf5b0c75c0387 100644
--- a/clang/docs/BoundsSafety.rst
+++ b/clang/docs/BoundsSafety.rst
@@ -777,13 +777,13 @@ the transformed pseudo code of function ``alloc_buf()`` in the example below.
size_t count;
} sized_buf_t;
- void alloc_buf(sized_buf_t *sbuf, sized_t nelems) {
+ void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
sbuf->buf = (int *)malloc(sizeof(int) * nelems);
sbuf->count = nelems;
}
// Transformed pseudo code:
- void alloc_buf(sized_buf_t *sbuf, sized_t nelems) {
+ void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
// Materialize RHS values:
int *tmp_ptr = (int *)malloc(sizeof(int) * nelems);
int tmp_count = nelems;
@@ -959,7 +959,8 @@ that has the define.
#if defined(__has_feature) && __has_feature(bounds_safety)
#define __counted_by(T) __attribute__((__counted_by__(T)))
// ... other bounds annotations
- #else #define __counted_by(T) // defined as nothing
+ #else
+ #define __counted_by(T) // defined as nothing
// ... other bounds annotations
#endif
@@ -987,7 +988,7 @@ and it does not guarantee other types of memory safety properties. Consequently,
it may not prevent some of the secondary bounds safety violations caused by
other types of safety violations such as type confusion. For instance,
``-fbounds-safety`` does not perform type-safety checks on conversions between
-`__single`` pointers of different pointee types (e.g., ``char *__single`` →
+``__single`` pointers of different pointee types (e.g., ``char *__single`` →
``void *__single`` → ``int *__single``) beyond what the foundation languages
(C/C++) already offer.
@@ -1003,4 +1004,4 @@ Try it out
Your feedback on the programming model is valuable. You may want to follow the
instruction in :doc:`BoundsSafetyAdoptionGuide` to play with ``-fbounds-safety``
-and please send your feedback to `Yeoul Na `_.
\ No newline at end of file
+and please send your feedback to `Yeoul Na `_.
diff --git a/clang/docs/BoundsSafetyImplPlans.rst b/clang/docs/BoundsSafetyImplPlans.rst
index 93c2ed7b43402..34276c920f31e 100644
--- a/clang/docs/BoundsSafetyImplPlans.rst
+++ b/clang/docs/BoundsSafetyImplPlans.rst
@@ -134,7 +134,7 @@ same basic block and without side effect in between.
int *__counted_by(count) buf; size_t count;
} sized_buf_t;
- void alloc_buf(sized_buf_t *sbuf, sized_t nelems) {
+ void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
sbuf->buf = (int *)malloc(sizeof(int) * nelems);
sbuf->count = nelems;
}
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 30a2325949f48..bf6dd9e13915f 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -2182,6 +2182,24 @@ the configuration (without a prefix: ``Auto``).
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
}
+.. _BinPackLongBracedList:
+
+**BinPackLongBracedList** (``Boolean``) :versionbadge:`clang-format 21` :ref:`¶ `
+ If ``BinPackLongBracedList`` is ``true`` it overrides
+ ``BinPackArguments`` if there are 20 or more items in a braced
+ initializer list.
+
+ .. code-block:: c++
+
+ BinPackLongBracedList: false vs. BinPackLongBracedList: true
+ vector x{ vector x{1, 2, ...,
+ 20, 21};
+ 1,
+ 2,
+ ...,
+ 20,
+ 21};
+
.. _BinPackParameters:
**BinPackParameters** (``BinPackParametersStyle``) :versionbadge:`clang-format 3.7` :ref:`¶ `
@@ -3421,6 +3439,35 @@ the configuration (without a prefix: ``Auto``).
+.. _BreakBeforeTemplateCloser:
+
+**BreakBeforeTemplateCloser** (``Boolean``) :versionbadge:`clang-format 21` :ref:`¶ `
+ If ``true``, break before a template closing bracket (``>``) when there is
+ a line break after the matching opening bracket (``<``).
+
+ .. code-block:: c++
+
+ true:
+ template
+
+ template
+
+ template <
+ typename Foo,
+ typename Bar
+ >
+
+ false:
+ template
+
+ template
+
+ template <
+ typename Foo,
+ typename Bar>
+
.. _BreakBeforeTernaryOperators:
**BreakBeforeTernaryOperators** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ `
@@ -5198,6 +5245,11 @@ the configuration (without a prefix: ``Auto``).
**PenaltyBreakBeforeFirstCallParameter** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ `
The penalty for breaking a function call after ``call(``.
+.. _PenaltyBreakBeforeMemberAccess:
+
+**PenaltyBreakBeforeMemberAccess** (``Unsigned``) :versionbadge:`clang-format 20` :ref:`¶ `
+ The penalty for breaking before a member access operator (``.``, ``->``).
+
.. _PenaltyBreakComment:
**PenaltyBreakComment** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ `
diff --git a/clang/docs/ControlFlowIntegrity.rst b/clang/docs/ControlFlowIntegrity.rst
index 7de805e2154db..3c97f7da3d7d9 100644
--- a/clang/docs/ControlFlowIntegrity.rst
+++ b/clang/docs/ControlFlowIntegrity.rst
@@ -336,6 +336,15 @@ cross-DSO function address equality. These properties make KCFI easier to
adopt in low-level software. KCFI is limited to checking only function
pointers, and isn't compatible with executable-only memory.
+``-fsanitize-kcfi-arity``
+-----------------------------
+
+For supported targets, this feature extends kCFI by telling the compiler to
+record information about each indirect-callable function's arity (i.e., the
+number of arguments passed in registers) into the binary. Some kernel CFI
+techniques, such as FineIBT, may be able to use this information to provide
+enhanced security.
+
Member Function Pointer Call Checking
=====================================
diff --git a/clang/docs/HIPSupport.rst b/clang/docs/HIPSupport.rst
index e830acd8dd85c..481ed39230813 100644
--- a/clang/docs/HIPSupport.rst
+++ b/clang/docs/HIPSupport.rst
@@ -27,7 +27,8 @@ AMD GPU Support
Clang provides HIP support on AMD GPUs via the ROCm platform ``_.
The ROCm runtime forms the base for HIP host APIs, while HIP device APIs are realized through HIP header
files and the ROCm device library. The Clang driver uses the HIPAMD toolchain to compile HIP device code
-to AMDGPU ISA via the AMDGPU backend. The compiled code is then bundled and embedded in the host executables.
+to AMDGPU ISA via the AMDGPU backend, or SPIR-V via the workflow outlined below.
+The compiled code is then bundled and embedded in the host executables.
Intel GPU Support
=================
@@ -285,6 +286,401 @@ Example Usage
basePtr->virtualFunction(); // Allowed since obj is constructed in device code
}
+C++ Standard Parallelism Offload Support: Compiler And Runtime
+==============================================================
+
+Introduction
+============
+
+This section describes the implementation of support for offloading the
+execution of standard C++ algorithms to accelerators that can be targeted via
+HIP. Furthermore, it enumerates restrictions on user defined code, as well as
+the interactions with runtimes.
+
+Algorithm Offload: What, Why, Where
+===================================
+
+C++17 introduced overloads
+`for most algorithms in the standard library `_
+which allow the user to specify a desired
+`execution policy `_.
+The `parallel_unsequenced_policy `_
+maps relatively well to the execution model of AMD GPUs. This, coupled with the
+the availability and maturity of GPU accelerated algorithm libraries that
+implement most / all corresponding algorithms in the standard library
+(e.g. `rocThrust `__), makes
+it feasible to provide seamless accelerator offload for supported algorithms,
+when an accelerated version exists. Thus, it becomes possible to easily access
+the computational resources of an AMD accelerator, via a well specified,
+familiar, algorithmic interface, without having to delve into low-level hardware
+specific details. Putting it all together:
+
+- **What**: standard library algorithms, when invoked with the
+ ``parallel_unsequenced_policy``
+- **Why**: democratise AMDGPU accelerator programming, without loss of user
+ familiarity
+- **Where**: only AMDGPU accelerators targeted by Clang/LLVM via HIP
+
+Small Example
+=============
+
+Given the following C++ code:
+
+.. code-block:: C++
+
+ bool has_the_answer(const std::vector& v) {
+ return std::find(std::execution::par_unseq, std::cbegin(v), std::cend(v), 42) != std::cend(v);
+ }
+
+if Clang is invoked with the ``--hipstdpar --offload-arch=foo`` flags, the call
+to ``find`` will be offloaded to an accelerator that is part of the ``foo``
+target family. If either ``foo`` or its runtime environment do not support
+transparent on-demand paging (such as e.g. that provided in Linux via
+`HMM `_), it is necessary to also include
+the ``--hipstdpar-interpose-alloc`` flag. If the accelerator specific algorithm
+library ``foo`` uses doesn't have an implementation of a particular algorithm,
+execution seamlessly falls back to the host CPU. It is legal to specify multiple
+``--offload-arch``\s. All the flags we introduce, as well as a thorough view of
+various restrictions an their implementations, will be provided below.
+
+Implementation - General View
+=============================
+
+We built support for Algorithm Offload support atop the pre-existing HIP
+infrastructure. More specifically, when one requests offload via ``--hipstdpar``,
+compilation is switched to HIP compilation, as if ``-x hip`` was specified.
+Similarly, linking is also switched to HIP linking, as if ``--hip-link`` was
+specified. Note that these are implicit, and one should not assume that any
+interop with HIP specific language constructs is available e.g. ``__device__``
+annotations are neither necessary nor guaranteed to work.
+
+Since there are no language restriction mechanisms in place, it is necessary to
+relax HIP language specific semantic checks performed by the FE; they would
+identify otherwise valid, offloadable code, as invalid HIP code. Given that we
+know that the user intended only for certain algorithms to be offloaded, and
+encoded this by specifying the ``parallel_unsequenced_policy``, we rely on a
+pass over IR to clean up any and all code that was not "meant" for offload. If
+requested, allocation interposition is also handled via a separate pass over IR.
+
+To interface with the client HIP runtime, and to forward offloaded algorithm
+invocations to the corresponding accelerator specific library implementation, an
+implementation detail forwarding header is implicitly included by the driver,
+when compiling with ``--hipstdpar``. In what follows, we will delve into each
+component that contributes to implementing Algorithm Offload support.
+
+Implementation - Driver
+=======================
+
+We augment the ``clang`` driver with the following flags:
+
+- ``--hipstdpar`` enables algorithm offload, which depending on phase, has the
+ following effects:
+
+ - when compiling:
+
+ - ``-x hip`` gets prepended to enable HIP support;
+ - the ``ROCmToolchain`` component checks for the ``hipstdpar_lib.hpp``
+ forwarding header,
+ `rocThrust `_ and
+ `rocPrim `_ in
+ their canonical locations, which can be overriden via flags found below;
+ if all are found, the forwarding header gets implicitly included,
+ otherwise an error listing the missing component is generated;
+ - the ``LangOpts.HIPStdPar`` member is set.
+
+ - when linking:
+
+ - ``--hip-link`` and ``-frtlib-add-rpath`` gets appended to enable HIP
+ support.
+
+- ``--hipstdpar-interpose-alloc`` enables the interposition of standard
+ allocation / deallocation functions with accelerator aware equivalents; the
+ ``LangOpts.HIPStdParInterposeAlloc`` member is set;
+- ``--hipstdpar-path=`` specifies a non-canonical path for the forwarding
+ header; it must point to the folder where the header is located and not to the
+ header itself;
+- ``--hipstdpar-thrust-path=`` specifies a non-canonical path for
+ `rocThrust `_; it
+ must point to the folder where the library is installed / built under a
+ ``/thrust`` subfolder;
+- ``--hipstdpar-prim-path=`` specifies a non-canonical path for
+ `rocPrim `_; it must
+ point to the folder where the library is installed / built under a
+ ``/rocprim`` subfolder;
+
+The `--offload-arch `_
+flag can be used to specify the accelerator for which offload code is to be
+generated.
+
+Implementation - Front-End
+==========================
+
+When ``LangOpts.HIPStdPar`` is set, we relax some of the HIP language specific
+``Sema`` checks to account for the fact that we want to consume pure unannotated
+C++ code:
+
+1. ``__device__`` / ``__host__ __device__`` functions (which would originate in
+ the accelerator specific algorithm library) are allowed to call implicitly
+ ``__host__`` functions;
+2. ``__global__`` functions (which would originate in the accelerator specific
+ algorithm library) are allowed to call implicitly ``__host__`` functions;
+3. resolving ``__builtin`` availability is deferred, because it is possible that
+ a ``__builtin`` that is unavailable on the target accelerator is not
+ reachable from any offloaded algorithm, and thus will be safely removed in
+ the middle-end;
+4. ASM parsing / checking is deferred, because it is possible that an ASM block
+ that e.g. uses some constraints that are incompatible with the target
+ accelerator is not reachable from any offloaded algorithm, and thus will be
+ safely removed in the middle-end.
+
+``CodeGen`` is similarly relaxed, with implicitly ``__host__`` functions being
+emitted as well.
+
+Implementation - Middle-End
+===========================
+
+We add two ``opt`` passes:
+
+1. ``HipStdParAcceleratorCodeSelectionPass``
+
+ - For all kernels in a ``Module``, compute reachability, where a function
+ ``F`` is reachable from a kernel ``K`` if and only if there exists a direct
+ call-chain rooted in ``F`` that includes ``K``;
+ - Remove all functions that are not reachable from kernels;
+ - This pass is only run when compiling for the accelerator.
+
+The first pass assumes that the only code that the user intended to offload was
+that which was directly or transitively invocable as part of an algorithm
+execution. It also assumes that an accelerator aware algorithm implementation
+would rely on accelerator specific special functions (kernels), and that these
+effectively constitute the only roots for accelerator execution graphs. Both of
+these assumptions are based on observing how widespread accelerators,
+such as GPUs, work.
+
+1. ``HipStdParAllocationInterpositionPass``
+
+ - Iterate through all functions in a ``Module``, and replace standard
+ allocation / deallocation functions with accelerator-aware equivalents,
+ based on a pre-established table; the list of functions that can be
+ interposed is available
+ `here `__;
+ - This is only run when compiling for the host.
+
+The second pass is optional.
+
+Implementation - Forwarding Header
+==================================
+
+The forwarding header implements two pieces of functionality:
+
+1. It forwards algorithms to a target accelerator, which is done by relying on
+ C++ language rules around overloading:
+
+ - overloads taking an explicit argument of type
+ ``parallel_unsequenced_policy`` are introduced into the ``std`` namespace;
+ - these will get preferentially selected versus the master template;
+ - the body forwards to the equivalent algorithm from the accelerator specific
+ library
+
+2. It provides allocation / deallocation functions that are equivalent to the
+ standard ones, but obtain memory by invoking
+ `hipMallocManaged `_
+ and release it via `hipFree `_.
+
+Predefined Macros
+=================
+
+.. list-table::
+ :header-rows: 1
+
+ * - Macro
+ - Description
+ * - ``__HIPSTDPAR__``
+ - Defined when Clang is compiling code in algorithm offload mode, enabled
+ with the ``--hipstdpar`` compiler option.
+ * - ``__HIPSTDPAR_INTERPOSE_ALLOC__``
+ - Defined only when compiling in algorithm offload mode, when the user
+ enables interposition mode with the ``--hipstdpar-interpose-alloc``
+ compiler option, indicating that all dynamic memory allocation /
+ deallocation functions should be replaced with accelerator aware
+ variants.
+
+Restrictions
+============
+
+We define two modes in which runtime execution can occur:
+
+1. **HMM Mode** - this assumes that the
+ `HMM `_ subsystem of the Linux kernel
+ is used to provide transparent on-demand paging i.e. memory obtained from a
+ system / OS allocator such as via a call to ``malloc`` or ``operator new`` is
+ directly accessible to the accelerator and it follows the C++ memory model;
+2. **Interposition Mode** - this is a fallback mode for cases where transparent
+ on-demand paging is unavailable (e.g. in the Windows OS), which means that
+ memory must be allocated via an accelerator aware mechanism, and system
+ allocated memory is inaccessible for the accelerator.
+
+The following restrictions imposed on user code apply to both modes:
+
+1. Pointers to function, and all associated features, such as e.g. dynamic
+ polymorphism, cannot be used (directly or transitively) by the user provided
+ callable passed to an algorithm invocation;
+2. Global / namespace scope / ``static`` / ``thread`` storage duration variables
+ cannot be used (directly or transitively) in name by the user provided
+ callable;
+
+ - When executing in **HMM Mode** they can be used in address e.g.:
+
+ .. code-block:: C++
+
+ namespace { int foo = 42; }
+
+ bool never(const std::vector& v) {
+ return std::any_of(std::execution::par_unseq, std::cbegin(v), std::cend(v), [](auto&& x) {
+ return x == foo;
+ });
+ }
+
+ bool only_in_hmm_mode(const std::vector& v) {
+ return std::any_of(std::execution::par_unseq, std::cbegin(v), std::cend(v),
+ [p = &foo](auto&& x) { return x == *p; });
+ }
+
+3. Only algorithms that are invoked with the ``parallel_unsequenced_policy`` are
+ candidates for offload;
+4. Only algorithms that are invoked with iterator arguments that model
+ `random_access_iterator `_
+ are candidates for offload;
+5. `Exceptions `_ cannot
+ be used by the user provided callable;
+6. Dynamic memory allocation (e.g. ``operator new``) cannot be used by the user
+ provided callable;
+7. Selective offload is not possible i.e. it is not possible to indicate that
+ only some algorithms invoked with the ``parallel_unsequenced_policy`` are to
+ be executed on the accelerator.
+
+In addition to the above, using **Interposition Mode** imposes the following
+additional restrictions:
+
+1. All code that is expected to interoperate has to be recompiled with the
+ ``--hipstdpar-interpose-alloc`` flag i.e. it is not safe to compose libraries
+ that have been independently compiled;
+2. automatic storage duration (i.e. stack allocated) variables cannot be used
+ (directly or transitively) by the user provided callable e.g.
+
+ .. code-block:: c++
+
+ bool never(const std::vector& v, int n) {
+ return std::any_of(std::execution::par_unseq, std::cbegin(v), std::cend(v),
+ [p = &n](auto&& x) { return x == *p; });
+ }
+
+Current Support
+===============
+
+At the moment, C++ Standard Parallelism Offload is only available for AMD GPUs,
+when the `ROCm `_ stack is used, on the
+Linux operating system. Support is synthesised in the following table:
+
+.. list-table::
+ :header-rows: 1
+
+ * - `Processor `_
+ - HMM Mode
+ - Interposition Mode
+ * - GCN GFX9 (Vega)
+ - YES
+ - YES
+ * - GCN GFX10.1 (RDNA 1)
+ - *NO*
+ - YES
+ * - GCN GFX10.3 (RDNA 2)
+ - *NO*
+ - YES
+ * - GCN GFX11 (RDNA 3)
+ - *NO*
+ - YES
+ * - GCN GFX12 (RDNA 4)
+ - *NO*
+ - YES
+
+The minimum Linux kernel version for running in HMM mode is 6.4.
+
+The forwarding header can be obtained from
+`its GitHub repository `_.
+It will be packaged with a future `ROCm `_
+release. Because accelerated algorithms are provided via
+`rocThrust `_, a
+transitive dependency on
+`rocPrim `_ exists. Both
+can be obtained either by installing their associated components of the
+`ROCm `_ stack, or from their respective
+repositories. The list algorithms that can be offloaded is available
+`here `_.
+
+HIP Specific Elements
+---------------------
+
+1. There is no defined interop with the
+ `HIP kernel language `_;
+ whilst things like using `__device__` annotations might accidentally "work",
+ they are not guaranteed to, and thus cannot be relied upon by user code;
+
+ - A consequence of the above is that both bitcode linking and linking
+ relocatable object files will "work", but it is not guaranteed to remain
+ working or actively tested at the moment; this restriction might be relaxed
+ in the future.
+
+2. Combining explicit HIP, CUDA or OpenMP Offload compilation with
+ ``--hipstdpar`` based offloading is not allowed or supported in any way.
+3. There is no way to target different accelerators via a standard algorithm
+ invocation (`this might be addressed in future C++ standards `_);
+ an unsafe (per the point above) way of achieving this is to spawn new threads
+ and invoke the `hipSetDevice `_
+ interface e.g.:
+
+ .. code-block:: c++
+
+ int accelerator_0 = ...;
+ int accelerator_1 = ...;
+
+ bool multiple_accelerators(const std::vector& u, const std::vector& v) {
+ std::atomic r{0u};
+
+ thread t0{[&]() {
+ hipSetDevice(accelerator_0);
+
+ r += std::count(std::execution::par_unseq, std::cbegin(u), std::cend(u), 42);
+ }};
+ thread t1{[&]() {
+ hitSetDevice(accelerator_1);
+
+ r += std::count(std::execution::par_unseq, std::cbegin(v), std::cend(v), 314152)
+ }};
+
+ t0.join();
+ t1.join();
+
+ return r;
+ }
+
+ Note that this is a temporary, unsafe workaround for a deficiency in the C++
+ Standard.
+
+Open Questions / Future Developments
+====================================
+
+1. The restriction on the use of global / namespace scope / ``static`` /
+ ``thread`` storage duration variables in offloaded algorithms will be lifted
+ in the future, when running in **HMM Mode**;
+2. The restriction on the use of dynamic memory allocation in offloaded
+ algorithms will be lifted in the future.
+3. The restriction on the use of pointers to function, and associated features
+ such as dynamic polymorphism might be lifted in the future, when running in
+ **HMM Mode**;
+4. Offload support might be extended to cases where the ``parallel_policy`` is
+ used for some or all targets.
+
SPIR-V Support on HIPAMD ToolChain
==================================
@@ -316,13 +712,6 @@ Using ``--offload-arch=amdgcnspirv``
- **Clang Offload Bundler**: The resulting SPIR-V is embedded in the Clang
offload bundler with the bundle ID ``hip-spirv64-amd-amdhsa--amdgcnspirv``.
-Mixed with Normal ``--offload-arch``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-**Mixing ``amdgcnspirv`` and concrete ``gfx###`` targets via ``--offload-arch``
-is not currently supported; this limitation is temporary and will be removed in
-a future release**
-
Architecture Specific Macros
----------------------------
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index c42b88015e269..973cf8f9d091c 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -514,9 +514,7 @@ available in all language modes.
__nullptr
---------
-``__nullptr`` is an alternate spelling for ``nullptr``, but is also available in
-C++ modes prior to C++11. Note that it's currently not availbale in C despite
-C23 having support for ``nullptr``.
+``__nullptr`` is an alternate spelling for ``nullptr``. It is available in all C and C++ language modes.
__signed, __signed__
--------------------
@@ -759,6 +757,9 @@ The integer elementwise intrinsics, including ``__builtin_elementwise_popcount``
``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
``__builtin_elementwise_sub_sat`` can be called in a ``constexpr`` context.
+No implicit promotion of integer types takes place. The mixing of integer types
+of different sizes and signs is forbidden in binary and ternary builtins.
+
============================================== ====================================================================== =========================================
Name Operation Supported element types
============================================== ====================================================================== =========================================
@@ -1802,10 +1803,6 @@ The following type trait primitives are supported by Clang. Those traits marked
* ``__is_pointer_interconvertible_base_of`` (C++, GNU, Microsoft)
* ``__is_polymorphic`` (C++, GNU, Microsoft, Embarcadero)
* ``__is_reference`` (C++, Embarcadero)
-* ``__is_referenceable`` (C++, GNU, Microsoft, Embarcadero):
- Returns true if a type is referenceable, and false otherwise. A referenceable
- type is a type that's either an object type, a reference type, or an unqualified
- function type. This trait is deprecated and will be removed in Clang 21.
* ``__is_rvalue_reference`` (C++, Embarcadero)
* ``__is_same`` (C++, Embarcadero)
* ``__is_same_as`` (GCC): Synonym for ``__is_same``.
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 673c34bf08a4a..725624ee8c66c 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -364,6 +364,8 @@ implementation.
+=============================================================+===========================+===========================+==========================================================================+
| free-agent threads | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| threadset clause | :`worked on` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Recording of task graphs | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Parallel inductions | :none:`unclaimed` | :none:`unclaimed` | |
@@ -410,13 +412,13 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Extensions to interop construct | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| no_openmp_constructs | :none:`unclaimed` | :none:`unclaimed` | |
+| no_openmp_constructs | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125933 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| safe_sync and progress with identifier and API | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| OpenMP directives in concurrent loop regions | :none:`unclaimed` | :none:`unclaimed` | |
+| OpenMP directives in concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| atomics constructs on concurrent loop regions | :none:`unclaimed` | :none:`unclaimed` | |
+| atomics constructs on concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Loop construct with DO CONCURRENT | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
@@ -454,9 +456,7 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| map-type modifiers in arbitrary position | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| atomic constructs in loop region | :none:`unclaimed` | :none:`unclaimed` | |
-+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| Lift nesting restriction on concurrent loop | :none:`unclaimed` | :none:`unclaimed` | |
+| Lift nesting restriction on concurrent loop | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| priority clause for target constructs | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f110b8cf76507..6344c4b36e357 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -33,218 +33,23 @@ latest release, please see the `Clang Web Site `_ or the
Potentially Breaking Changes
============================
-These changes are ones which we think may surprise users when upgrading to
-Clang |release| because of the opportunity they pose for disruption to existing
-code bases.
-
-- The ``le32`` and ``le64`` targets have been removed.
-
-- ``clang -m32`` defaults to ``-mcpu=v9`` on SPARC Linux now. Distros
- still supporting SPARC V8 CPUs need to specify ``-mcpu=v8`` with a
- `config file
- `_.
-
-- The ``clang-rename`` tool has been removed.
-
-- Removed support for RenderScript targets. This technology is
- `officially deprecated `_
- and users are encouraged to
- `migrate to Vulkan `_
- or other options.
-
-- Clang now emits distinct type-based alias analysis tags for incompatible
- pointers by default, enabling more powerful alias analysis when accessing
- pointer types. This change may silently change code behavior for code
- containing strict-aliasing violations. The new default behavior can be
- disabled using ``-fno-pointer-tbaa``.
-
-- Clang will now more aggressively use undefined behavior on pointer addition
- overflow for optimization purposes. For example, a check like
- ``ptr + unsigned_offset < ptr`` will now optimize to ``false``, because
- ``ptr + unsigned_offset`` will cause undefined behavior if it overflows (or
- advances past the end of the object).
-
- Previously, ``ptr + unsigned_offset < ptr`` was optimized (by both Clang and
- GCC) to ``(ssize_t)unsigned_offset < 0``. This also results in an incorrect
- overflow check, but in a way that is less apparent when only testing with
- pointers in the low half of the address space.
-
- To avoid pointer addition overflow, it is necessary to perform the addition
- on integers, for example using
- ``(uintptr_t)ptr + unsigned_offset < (uintptr_t)ptr``. Sometimes, it is also
- possible to rewrite checks by only comparing the offset. For example,
- ``ptr + offset < end_ptr && ptr + offset >= ptr`` can be written as
- ``offset < (uintptr_t)(end_ptr - ptr)``.
-
- Undefined behavior due to pointer addition overflow can be reliably detected
- using ``-fsanitize=pointer-overflow``. It is also possible to use
- ``-fno-strict-overflow`` to opt-in to a language dialect where signed integer
- and pointer overflow are well-defined.
+
+- The Objective-C ARC migrator (ARCMigrate) has been removed.
C/C++ Language Potentially Breaking Changes
-------------------------------------------
-- Clang now rejects ``_Complex _BitInt`` types.
-
C++ Specific Potentially Breaking Changes
-----------------------------------------
-- The type trait builtin ``__is_nullptr`` has been removed, since it has very
- few users and can be written as ``__is_same(__remove_cv(T), decltype(nullptr))``,
- which GCC supports as well.
-
-- The type trait builtin ``__is_referenceable`` has been deprecated, since it has
+- The type trait builtin ``__is_referenceable`` has been removed, since it has
very few users and all the type traits that could benefit from it in the
- standard library already have their own bespoke builtins. It will be removed in
- Clang 21.
-
-- Clang will now correctly diagnose as ill-formed a constant expression where an
- enum without a fixed underlying type is set to a value outside the range of
- the enumeration's values.
-
- .. code-block:: c++
-
- enum E { Zero, One, Two, Three, Four };
- constexpr E Val1 = (E)3; // Ok
- constexpr E Val2 = (E)7; // Ok
- constexpr E Val3 = (E)8; // Now ill-formed, out of the range [0, 7]
- constexpr E Val4 = (E)-1; // Now ill-formed, out of the range [0, 7]
-
- Since Clang 16, it has been possible to suppress the diagnostic via
- `-Wno-enum-constexpr-conversion`, to allow for a transition period for users.
- Now, in Clang 20, **it is no longer possible to suppress the diagnostic**.
-
-- Extraneous template headers are now ill-formed by default.
- This error can be disable with ``-Wno-error=extraneous-template-head``.
-
- .. code-block:: c++
-
- template <> // error: extraneous template head
- template
- void f();
-
-- During constant evaluation, comparisons between different evaluations of the
- same string literal are now correctly treated as non-constant, and comparisons
- between string literals that cannot possibly overlap in memory are now treated
- as constant. This updates Clang to match the anticipated direction of open core
- issue `CWG2765 `, but is subject to change once that
- issue is resolved.
-
- .. code-block:: c++
-
- constexpr const char *f() { return "hello"; }
- constexpr const char *g() { return "world"; }
- // Used to evaluate to false, now error: non-constant comparison.
- constexpr bool a = f() == f();
- // Might evaluate to true or false, as before.
- bool at_runtime() { return f() == f(); }
- // Was error, now evaluates to false.
- constexpr bool b = f() == g();
-
-- Clang will now correctly not consider pointers to non classes for covariance
- and disallow changing return type to a type that doesn't have the same or less cv-qualifications.
-
- .. code-block:: c++
-
- struct A {
- virtual const int *f() const;
- virtual const std::string *g() const;
- };
- struct B : A {
- // Return type has less cv-qualification but doesn't point to a class.
- // Error will be generated.
- int *f() const override;
-
- // Return type doesn't have more cv-qualification also not the same or
- // less cv-qualification.
- // Error will be generated.
- volatile std::string *g() const override;
- };
-
-- The warning ``-Wdeprecated-literal-operator`` is now on by default, as this is
- something that WG21 has shown interest in removing from the language. The
- result is that anyone who is compiling with ``-Werror`` should see this
- diagnostic. To fix this diagnostic, simply removing the space character from
- between the ``operator""`` and the user defined literal name will make the
- source no longer deprecated. This is consistent with `CWG2521 _`.
-
- .. code-block:: c++
-
- // Now diagnoses by default.
- unsigned operator"" _udl_name(unsigned long long);
- // Fixed version:
- unsigned operator""_udl_name(unsigned long long);
-
-- Clang will now produce an error diagnostic when ``[[clang::lifetimebound]]`` is
- applied on a parameter or an implicit object parameter of a function that
- returns void. This was previously ignored and had no effect. (#GH107556)
-
- .. code-block:: c++
-
- // Now diagnoses with an error.
- void f(int& i [[clang::lifetimebound]]);
-
-- Clang will now produce an error diagnostic when ``[[clang::lifetimebound]]``
- is applied on a type (instead of a function parameter or an implicit object
- parameter); this includes the case when the attribute is specified for an
- unnamed function parameter. These were previously ignored and had no effect.
- (#GH118281)
-
- .. code-block:: c++
-
- // Now diagnoses with an error.
- int* [[clang::lifetimebound]] x;
- // Now diagnoses with an error.
- void f(int* [[clang::lifetimebound]] i);
- // Now diagnoses with an error.
- void g(int* [[clang::lifetimebound]]);
-
-- Clang now rejects all field accesses on null pointers in constant expressions. The following code
- used to work but will now be rejected:
-
- .. code-block:: c++
-
- struct S { int a; int b; };
- constexpr const int *p = &((S*)nullptr)->b;
-
- Previously, this code was erroneously accepted.
-
-- Clang will now consider the implicitly deleted destructor of a union or
- a non-union class without virtual base class to be ``constexpr`` in C++20
- mode (Clang 19 only did so in C++23 mode but the standard specification for
- this changed in C++20). (#GH85550)
-
- .. code-block:: c++
-
- struct NonLiteral {
- NonLiteral() {}
- ~NonLiteral() {}
- };
-
- template
- struct Opt {
- union {
- char c;
- T data;
- };
- bool engaged = false;
-
- constexpr Opt() {}
- constexpr ~Opt() {
- if (engaged)
- data.~T();
- }
- };
-
- // Previously only accepted in C++23 and later, now also accepted in C++20.
- consteval void foo() { Opt{}; }
+ standard library already have their own bespoke builtins.
ABI Changes in This Version
---------------------------
-- Fixed Microsoft name mangling of placeholder, auto and decltype(auto), return types for MSVC 1920+. This change resolves incompatibilities with code compiled by MSVC 1920+ but will introduce incompatibilities with code compiled by earlier versions of Clang unless such code is built with the compiler option -fms-compatibility-version=19.14 to imitate the MSVC 1914 mangling behavior.
-- Fixed the Itanium mangling of the construction vtable name. This change will introduce incompatibilities with code compiled by Clang 19 and earlier versions, unless the -fclang-abi-compat=19 option is used. (#GH108015)
-- Mangle member-like friend function templates as members of the enclosing class. (#GH110247, #GH110503)
+- Return larger CXX records in memory instead of using AVX registers. Code compiled with older clang will be incompatible with newer version of the clang unless -fclang-abi-compat=20 is provided. (#GH120670)
AST Dumping Potentially Breaking Changes
----------------------------------------
@@ -254,569 +59,82 @@ Clang Frontend Potentially Breaking Changes
Clang Python Bindings Potentially Breaking Changes
--------------------------------------------------
-- Parts of the interface returning string results will now return
- the empty string ``""`` when no result is available, instead of ``None``.
-- Calling a property on the ``CompletionChunk`` or ``CompletionString`` class
- statically now leads to an error, instead of returning a ``CachedProperty`` object
- that is used internally. Properties are only available on instances.
-- For a single-line ``SourceRange`` and a ``SourceLocation`` in the same line,
- but after the end of the ``SourceRange``, ``SourceRange.__contains__``
- used to incorrectly return ``True``. (#GH22617), (#GH52827)
What's New in Clang |release|?
==============================
-Some of the major new features and improvements to Clang are listed
-here. Generic improvements to Clang as a whole or to its underlying
-infrastructure are described first, followed by language-specific
-sections with improvements to Clang's support for those languages.
C++ Language Changes
--------------------
-- Allow single element access of GCC vector/ext_vector_type object to be
- constant expression. Supports the `V.xyzw` syntax and other tidbits
- as seen in OpenCL. Selecting multiple elements is left as a future work.
-- Implement `CWG1815 `_. Support lifetime extension
- of temporary created by aggregate initialization using a default member
- initializer.
-
-- Accept C++26 user-defined ``static_assert`` messages in C++11 as an extension.
-
-- Add ``__builtin_elementwise_popcount`` builtin for integer types only.
-
-- Add ``__builtin_elementwise_fmod`` builtin for floating point types only.
-
-- Add ``__builtin_elementwise_minimum`` and ``__builtin_elementwise_maximum``
- builtin for floating point types only.
-
-- The builtin type alias ``__builtin_common_type`` has been added to improve the
- performance of ``std::common_type``.
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- Add ``__builtin_is_virtual_base_of`` intrinsic, which supports
- `P2985R0 A type trait for detecting virtual base classes `_
-
-- Implemented `P2893R3 Variadic Friends `_
-
-- Implemented `P2747R2 constexpr placement new `_.
-
-- Added the ``__builtin_is_within_lifetime`` builtin, which supports
- `P2641R4 Checking if a union alternative is active `_
-
-- Implemented `P3176R1 The Oxford variadic comma `_
-
C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- Removed the restriction to literal types in constexpr functions in C++23 mode.
-
-- Extend lifetime of temporaries in mem-default-init for P2718R0. Clang now fully
- supports `P2718R0 Lifetime extension in range-based for loops `_.
-
-- ``__cpp_explicit_this_parameter`` is now defined. (#GH82780)
-
-- Add ``__builtin_is_implicit_lifetime`` intrinsic, which supports
- `P2674R1 A trait for implicit lifetime types `_
-
-- Add support for `P2280R4 Using unknown pointers and references in constant expressions `_. (#GH63139)
C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- Implemented module level lookup for C++20 modules. (#GH90154)
-
C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- The implementation of the relaxed template template argument matching rules is
- more complete and reliable, and should provide more accurate diagnostics.
Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Allow calling initializer list constructors from initializer lists with
- a single element of the same type instead of always copying.
- (`CWG2137: List-initialization from object of same type `)
-
-- Speculative resolution for CWG2311 implemented so that the implementation of CWG2137 doesn't remove
- previous cases where guaranteed copy elision was done. Given a prvalue ``e`` of class type
- ``T``, ``T{e}`` will try to resolve an initializer list constructor and will use it if successful.
- Otherwise, if there is no initializer list constructor, the copy will be elided as if it was ``T(e)``.
- (`CWG2311: Missed case for guaranteed copy elision `)
-
-- Casts from a bit-field to an integral type is now not considered narrowing if the
- width of the bit-field means that all potential values are in the range
- of the target type, even if the type of the bit-field is larger.
- (`CWG2627: Bit-fields and narrowing conversions `_)
-
-- ``nullptr`` is now promoted to ``void*`` when passed to a C-style variadic function.
- (`CWG722: Can nullptr be passed to an ellipsis? `_)
-
-- Allow ``void{}`` as a prvalue of type ``void``.
- (`CWG2351: void{} `_).
-
-- Clang now has improved resolution to CWG2398, allowing class templates to have
- default arguments deduced when partial ordering, and better backwards compatibility
- in overload resolution.
-
-- Clang now allows comparing unequal object pointers that have been cast to ``void *``
- in constant expressions. These comparisons always worked in non-constant expressions.
- (`CWG2749: Treatment of "pointer to void" for relational comparisons `_).
-
-- Reject explicit object parameters with type ``void`` (``this void``).
- (`CWG2915: Explicit object parameters of type void `_).
-
-- Clang now allows trailing requires clause on explicit deduction guides.
- (`CWG2707: Deduction guides cannot have a trailing requires-clause `_).
-
-- Respect constructor constraints during CTAD.
- (`CWG2628: Implicit deduction guides should propagate constraints `_).
-
-- Clang now diagnoses a space in the first production of a ``literal-operator-id``
- by default.
- (`CWG2521: User-defined literals and reserved identifiers `_).
-
-- Fix name lookup for a dependent base class that is the current instantiation.
- (`CWG591: When a dependent base class is the current instantiation `_).
-
-- Clang now allows calling explicit object member functions directly with prvalues
- instead of always materializing a temporary, meaning by-value explicit object parameters
- do not need to move from a temporary.
- (`CWG2813: Class member access with prvalues `_).
+- The flag `-frelaxed-template-template-args`
+ and its negation have been removed, having been deprecated since the previous
+ two releases. The improvements to template template parameter matching implemented
+ in the previous release, as described in P3310 and P3579, made this flag unnecessary.
C Language Changes
------------------
-- Extend clang's ```` to define ``LONG_LONG_*`` macros for Android's bionic.
+- Clang now allows an ``inline`` specifier on a typedef declaration of a
+ function type in Microsoft compatibility mode. #GH124869
C2y Feature Support
^^^^^^^^^^^^^^^^^^^
-- Updated conformance for `N3298 `_
- which adds the ``i`` and ``j`` suffixes for the creation of a ``_Complex``
- constant value. Clang has always supported these suffixes as a GNU extension,
- so ``-Wgnu-imaginary-constant`` no longer has effect in C modes, as this is
- now a C2y extension in C. ``-Wgnu-imaginary-constant`` still applies in C++
- modes.
-
-- Clang updated conformance for `N3370 `_
- case range expressions. This feature was previously supported by Clang as a
- GNU extension, so ``-Wgnu-case-range`` no longer has effect in C modes, as
- this is now a C2y extension in C. ``-Wgnu-case-range`` still applies in C++
- modes.
-
-- Clang implemented support for `N3344 `_
- which disallows a ``void`` parameter from having a qualifier or storage class
- specifier. Note that ``register void`` was previously accepted in all C
- language modes but is now rejected (all of the other qualifiers and storage
- class specifiers were previously rejected).
-
-- Updated conformance for `N3364 `_
- on floating-point translation-time initialization with signaling NaN. This
- paper adopts Clang's existing practice, so there were no changes to compiler
- behavior.
-
-- Implemented support for `N3341 `_
- which makes empty structure and union objects implementation-defined in C.
- ``-Wgnu-empty-struct`` will be emitted in C23 and earlier modes because the
- behavior is a conforming GNU extension in those modes, but will no longer
- have an effect in C2y mode.
-
-- Updated conformance for `N3342 `_
- which made qualified function types implementation-defined rather than
- undefined. Clang has always accepted ``const`` and ``volatile`` qualified
- function types by ignoring the qualifiers.
-
-- Updated conformance for `N3346 `_
- which changes some undefined behavior around initialization to instead be
- constraint violations. This paper adopts Clang's existing practice, so there
- were no changes to compiler behavior.
-
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
-- Clang now supports `N3029 `_ Improved Normal Enumerations.
-- Clang now officially supports `N3030 `_ Enhancements to Enumerations. Clang already supported it as an extension, so there were no changes to compiler behavior.
-- Fixed the value of ``BOOL_WIDTH`` in ```` to return ``1``
- explicitly, as mandated by the standard. Fixes #GH117348
-
Non-comprehensive list of changes in this release
-------------------------------------------------
-- The floating point comparison builtins (``__builtin_isgreater``,
- ``__builtin_isgreaterequal``, ``__builtin_isless``, etc.) and
- ``__builtin_signbit`` can now be used in constant expressions.
-- Plugins can now define custom attributes that apply to statements
- as well as declarations.
-- ``__builtin_abs`` function can now be used in constant expressions.
-
-- The new builtin ``__builtin_counted_by_ref`` was added. In contexts where the
- programmer needs access to the ``counted_by`` attribute's field, but it's not
- available --- e.g. in macros. For instance, it can be used to automatically
- set the counter during allocation in the Linux kernel:
-
- .. code-block:: c
-
- /* A simplified version of Linux allocation macros */
- #define alloc(PTR, FAM, COUNT) ({ \
- sizeof_t __ignored_assignment; \
- typeof(P) __p; \
- size_t __size = sizeof(*P) + sizeof(*P->FAM) * COUNT; \
- __p = malloc(__size); \
- *_Generic( \
- __builtin_counted_by_ref(__p->FAM), \
- void *: &__ignored_assignment, \
- default: __builtin_counted_by_ref(__p->FAM)) = COUNT; \
- __p; \
- })
-
- The flexible array member (FAM) can now be accessed immediately without causing
- issues with the sanitizer because the counter is automatically set.
-
-- The following builtins can now be used in constant expressions: ``__builtin_reduce_add``,
- ``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``,
- ``__builtin_reduce_xor``, ``__builtin_elementwise_popcount``,
- ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
- ``__builtin_elementwise_sub_sat``, ``__builtin_reduce_min`` (For integral element type),
- ``__builtin_reduce_max`` (For integral element type).
-
-- Clang now rejects ``_BitInt`` matrix element types if the bit width is less than ``CHAR_WIDTH`` or
- not a power of two, matching preexisting behaviour for vector types.
-
-- Matrix types (a Clang extension) can now be used in pseudo-destructor expressions,
- which allows them to be stored in STL containers.
-
-- In the ``-ftime-report`` output, the new "Clang time report" group replaces
- the old "Clang front-end time report" and includes "Front end", "LLVM IR
- generation", "Optimizer", and "Machine code generation".
-
New Compiler Flags
------------------
-- The ``-fc++-static-destructors={all,thread-local,none}`` flag was
- added to control which C++ variables have static destructors
- registered: all (the default) does so for all variables, thread-local
- only for thread-local variables, and none (which corresponds to the
- existing ``-fno-c++-static-destructors`` flag) skips all static
- destructors registration.
-
-- The ``-Warray-compare`` warning has been added to warn about array comparison
- on versions older than C++20.
-
-- The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison
- starting from C++26, this warning is enabled as an error by default.
-
-- clang-cl and clang-dxc now support ``-fdiagnostics-color=[auto|never|always]``
- in addition to ``-f[no-]color-diagnostics``.
+- New option ``-fprofile-continuous`` added to enable continuous profile syncing to file (#GH124353, `docs `_).
+ The feature has `existed `_)
+ for a while and this is just a user facing option.
Deprecated Compiler Flags
-------------------------
-- ``-fheinous-gnu-extensions`` is deprecated; it is now equivalent to
- specifying ``-Wno-error=invalid-gnu-asm-cast`` and may be removed in the
- future.
-
Modified Compiler Flags
-----------------------
-- The ``-ffp-model`` option has been updated to enable a more limited set of
- optimizations when the ``fast`` argument is used and to accept a new argument,
- ``aggressive``. The behavior of ``-ffp-model=aggressive`` is equivalent
- to the previous behavior of ``-ffp-model=fast``. The updated
- ``-ffp-model=fast`` behavior no longer assumes finite math only and uses
- the ``promoted`` algorithm for complex division when possible rather than the
- less basic (limited range) algorithm.
-
-- The ``-fveclib`` option has been updated to enable ``-fno-math-errno`` for
- ``-fveclib=ArmPL`` and ``-fveclib=SLEEF``. This gives Clang more opportunities
- to utilize these vector libraries. The behavior for all other vector function
- libraries remains unchanged.
-
-- The ``-Wnontrivial-memcall`` warning has been added to warn about
- passing non-trivially-copyable destination parameter to ``memcpy``,
- ``memset`` and similar functions for which it is a documented undefined
- behavior. It is implied by ``-Wnontrivial-memaccess``
-
-- Added ``-fmodules-reduced-bmi`` flag corresponding to
- ``-fexperimental-modules-reduced-bmi`` flag. The ``-fmodules-reduced-bmi`` flag
- is intended to be enabled by default in the future.
-
Removed Compiler Flags
-------------------------
-- The compiler flag `-Wenum-constexpr-conversion` (and the `Wno-`, `Wno-error-`
- derivatives) is now removed, since it's no longer possible to suppress the
- diagnostic (see above). Users can expect an `unknown warning` diagnostic if
- it's still in use.
-
Attribute Changes in Clang
--------------------------
-- The ``swift_attr`` can now be applied to types. To make it possible to use imported APIs
- in Swift safely there has to be a way to annotate individual parameters and result types
- with relevant attributes that indicate that e.g. a block is called on a particular actor
- or it accepts a Sendable or global-actor (i.e. ``@MainActor``) isolated parameter.
-
- For example:
-
- .. code-block:: objc
-
- @interface MyService
- -(void) handle: (void (^ __attribute__((swift_attr("@Sendable"))))(id)) handler;
- @end
-
-- Clang now disallows more than one ``__attribute__((ownership_returns(class, idx)))`` with
- different class names attached to one function.
-
-- Introduced a new format attribute ``__attribute__((format(syslog, 1, 2)))`` from OpenBSD.
-
-- The ``hybrid_patchable`` attribute is now supported on ARM64EC targets. It can be used to specify
- that a function requires an additional x86-64 thunk, which may be patched at runtime.
-
-- The attribute ``[[clang::no_specializations]]`` has been added to warn
- users that a specific template shouldn't be specialized. This is useful for
- e.g. standard library type traits, where adding a specialization results in
- undefined behaviour.
-
-- ``[[clang::lifetimebound]]`` is now explicitly disallowed on explicit object member functions
- where they were previously silently ignored.
-
-- Clang now automatically adds ``[[clang::lifetimebound]]`` to the parameters of
- ``std::span, std::string_view`` constructors, this enables Clang to capture
- more cases where the returned reference outlives the object.
- (#GH100567)
-
-- Clang now correctly diagnoses the use of ``btf_type_tag`` in C++ and ignores
- it; this attribute is a C-only attribute, and caused crashes with template
- instantiation by accidentally allowing it in C++ in some circumstances.
- (#GH106864)
-
-- Introduced a new attribute ``[[clang::coro_await_elidable]]`` on coroutine return types
- to express elideability at call sites where the coroutine is invoked under a safe elide context.
-
-- Introduced a new attribute ``[[clang::coro_await_elidable_argument]]`` on function parameters
- to propagate safe elide context to arguments if such function is also under a safe elide context.
-
-- The documentation of the ``[[clang::musttail]]`` attribute was updated to
- note that the lifetimes of all local variables end before the call. This does
- not change the behaviour of the compiler, as this was true for previous
- versions.
-
-- Fix a bug where clang doesn't automatically apply the ``[[gsl::Owner]]`` or
- ``[[gsl::Pointer]]`` to STL explicit template specialization decls. (#GH109442)
-
-- Clang now supports ``[[clang::lifetime_capture_by(X)]]``. Similar to lifetimebound, this can be
- used to specify when a reference to a function parameter is captured by another capturing entity ``X``.
-
-- The ``target_version`` attribute is now only supported for AArch64 and RISC-V architectures.
-
-- Clang now permits the usage of the placement new operator in ``[[msvc::constexpr]]``
- context outside of the std namespace. (#GH74924)
-
-- Clang now disallows the use of attributes after the namespace name. (#GH121407)
+- The ``no_sanitize`` attribute now accepts both ``gnu`` and ``clang`` names.
+- Clang now diagnoses use of declaration attributes on void parameters. (#GH108819)
Improvements to Clang's diagnostics
-----------------------------------
-- Some template related diagnostics have been improved.
-
- .. code-block:: c++
-
- void foo() { template int i; } // error: templates can only be declared in namespace or class scope
-
- struct S {
- template int i; // error: non-static data member 'i' cannot be declared as a template
- };
-
-- Clang now has improved diagnostics for functions with explicit 'this' parameters. Fixes #GH97878
-
-- Clang now diagnoses dangling references to fields of temporary objects. Fixes #GH81589.
-
-- Clang now diagnoses undefined behavior in constant expressions more consistently. This includes invalid shifts, and signed overflow in arithmetic.
-
-- -Wdangling-assignment-gsl is enabled by default.
-- Clang now always preserves the template arguments as written used
- to specialize template type aliases.
-
-- Clang now diagnoses the use of ``main`` in an ``extern`` context as invalid according to [basic.start.main] p3. Fixes #GH101512.
-
-- Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391.
-
-- Clang now properly explains the reason a template template argument failed to
- match a template template parameter, in terms of the C++17 relaxed matching rules
- instead of the old ones.
-
-- Don't emit duplicated dangling diagnostics. (#GH93386).
-
-- Improved diagnostic when trying to befriend a concept. (#GH45182).
-
-- Added the ``-Winvalid-gnu-asm-cast`` diagnostic group to control warnings
- about use of "noop" casts for lvalues (a GNU extension). This diagnostic is
- a warning which defaults to being an error, is enabled by default, and is
- also controlled by the now-deprecated ``-fheinous-gnu-extensions`` flag.
-
-- Added the ``-Wdecls-in-multiple-modules`` option to assist users to identify
- multiple declarations in different modules, which is the major reason of the slow
- compilation speed with modules. This warning is disabled by default and it needs
- to be explicitly enabled or by ``-Weverything``.
-
-- Improved diagnostic when trying to overload a function in an ``extern "C"`` context. (#GH80235)
-
-- Clang now respects lifetimebound attribute for the assignment operator parameter. (#GH106372).
-
-- The lifetimebound and GSL analysis in clang are coherent, allowing clang to
- detect more use-after-free bugs. (#GH100549).
-
-- Clang now diagnoses dangling cases where a gsl-pointer is constructed from a gsl-owner object inside a container (#GH100384).
-
-- Clang now warns for u8 character literals used in C23 with ``-Wpre-c23-compat`` instead of ``-Wpre-c++17-compat``.
-
-- Clang now diagnose when importing module implementation partition units in module interface units.
-
-- Don't emit bogus dangling diagnostics when ``[[gsl::Owner]]`` and `[[clang::lifetimebound]]` are used together (#GH108272).
-
-- Don't emit bogus dignostic about an undefined behavior on ``reinterpret_cast`` for non-instantiated template functions without sufficient knowledge whether it can actually lead to undefined behavior for ``T`` (#GH109430).
-
-- The ``-Wreturn-stack-address`` warning now also warns about addresses of
- local variables passed to function calls using the ``[[clang::musttail]]``
- attribute.
-
-- Clang now diagnoses cases where a dangling ``GSLOwner`` object is constructed, e.g. ``std::vector v = {std::string()};`` (#GH100526).
-
-- Clang now diagnoses when a ``requires`` expression has a local parameter of void type, aligning with the function parameter (#GH109831).
-
-- Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638).
-
-- Clang now omits warnings for extra parentheses in fold expressions with single expansion (#GH101863).
-
-- The warning for an unsupported type for a named register variable is now phrased ``unsupported type for named register variable``,
- instead of ``bad type for named register variable``. This makes it clear that the type is not supported at all, rather than being
- suboptimal in some way the error fails to mention (#GH111550).
-
-- Clang now emits a ``-Wdepredcated-literal-operator`` diagnostic, even if the
- name was a reserved name, which we improperly allowed to suppress the
- diagnostic.
-
-- Clang now diagnoses ``[[deprecated]]`` attribute usage on local variables (#GH90073).
-
-- Fix false positives when `[[gsl::Owner/Pointer]]` and `[[clang::lifetimebound]]` are used together.
-
-- Improved diagnostic message for ``__builtin_bit_cast`` size mismatch (#GH115870).
-
-- Clang now omits shadow warnings for enum constants in separate class scopes (#GH62588).
-
-- When diagnosing an unused return value of a type declared ``[[nodiscard]]``, the type
- itself is now included in the diagnostic.
-
-- Clang will now prefer the ``[[nodiscard]]`` declaration on function declarations over ``[[nodiscard]]``
- declaration on the return type of a function. Previously, when both have a ``[[nodiscard]]`` declaration attached,
- the one on the return type would be preferred. This may affect the generated warning message:
-
- .. code-block:: c++
-
- struct [[nodiscard("Reason 1")]] S {};
- [[nodiscard("Reason 2")]] S getS();
- void use()
- {
- getS(); // Now diagnoses "Reason 2", previously diagnoses "Reason 1"
- }
-
-- Clang now diagnoses ``= delete("reason")`` extension warnings only in pedantic mode rather than on by default. (#GH109311).
-
-- Clang now diagnoses missing return value in functions containing ``if consteval`` (#GH116485).
-
-- Clang now correctly recognises code after a call to a ``[[noreturn]]`` constructor
- as unreachable (#GH63009).
-
-- Clang now omits shadowing warnings for parameter names in explicit object member functions (#GH95707).
-
-- Improved error recovery for function call arguments with trailing commas (#GH100921).
-
-- For an rvalue reference bound to a temporary struct with an integer member, Clang will detect constant integer overflow
- in the initializer for the integer member (#GH46755).
-
-- Fixed a false negative ``-Wunused-private-field`` diagnostic when a defaulted comparison operator is defined out of class (#GH116961).
-
-- Clang now diagnoses dangling references for C++20's parenthesized aggregate initialization (#101957).
-
-- Fixed a bug where Clang would not emit ``-Wunused-private-field`` warnings when an unrelated class
- defined a defaulted comparison operator (#GH116270).
-
- .. code-block:: c++
-
- class A {
- private:
- int a; // warning: private field 'a' is not used, no diagnostic previously
- };
-
- class C {
- bool operator==(const C&) = default;
- };
-
-- Clang now emits `-Wdangling-capture` diangostic when a STL container captures a dangling reference.
-
- .. code-block:: c++
-
- void test() {
- std::vector views;
- views.push_back(std::string("123")); // warning
- }
-
-- Clang now emits a ``-Wtautological-compare`` diagnostic when a check for
- pointer addition overflow is always true or false, because overflow would
- be undefined behavior.
-
- .. code-block:: c++
-
- bool incorrect_overflow_check(const char *ptr, size_t index) {
- return ptr + index < ptr; // warning
- }
-
-- Clang now emits a ``-Wvarargs`` diagnostic when the second argument
- to ``va_arg`` is of array type, which is an undefined behavior (#GH119360).
-
- .. code-block:: c++
-
- void test() {
- va_list va;
- va_arg(va, int[10]); // warning
- }
-
-- Fix -Wdangling false positives on conditional operators (#120206).
-
-- Fixed a bug where Clang hung on an unsupported optional scope specifier ``::`` when parsing
- Objective-C. Clang now emits a diagnostic message instead of hanging.
-
-- The :doc:`ThreadSafetyAnalysis` now supports passing scoped capabilities into functions:
- an attribute on the scoped capability parameter indicates both the expected associated capabilities and,
- like in the case of attributes on the function declaration itself, their state before and after the call.
-
- .. code-block:: c++
-
- #include "mutex.h"
-
- Mutex mu1, mu2;
- int a GUARDED_BY(mu1);
-
- void require(MutexLocker& scope REQUIRES(mu1)) {
- scope.Unlock();
- a = 0; // Warning! Requires mu1.
- scope.Lock();
- }
-
- void testParameter() {
- MutexLocker scope(&mu1), scope2(&mu2);
- require(scope2); // Warning! Mutex managed by 'scope2' is 'mu2' instead of 'mu1'
- require(scope); // OK.
- scope.Unlock();
- require(scope); // Warning! Requires mu1.
- }
-- Diagnose invalid declarators in the declaration of constructors and destructors (#GH121706).
-
-- Fix false positives warning for non-std functions with name `infinity` (#123231).
-
-- Clang now emits a ``-Wignored-qualifiers`` diagnostic when a base class includes cv-qualifiers (#GH55474).
-
-- Clang now diagnoses the use of attribute names reserved by the C++ standard (#GH92196).
+- Improve the diagnostics for deleted default constructor errors for C++ class
+ initializer lists that don't explicitly list a class member and thus attempt
+ to implicitly default construct that member.
+- The ``-Wunique-object-duplication`` warning has been added to warn about objects
+ which are supposed to only exist once per program, but may get duplicated when
+ built into a shared library.
+- Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
+- A statement attribute applied to a ``case`` label no longer suppresses
+ 'bypassing variable initialization' diagnostics (#84072).
Improvements to Clang's time-trace
----------------------------------
@@ -827,365 +145,78 @@ Improvements to Coverage Mapping
Bug Fixes in This Version
-------------------------
-- Fixed the definition of ``ATOMIC_FLAG_INIT`` in ```` so it can
- be used in C++.
-- Fixed a failed assertion when checking required literal types in C context. (#GH101304).
-- Fixed a crash when trying to transform a dependent address space type. Fixes #GH101685.
-- Fixed a crash when diagnosing format strings and encountering an empty
- delimited escape sequence (e.g., ``"\o{}"``). #GH102218
-- Fixed a crash using ``__array_rank`` on 64-bit targets. (#GH113044).
-- The warning emitted for an unsupported register variable type now points to
- the unsupported type instead of the ``register`` keyword (#GH109776).
-- Fixed a crash when emit ctor for global variant with flexible array init (#GH113187).
-- Fixed a crash when GNU statement expression contains invalid statement (#GH113468).
-- Fixed a crash when passing the variable length array type to ``va_arg`` (#GH119360).
-- Fixed a failed assertion when using ``__attribute__((noderef))`` on an
- ``_Atomic``-qualified type (#GH116124).
-- No longer incorrectly diagnosing use of a deleted destructor when the
- selected overload of ``operator delete`` for that type is a destroying delete
- (#GH46818).
-- No longer return ``false`` for ``noexcept`` expressions involving a
- ``delete`` which resolves to a destroying delete but the type of the object
- being deleted has a potentially throwing destructor (#GH118660).
-
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fix crash when atomic builtins are called with pointer to zero-size struct (#GH90330)
-
-- Clang now allows pointee types of atomic builtin arguments to be complete template types
- that was not instantiated elsewhere.
-
-- ``__noop`` can now be used in a constant expression. (#GH102064)
-
-- Fix ``__has_builtin`` incorrectly returning ``false`` for some C++ type traits. (#GH111477)
-
-- Fix ``__builtin_source_location`` incorrectly returning wrong column for method chains. (#GH119129)
+- The behvaiour of ``__add_pointer`` and ``__remove_pointer`` for Objective-C++'s ``id`` and interfaces has been fixed.
Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ - Fixed crash when a parameter to the ``clang::annotate`` attribute evaluates to ``void``. See #GH119125
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed a crash when an expression with a dependent ``__typeof__`` type is used as the operand of a unary operator. (#GH97646)
-- Fixed incorrect pack expansion of init-capture references in requires expresssions.
-- Fixed a failed assertion when checking invalid delete operator declaration. (#GH96191)
-- Fix a crash when checking destructor reference with an invalid initializer. (#GH97230)
-- Clang now correctly parses potentially declarative nested-name-specifiers in pointer-to-member declarators.
-- Fix a crash when checking the initializer of an object that was initialized
- with a string literal. (#GH82167)
-- Fix a crash when matching template template parameters with templates which have
- parameters of different class type. (#GH101394)
-- Clang now correctly recognizes the correct context for parameter
- substitutions in concepts, so it doesn't incorrectly complain of missing
- module imports in those situations. (#GH60336)
-- Fix init-capture packs having a size of one before being instantiated. (#GH63677)
-- Clang now preserves the unexpanded flag in a lambda transform used for pack expansion. (#GH56852), (#GH85667),
- (#GH99877), (#GH122417).
-- Fixed a bug when diagnosing ambiguous explicit specializations of constrained member functions.
-- Fixed an assertion failure when selecting a function from an overload set that includes a
- specialization of a conversion function template.
-- Correctly diagnose attempts to use a concept name in its own definition;
- A concept name is introduced to its scope sooner to match the C++ standard. (#GH55875)
-- Properly reject defaulted relational operators with invalid types for explicit object parameters,
- e.g., ``bool operator==(this int, const Foo&)`` (#GH100329), and rvalue reference parameters.
-- Properly reject defaulted copy/move assignment operators that have a non-reference explicit object parameter.
-- Clang now properly handles the order of attributes in `extern` blocks. (#GH101990).
-- Fixed an assertion failure by preventing null explicit object arguments from being deduced. (#GH102025).
-- Correctly check constraints of explicit instantiations of member functions. (#GH46029)
-- When performing partial ordering of function templates, clang now checks that
- the deduction was consistent. Fixes (#GH18291).
-- Fixes to several issues in partial ordering of template template parameters, which
- were documented in the test suite.
-- Fixed an assertion failure about a constraint of a friend function template references to a value with greater
- template depth than the friend function template. (#GH98258)
-- Clang now rebuilds the template parameters of out-of-line declarations and specializations in the context
- of the current instantiation in all cases.
-- Fix evaluation of the index of dependent pack indexing expressions/types specifiers (#GH105900)
-- Correctly handle subexpressions of an immediate invocation in the presence of implicit casts. (#GH105558)
-- Clang now correctly handles direct-list-initialization of a structured bindings from an array. (#GH31813)
-- Mangle placeholders for deduced types as a template-prefix, such that mangling
- of template template parameters uses the correct production. (#GH106182)
-- Fixed an assertion failure when converting vectors to int/float with invalid expressions. (#GH105486)
-- Template parameter names are considered in the name lookup of out-of-line class template
- specialization right before its declaration context. (#GH64082)
-- Fixed a constraint comparison bug for friend declarations. (#GH78101)
-- Fix handling of ``_`` as the name of a lambda's init capture variable. (#GH107024)
-- Fix an issue with dependent source location expressions (#GH106428), (#GH81155), (#GH80210), (#GH85373)
-- Fixed a bug in the substitution of empty pack indexing types. (#GH105903)
-- Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048)
-- Fixed a bug where defaulted comparison operators would remove ``const`` from base classes. (#GH102588)
-- Fix a crash when using ``source_location`` in the trailing return type of a lambda expression. (#GH67134)
-- A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361), (#GH112352)
-- Fixed a crash in the typo correction of an invalid CTAD guide. (#GH107887)
-- Fixed a crash when clang tries to substitute parameter pack while retaining the parameter
- pack. (#GH63819), (#GH107560)
-- Fix a crash when a static assert declaration has an invalid close location. (#GH108687)
-- Avoided a redundant friend declaration instantiation under a certain ``consteval`` context. (#GH107175)
-- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
- diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
-- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
-- Fixed a crash when mixture of designated and non-designated initializers in union. (#GH113855)
-- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
-- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
- containing outer unexpanded parameters were not correctly expanded. (#GH101754)
-- Fixes crashes with function template member specializations, and increases
- conformance of explicit instantiation behaviour with MSVC. (#GH111266)
-- Fixed a bug in constraint expression comparison where the ``sizeof...`` expression was not handled properly
- in certain friend declarations. (#GH93099)
-- Clang now instantiates the correct lambda call operator when a lambda's class type is
- merged across modules. (#GH110401)
-- Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460)
-- Fixed an assertion failure when invoking recovery call expressions with explicit attributes
- and undeclared templates. (#GH107047), (#GH49093)
-- Clang no longer crashes when a lambda contains an invalid block declaration that contains an unexpanded
- parameter pack. (#GH109148)
-- Fixed overload handling for object parameters with top-level cv-qualifiers in explicit member functions (#GH100394)
-- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in
- certain situations. (#GH47400), (#GH90896)
-- Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441)
-- During the lookup for a base class name, non-type names are ignored. (#GH16855)
-- Fix a crash when recovering an invalid expression involving an explicit object member conversion operator. (#GH112559)
-- Clang incorrectly considered a class with an anonymous union member to not be
- const-default-constructible even if a union member has a default member initializer.
- (#GH95854).
-- Fixed an assertion failure when evaluating an invalid expression in an array initializer. (#GH112140)
-- Fixed an assertion failure in range calculations for conditional throw expressions. (#GH111854)
-- Clang now correctly ignores previous partial specializations of member templates explicitly specialized for
- an implicitly instantiated class template specialization. (#GH51051)
-- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
-- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
-- Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the
- assumption if they also occur inside of a dependent lambda. (#GH114787)
-- Lambdas now capture function types without considering top-level const qualifiers. (#GH84961)
-- Clang now uses valid deduced type locations when diagnosing functions with trailing return type
- missing placeholder return type. (#GH78694)
-- Fixed a bug where bounds of partially expanded pack indexing expressions were checked too early. (#GH116105)
-- Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385)
-- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
- friend declarations. (#GH113324)
-- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
-- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072)
-- Fixed a null pointer dereference issue when heuristically computing ``sizeof...(pack)`` expressions. (#GH81436)
-- Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205)
-- Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda
- captures at the end of a full expression. (#GH115931)
-- Clang no longer rejects deleting a pointer of incomplete enumeration type. (#GH99278)
-- Fixed recognition of ``std::initializer_list`` when it's surrounded with ``extern "C++"`` and exported
- out of a module (which is the case e.g. in MSVC's implementation of ``std`` module). (#GH118218)
-- Fixed a pack expansion issue in checking unexpanded parameter sizes. (#GH17042)
-- Fixed a bug where captured structured bindings were modifiable inside non-mutable lambda (#GH95081)
-- Passing incomplete types to ``__is_base_of`` and other builtin type traits for which the corresponding
- standard type trait mandates a complete type is now a hard (non-sfinae-friendly) error
- (`LWG3929 `__.) (#GH121278)
-- Clang now identifies unexpanded parameter packs within the type constraint on a non-type template parameter. (#GH88866)
-- Fixed an issue while resolving type of expression indexing into a pack of values of non-dependent type (#GH121242)
-- Fixed a crash when __PRETTY_FUNCTION__ or __FUNCSIG__ (clang-cl) appears in the trailing return type of the lambda (#GH121274)
-- Fixed a crash caused by the incorrect construction of template arguments for CTAD alias guides when type
- constraints are applied. (#GH122134)
-- Fixed canonicalization of pack indexing types - Clang did not always recognized identical pack indexing. (#GH123033)
-- Fixed a nested lambda substitution issue for constraint evaluation. (#GH123441)
-- Fixed various false diagnostics related to the use of immediate functions. (#GH123472)
-- Fix immediate escalation not propagating through inherited constructors. (#GH112677)
-- Fixed assertions or false compiler diagnostics in the case of C++ modules for
- lambda functions or inline friend functions defined inside templates (#GH122493).
+- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
+- The initialization kind of elements of structured bindings
+ direct-list-initialized from an array is corrected to direct-initialization.
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed a crash that occurred when dividing by zero in complex integer division. (#GH55390).
-- Fixed a bug in ``ASTContext::getRawCommentForAnyRedecl()`` where the function could
- sometimes incorrectly return null even if a comment was present. (#GH108145)
-- Clang now correctly parses the argument of the ``relates``, ``related``, ``relatesalso``,
- and ``relatedalso`` comment commands.
-- Clang now uses the location of the begin of the member expression for ``CallExpr``
- involving deduced ``this``. (#GH116928)
-- Fixed printout of AST that uses pack indexing expression. (#GH116486)
-
Miscellaneous Bug Fixes
^^^^^^^^^^^^^^^^^^^^^^^
+- HTML tags in comments that span multiple lines are now parsed correctly by Clang's comment parser. (#GH120843)
+
Miscellaneous Clang Crashes Fixed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed a crash in C due to incorrect lookup that members in nested anonymous struct/union
- can be found as ordinary identifiers in struct/union definition. (#GH31295)
-
-- Fixed a crash caused by long chains of ``sizeof`` and other similar operators
- that can be followed by a non-parenthesized expression. (#GH45061)
-
-- Fixed an crash when compiling ``#pragma STDC FP_CONTRACT DEFAULT`` with
- ``-ffp-contract=fast-honor-pragmas``. (#GH104830)
-
-- Fixed a crash when function has more than 65536 parameters.
- Now a diagnostic is emitted. (#GH35741)
-
-- Fixed ``-ast-dump`` crashes on codes involving ``concept`` with ``-ast-dump-decl-types``. (#GH94928)
-
-- Fixed internal assertion firing when a declaration in the implicit global
- module is found through ADL. (GH#109879)
-
-- Fixed a crash when an unscoped enumeration declared by an opaque-enum-declaration within a class template
- with a dependent underlying type is subject to integral promotion. (#GH117960)
-
OpenACC Specific Changes
------------------------
Target Specific Changes
-----------------------
-- Clang now implements the Solaris-specific mangling of ``std::tm`` as
- ``tm``, same for ``std::div_t``, ``std::ldiv_t``, and
- ``std::lconv``, for Solaris ABI compatibility. (#GH33114)
-
AMDGPU Support
^^^^^^^^^^^^^^
-- Initial support for gfx950
-
-- Added headers ``gpuintrin.h`` and ``amdgpuintrin.h`` that contains common
- definitions for GPU builtin functions. This header can be included for OpenMP,
- CUDA, HIP, OpenCL, and C/C++.
-
NVPTX Support
^^^^^^^^^^^^^^
-- Added headers ``gpuintrin.h`` and ``nvptxintrin.h`` that contains common
- definitions for GPU builtin functions. This header can be included for OpenMP,
- CUDA, HIP, OpenCL, and C/C++.
+Hexagon Support
+^^^^^^^^^^^^^^^
+
+- The default compilation target has been changed from V60 to V68.
X86 Support
^^^^^^^^^^^
-- The MMX vector intrinsic functions from ``*mmintrin.h`` which
- operate on `__m64` vectors, such as ``_mm_add_pi8``, have been
- reimplemented to use the SSE2 instruction-set and XMM registers
- unconditionally. These intrinsics are therefore *no longer
- supported* if MMX is enabled without SSE2 -- either from targeting
- CPUs from the Pentium-MMX through the Pentium 3, or explicitly via
- passing arguments such as ``-mmmx -mno-sse2``. MMX assembly code
- remains supported without requiring SSE2, including inside
- inline-assembly.
-
-- The compiler builtins such as ``__builtin_ia32_paddb`` which
- formerly implemented the above MMX intrinsic functions have been
- removed. Any uses of these removed functions should migrate to the
- functions defined by the ``*mmintrin.h`` headers. A mapping can be
- found in the file ``clang/www/builtins.py``.
-
-- Support ISA of ``AVX10.2``.
- * Supported MINMAX intrinsics of ``*_(mask(z)))_minmax(ne)_p[s|d|h|bh]`` and
- ``*_(mask(z)))_minmax_s[s|d|h]``.
-
-- Supported intrinsics for ``SM4 and AVX10.2``.
- * Supported SM4 intrinsics of ``_mm512_sm4key4_epi32`` and
- ``_mm512_sm4rnds4_epi32``.
-
-- All intrinsics in adcintrin.h can now be used in constant expressions.
-
-- All intrinsics in adxintrin.h can now be used in constant expressions.
-
-- All intrinsics in lzcntintrin.h can now be used in constant expressions.
-
-- All intrinsics in bmiintrin.h can now be used in constant expressions.
-
-- All intrinsics in bmi2intrin.h can now be used in constant expressions.
-
-- All intrinsics in tbmintrin.h can now be used in constant expressions.
-
-- Supported intrinsics for ``MOVRS AND AVX10.2``.
- * Supported intrinsics of ``_mm(256|512)_(mask(z))_loadrs_epi(8|16|32|64)``.
-- Support ISA of ``AMX-FP8``.
-- Support ISA of ``AMX-TRANSPOSE``.
-- Support ISA of ``AMX-MOVRS``.
-- Support ISA of ``AMX-AVX512``.
-- Support ISA of ``AMX-TF32``.
-- Support ISA of ``MOVRS``.
-
-- Supported ``-march/tune=diamondrapids``
+- Disable ``-m[no-]avx10.1`` and switch ``-m[no-]avx10.2`` to alias of 512 bit
+ options.
+- Change ``-mno-avx10.1-512`` to alias of ``-mno-avx10.1-256`` to disable both
+ 256 and 512 bit instructions.
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^
-- Implementation of SVE2.1 and SME2.1 in accordance with the Arm C Language
- Extensions (ACLE) is now available.
-
-- In the ARM Target, the frame pointer (FP) of a leaf function can be retained
- by using the ``-fno-omit-frame-pointer`` option. If you want to eliminate the FP
- in leaf functions after enabling ``-fno-omit-frame-pointer``, you can do so by adding
- the ``-momit-leaf-frame-pointer`` option.
-
-- SME keyword attributes which apply to function types are now represented in the
- mangling of the type. This means that ``void foo(void (*f)() __arm_streaming);``
- now has a different mangling from ``void foo(void (*f)());``.
-
-- The ``__arm_agnostic`` keyword attribute was added to let users describe
- a function that preserves SME state enabled by PSTATE.ZA without having to share
- this state with its callers and without making the assumption that this state
- exists.
-
-- Support has been added for the following processors (-mcpu identifiers in parenthesis):
-
- For AArch64:
-
- * FUJITSU-MONAKA (fujitsu-monaka)
-
Android Support
^^^^^^^^^^^^^^^
Windows Support
^^^^^^^^^^^^^^^
-- clang-cl now supports ``/std:c++23preview`` which enables C++23 features.
-
-- Clang no longer allows references inside a union when emulating MSVC 1900+ even if `fms-extensions` is enabled.
- Starting with VS2015, MSVC 1900, this Microsoft extension is no longer allowed and always results in an error.
- Clang now follows the MSVC behavior in this scenario.
- When `-fms-compatibility-version=18.00` or prior is set on the command line this Microsoft extension is still
- allowed as VS2013 and prior allow it.
-
-- Clang now supports the ``#pragma clang section`` directive for COFF targets.
-
LoongArch Support
^^^^^^^^^^^^^^^^^
-- Types of parameters and return value of ``__builtin_lsx_vorn_v`` and ``__builtin_lasx_xvorn_v``
- are changed from ``signed char`` to ``unsigned char``. (#GH114514)
-
-- ``-mrelax`` and ``-mno-relax`` are supported now on LoongArch that can be used
- to enable / disable the linker relaxation optimization. (#GH123587)
-
-- Fine-grained la64v1.1 options are added including ``-m{no-,}frecipe``, ``-m{no-,}lam-bh``,
- ``-m{no-,}ld-seq-sa``, ``-m{no-,}div32``, ``-m{no-,}lamcas`` and ``-m{no-,}scq``.
-
-- Two options ``-m{no-,}annotate-tablejump`` are added to enable / disable
- annotating table jump instruction to correlate it with the jump table. (#GH102411)
-
-- FreeBSD support is added for LoongArch64 and has been tested by building kernel-toolchain. (#GH119191)
-
RISC-V Support
^^^^^^^^^^^^^^
-- The option ``-mcmodel=large`` for the large code model is supported.
-- Bump RVV intrinsic to version 1.0, the spec: https://github.com/riscv-non-isa/rvv-intrinsic-doc/releases/tag/v1.0.0-rc4
-
CUDA/HIP Language Changes
^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed a bug about overriding a constexpr pure-virtual member function with a non-constexpr virtual member function which causes compilation failure when including standard C++ header `format`.
-- Added initial support for version 3 of the compressed offload bundle format, which uses 64-bit fields for Total File Size and Uncompressed Binary Size. This enables support for files larger than 4GB. The support is currently experimental and can be enabled by setting the environment variable `COMPRESSED_BUNDLE_FORMAT_VERSION=3`.
CUDA Support
^^^^^^^^^^^^
-- Clang now supports CUDA SDK up to 12.6
-- Added support for sm_100
-- Added support for `__grid_constant__` attribute.
-- CUDA now uses the new offloading driver by default. The new driver supports
- device-side LTO, interoperability with OpenMP and other languages, and native ``-fgpu-rdc``
- support with static libraries. The old behavior can be returned using the
- ``--no-offload-new-driver`` flag. The binary format is no longer compatible
- with the NVIDIA compiler's RDC-mode support. More information can be found at:
- https://clang.llvm.org/docs/OffloadingDesign.html
AIX Support
^^^^^^^^^^^
@@ -1196,276 +227,73 @@ NetBSD Support
WebAssembly Support
^^^^^^^^^^^^^^^^^^^
-The default target CPU, "generic", now enables the `-mnontrapping-fptoint`
-and `-mbulk-memory` flags, which correspond to the [Bulk Memory Operations]
-and [Non-trapping float-to-int Conversions] language features, which are
-[widely implemented in engines].
-
-A new Lime1 target CPU is added, -mcpu=lime1. This CPU follows the definition of
-the Lime1 CPU [here], and enables -mmultivalue, -mmutable-globals,
--mcall-indirect-overlong, -msign-ext, -mbulk-memory-opt, -mnontrapping-fptoint,
-and -mextended-const.
-
-[Bulk Memory Operations]: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md
-[Non-trapping float-to-int Conversions]: https://github.com/WebAssembly/spec/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
-[widely implemented in engines]: https://webassembly.org/features/
-[here]: https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1
-
AVR Support
^^^^^^^^^^^
-- Reject C/C++ compilation for avr1 devices which have no SRAM.
-
DWARF Support in Clang
----------------------
Floating Point Support in Clang
-------------------------------
-- Add ``__builtin_elementwise_atan2`` builtin for floating point types only.
-
Fixed Point Support in Clang
----------------------------
AST Matchers
------------
-- Fixed an issue with the `hasName` and `hasAnyName` matcher when matching
- inline namespaces with an enclosing namespace of the same name.
-
-- Fixed an ordering issue with the `hasOperands` matcher occurring when setting a
- binding in the first matcher and using it in the second matcher.
-
-- Fixed a crash when traverse lambda expr with invalid captures. (#GH106444)
-
-- Fixed ``isInstantiated`` and ``isInTemplateInstantiation`` to also match for variable templates. (#GH110666)
-
-- Ensure ``hasName`` matches template specializations across inline namespaces,
- making `matchesNodeFullSlow` and `matchesNodeFullFast` consistent.
-
-- Improved the performance of the ``getExpansionLocOfMacro`` by tracking already processed macros during recursion.
-
-- Add ``exportDecl`` matcher to match export declaration.
-
-- Ensure ``hasType`` and ``hasDeclaration`` match Objective-C interface declarations.
-
-- Ensure ``pointee`` matches Objective-C pointer types.
-
-- Add ``dependentScopeDeclRefExpr`` matcher to match expressions that refer to dependent scope declarations.
-
-- Add ``dependentNameType`` matcher to match a dependent name type.
-
-- Add ``dependentTemplateSpecializationType`` matcher to match a dependent template specialization type.
-
-- Add ``hasDependentName`` matcher to match the dependent name of a DependentScopeDeclRefExpr or DependentNameType.
-
clang-format
------------
-- Adds ``BreakBinaryOperations`` option.
-- Adds ``TemplateNames`` option.
-- Adds ``AlignFunctionDeclarations`` option to ``AlignConsecutiveDeclarations``.
-- Adds ``IndentOnly`` suboption to ``ReflowComments`` to fix the indentation of
- multi-line comments without touching their contents, renames ``false`` to
- ``Never``, and ``true`` to ``Always``.
-- Adds ``RemoveEmptyLinesInUnwrappedLines`` option.
-- Adds ``KeepFormFeed`` option and set it to ``true`` for ``GNU`` style.
-- Adds ``AllowShortNamespacesOnASingleLine`` option.
-- Adds ``VariableTemplates`` option.
-- Adds support for bash globstar in ``.clang-format-ignore``.
-- Adds ``WrapNamespaceBodyWithEmptyLines`` option.
-- Adds the ``IndentExportBlock`` option.
+- Adds ``BreakBeforeTemplateCloser`` option.
+- Adds ``BinPackLongBracedList`` option to override bin packing options in
+ long (20 item or more) braced list initializer lists.
libclang
--------
-- Add ``clang_isBeforeInTranslationUnit``. Given two source locations, it determines
- whether the first one comes strictly before the second in the source code.
-- Add ``clang_getTypePrettyPrinted``. It allows controlling the PrintingPolicy used
- to pretty-print a type.
-- Added ``clang_visitCXXBaseClasses``, which allows visiting the base classes
- of a class.
-- Added ``clang_getOffsetOfBase``, which allows computing the offset of a base
- class in a class's layout.
-
Code Completion
---------------
-- Use ``HeuristicResolver`` (upstreamed from clangd) to improve code completion results
- in dependent code
-
Static Analyzer
---------------
New features
^^^^^^^^^^^^
-- Now CSA models `__builtin_*_overflow` functions. (#GH102602)
-
-- MallocChecker now checks for ``ownership_returns(class, idx)`` and ``ownership_takes(class, idx)``
- attributes with class names different from "malloc". Clang static analyzer now reports an error
- if class of allocation and deallocation function mismatches.
- `Documentation `__.
-
-- Function effects, e.g. the ``nonblocking`` and ``nonallocating`` "performance constraint"
- attributes, are now verified. For example, for functions declared with the ``nonblocking``
- attribute, the compiler can generate warnings about the use of any language features, or calls to
- other functions, which may block.
-
-- Introduced ``-warning-suppression-mappings`` flag to control diagnostic
- suppressions per file. See `documentation _` for details.
+A new flag - `-static-libclosure` was introduced to support statically linking
+the runtime for the Blocks extension on Windows. This flag currently only
+changes the code generation, and even then, only on Windows. This does not
+impact the linker behaviour like the other `-static-*` flags.
Crash and bug fixes
^^^^^^^^^^^^^^^^^^^
-- In loops where the loop condition is opaque (i.e. the analyzer cannot
- determine whether it's true or false), the analyzer will no longer assume
- execution paths that perform more that two iterations. These unjustified
- assumptions caused false positive reports (e.g. 100+ out-of-bounds reports in
- the FFMPEG codebase) in loops where the programmer intended only two or three
- steps but the analyzer wasn't able to understand that the loop is limited.
-
Improvements
^^^^^^^^^^^^
-- Improved the handling of the ``ownership_returns`` attribute. Now, Clang reports an
- error if the attribute is attached to a function that returns a non-pointer value.
- Fixes (#GH99501)
-
Moved checkers
^^^^^^^^^^^^^^
-- The checker ``alpha.core.IdenticalExpr`` was deleted because it was
- duplicated in the clang-tidy checkers ``misc-redundant-expression`` and
- ``bugprone-branch-clone``.
-
-- The checker ``alpha.security.MallocOverflow`` was deleted because it was
- badly implemented and its aggressive logic produced too many false positives.
- To detect too large arguments passed to malloc, consider using the checker
- ``alpha.taint.TaintedAlloc``.
-
-- The checkers ``alpha.nondeterministic.PointerSorting`` and
- ``alpha.nondeterministic.PointerIteration`` were moved to a new bugprone
- checker named ``bugprone-nondeterministic-pointer-iteration-order``. The
- original checkers were implemented only using AST matching and make more
- sense as a single clang-tidy check.
-
-- The checker ``alpha.unix.Chroot`` was modernized, improved and moved to
- ``unix.Chroot``. Testing was done on open source projects that use chroot(),
- and false issues addressed in the improvements based on real use cases. Open
- source projects used for testing include nsjail, lxroot, dive and ruri.
- This checker conforms to SEI Cert C recommendation `POS05-C. Limit access to
- files by creating a jail
- `_.
- Fixes (#GH34697).
- (#GH117791) [Documentation](https://clang.llvm.org/docs/analyzer/checkers.html#unix-chroot-c).
+- After lots of improvements, the checker ``alpha.security.ArrayBoundV2`` is
+ renamed to ``security.ArrayBound``. As this checker is stable now, the old
+ checker ``alpha.security.ArrayBound`` (which was searching for the same kind
+ of bugs with an different, simpler and less accurate algorithm) is removed.
.. _release-notes-sanitizers:
Sanitizers
----------
-- Introduced Realtime Sanitizer, activated by using the -fsanitize=realtime
- flag. This sanitizer detects unsafe system library calls, such as memory
- allocations and mutex locks. If any such function is called during invocation
- of a function marked with the ``[[clang::nonblocking]]`` attribute, an error
- is printed to the console and the process exits non-zero.
-
-- Added the ``-fsanitize-undefined-ignore-overflow-pattern`` flag which can be
- used to disable specific overflow-dependent code patterns. The supported
- patterns are: ``add-signed-overflow-test``, ``add-unsigned-overflow-test``,
- ``negated-unsigned-const``, and ``unsigned-post-decr-while``. The sanitizer
- instrumentation can be toggled off for all available patterns by specifying
- ``all``. Conversely, you may disable all exclusions with ``none`` which is
- the default.
-
- .. code-block:: c++
-
- /// specified with ``-fsanitize-undefined-ignore-overflow-pattern=add-unsigned-overflow-test``
- int common_overflow_check_pattern(unsigned base, unsigned offset) {
- if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented
- }
-
- /// specified with ``-fsanitize-undefined-ignore-overflow-pattern=add-signed-overflow-test``
- int common_overflow_check_pattern_signed(signed int base, signed int offset) {
- if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented
- }
-
- /// specified with ``-fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const``
- void negation_overflow() {
- unsigned long foo = -1UL; // No longer causes a negation overflow warning
- unsigned long bar = -2UL; // and so on...
- }
-
- /// specified with ``-fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while``
- void while_post_decrement() {
- unsigned char count = 16;
- while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
- }
-
- Many existing projects have a large amount of these code patterns present.
- This new flag should allow those projects to enable integer sanitizers with
- less noise.
-
-- ``-fsanitize=signed-integer-overflow``, ``-fsanitize=unsigned-integer-overflow``,
- ``-fsanitize=implicit-signed-integer-truncation``, ``-fsanitize=implicit-unsigned-integer-truncation``,
- ``-fsanitize=enum`` now properly support the
- "type" prefix within `Sanitizer Special Case Lists (SSCL)
- `_. See that link
- for examples.
-
-- Introduced an experimental Type Sanitizer, activated by using the
- ``-fsanitize=type`` flag. This sanitizer detects violations of C/C++ type-based
- aliasing rules.
-
-- Implemented ``-f[no-]sanitize-trap=local-bounds``, and ``-f[no-]sanitize-recover=local-bounds``.
-
-- ``-fsanitize-merge`` (default) and ``-fno-sanitize-merge`` have been added for
- fine-grained, unified control of which UBSan checks can potentially be merged
- by the compiler (for example,
- ``-fno-sanitize-merge=bool,enum,array-bounds,local-bounds``).
-
-- Changed ``-fsanitize=pointer-overflow`` to no longer report ``NULL + 0`` as
- undefined behavior in C, in line with
- `N3322 `_,
- and matching the previous behavior for C++.
- ``NULL + non_zero`` continues to be reported as undefined behavior.
Python Binding Changes
----------------------
-- Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.
-- Added ``Cursor.pretty_printed``, a binding for ``clang_getCursorPrettyPrinted``,
- and related functions, which allow changing the formatting of pretty-printed code.
-- Added ``Cursor.is_anonymous_record_decl``, a binding for
- ``clang_Cursor_isAnonymousRecordDecl``, which allows checking if a
- declaration is an anonymous union or anonymous struct.
-- Added ``Type.pretty_printed`, a binding for ``clang_getTypePrettyPrinted``,
- which allows changing the formatting of pretty-printed types.
-- Added ``Cursor.is_virtual_base``, a binding for ``clang_isVirtualBase``,
- which checks whether a base class is virtual.
-- Added ``Type.get_bases``, a binding for ``clang_visitCXXBaseClasses``, which
- allows visiting the base classes of a class.
-- Added ``Cursor.get_base_offsetof``, a binding for ``clang_getOffsetOfBase``,
- which allows computing the offset of a base class in a class's layout.
OpenMP Support
--------------
-- Added support for 'omp assume' directive.
-- Added support for 'omp scope' directive.
-- Added support for allocator-modifier in 'allocate' clause.
-- Changed the OpenMP DeviceRTL to use 'generic' IR. The
- ``LIBOMPTARGET_DEVICE_ARCHITECTURES`` CMake argument is now unused and will
- always build support for AMDGPU and NVPTX targets.
-- Added support for combined masked constructs 'omp parallel masked taskloop',
- 'omp parallel masked taskloop simd','omp masked taskloop' and 'omp masked taskloop simd' directive.
-- Added support for align-modifier in 'allocate' clause.
+- Added support 'no_openmp_constructs' assumption clause.
Improvements
^^^^^^^^^^^^
-- Improve the handling of mapping array-section for struct containing nested structs with user defined mappers
-
-- `num_teams` and `thead_limit` now accept multiple expressions when it is used
- along in ``target teams ompx_bare`` construct. This allows the target region
- to be launched with multi-dim grid on GPUs.
Additional Information
======================
diff --git a/clang/docs/SourceBasedCodeCoverage.rst b/clang/docs/SourceBasedCodeCoverage.rst
index 73910e134a589..3e8642479a56d 100644
--- a/clang/docs/SourceBasedCodeCoverage.rst
+++ b/clang/docs/SourceBasedCodeCoverage.rst
@@ -94,6 +94,11 @@ directory structure will be created. Additionally, the following special
not specified (i.e the pattern is "%m"), it's assumed that ``N = 1``. The
merge pool specifier can only occur once per filename pattern.
+* "%b" expands out to the binary ID (build ID). It can be used with "%Nm" to
+ avoid binary signature collisions. To use it, the program should be compiled
+ with the build ID linker option (``--build-id`` for GNU ld or LLD,
+ ``/build-id`` for lld-link on Windows). Linux, Windows and AIX are supported.
+
* "%c" expands out to nothing, but enables a mode in which profile counter
updates are continuously synced to a file. This means that if the
instrumented program crashes, or is killed by a signal, perfect coverage
diff --git a/clang/docs/TypeSanitizer.rst b/clang/docs/TypeSanitizer.rst
new file mode 100644
index 0000000000000..3c683a6c24bb4
--- /dev/null
+++ b/clang/docs/TypeSanitizer.rst
@@ -0,0 +1,205 @@
+=============
+TypeSanitizer
+=============
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+The TypeSanitizer is a detector for strict type aliasing violations. It consists of a compiler
+instrumentation module and a run-time library. C/C++ has type-based aliasing rules, and LLVM
+can exploit these for optimizations given the TBAA metadata Clang emits. In general, a pointer
+of a given type cannot access an object of a different type, with only a few exceptions.
+
+These rules aren't always apparent to users, which leads to code that violates these rules
+(e.g. for type punning). This can lead to optimization passes introducing bugs unless the
+code is build with ``-fno-strict-aliasing``, sacrificing performance.
+
+TypeSanitizer is built to catch when these strict aliasing rules have been violated, helping
+users find where such bugs originate in their code despite the code looking valid at first glance.
+
+As TypeSanitizer is still experimental, it can currently have a large impact on runtime speed,
+memory use, and code size. It also has a large compile-time overhead. Work is being done to
+reduce these impacts.
+
+The TypeSanitizer Algorithm
+===========================
+For each TBAA type-access descriptor, encoded in LLVM IR using TBAA Metadata, the instrumentation
+pass generates descriptor tables. Thus there is a unique pointer to each type (and access descriptor).
+These tables are comdat (except for anonymous-namespace types), so the pointer values are unique
+across the program.
+
+The descriptors refer to other descriptors to form a type aliasing tree, like how LLVM's TBAA data
+does.
+
+The runtime uses 8 bytes of shadow memory, the size of the pointer to the type descriptor, for
+every byte of accessed data in the program. The first byte of a type will have its shadow memory
+be set to the pointer to its type descriptor. Aside from that, there are some other values it may be.
+
+* 0 is used to represent an unknown type
+* Negative numbers represent an interior byte: A byte inside a type that is not the first one. As an
+ example, a value of -2 means you are in the third byte of a type.
+
+The Instrumentation first checks for an exact match between the type of the current access and the
+type for that address in the shadow memory. This can quickly be done by checking pointer values. If
+it matches, it checks the remaining shadow memory of the type to ensure they are the correct negative
+numbers. If this fails, it calls the "slow path" check. If the exact match fails, we check to see if
+the value, and the remainder of the shadow bytes, is 0. If they are, we can set the shadow memory to
+the correct type descriptor pointer for the first byte, and the correct negative numbers for the rest
+of the type's shadow.
+
+If the type in shadow memory is neither an exact match nor 0, we call the slower runtime check. It
+uses the full TBAA algorithm, just as the compiler does, to determine when two types are permitted to
+alias.
+
+The instrumentation pass inserts calls to the memset intrinsic to set the memory updated by memset,
+memcpy, and memmove, as well as allocas/byval (and for lifetime.start/end) to reset the shadow memory
+to reflect that the type is now unknown. The runtime intercepts memset, memcpy, etc. to perform the
+same function for the library calls.
+
+How to build
+============
+
+Build LLVM/Clang with `CMake `_ and enable
+the ``compiler-rt`` runtime. An example CMake configuration that will allow
+for the use/testing of TypeSanitizer:
+
+.. code-block:: console
+
+ $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" /llvm
+
+Usage
+=====
+
+Compile and link your program with ``-fsanitize=type`` flag. The
+TypeSanitizer run-time library should be linked to the final executable, so
+make sure to use ``clang`` (not ``ld``) for the final link step. To
+get a reasonable performance add ``-O1`` or higher.
+TypeSanitizer by default doesn't print the full stack trace in error messages. Use ``TYSAN_OPTIONS=print_stacktrace=1``
+to print the full trace. To get nicer stack traces in error messages add ``-fno-omit-frame-pointer`` and
+``-g``. To get perfect stack traces you may need to disable inlining (just use ``-O1``) and tail call elimination
+(``-fno-optimize-sibling-calls``).
+
+.. code-block:: console
+
+ % cat example_AliasViolation.c
+ int main(int argc, char **argv) {
+ int x = 100;
+ float *y = (float*)&x;
+ *y += 2.0f; // Strict aliasing violation
+ return 0;
+ }
+
+ # Compile and link
+ % clang++ -g -fsanitize=type example_AliasViolation.cc
+
+The program will print an error message to ``stderr`` each time a strict aliasing violation is detected.
+The program won't terminate, which will allow you to detect many strict aliasing violations in one
+run.
+
+.. code-block:: console
+
+ % ./a.out
+ ==1375532==ERROR: TypeSanitizer: type-aliasing-violation on address 0x7ffeebf1a72c (pc 0x5b3b1145ff41 bp 0x7ffeebf1a660 sp 0x7ffeebf19e08 tid 1375532)
+ READ of size 4 at 0x7ffeebf1a72c with type float accesses an existing object of type int
+ #0 0x5b3b1145ff40 in main example_AliasViolation.c:4:10
+
+ ==1375532==ERROR: TypeSanitizer: type-aliasing-violation on address 0x7ffeebf1a72c (pc 0x5b3b1146008a bp 0x7ffeebf1a660 sp 0x7ffeebf19e08 tid 1375532)
+ WRITE of size 4 at 0x7ffeebf1a72c with type float accesses an existing object of type int
+ #0 0x5b3b11460089 in main example_AliasViolation.c:4:10
+
+Error terminology
+------------------
+
+There are some terms that may appear in TypeSanitizer errors that are derived from
+`TBAA Metadata `. This section hopes to provide a
+brief dictionary of these terms.
+
+* ``omnipotent char``: This is a special type which can alias with anything. Its name comes from the C/C++
+ type ``char``.
+* ``type p[x]``: This signifies pointers to the type. ``x`` is the number of indirections to reach the final value.
+ As an example, a pointer to a pointer to an integer would be ``type p2 int``.
+
+TypeSanitizer is still experimental. User-facing error messages should be improved in the future to remove
+references to LLVM IR specific terms.
+
+Sanitizer features
+==================
+
+``__has_feature(type_sanitizer)``
+------------------------------------
+
+In some cases one may need to execute different code depending on whether
+TypeSanitizer is enabled.
+:ref:`\_\_has\_feature ` can be used for
+this purpose.
+
+.. code-block:: c
+
+ #if defined(__has_feature)
+ # if __has_feature(type_sanitizer)
+ // code that builds only under TypeSanitizer
+ # endif
+ #endif
+
+``__attribute__((no_sanitize("type")))``
+-----------------------------------------------
+
+Some code you may not want to be instrumented by TypeSanitizer. One may use the
+function attribute ``no_sanitize("type")`` to disable instrumenting type aliasing.
+It is possible, depending on what happens in non-instrumented code, that instrumented code
+emits false-positives/ false-negatives. This attribute may not be supported by other
+compilers, so we suggest to use it together with ``__has_feature(type_sanitizer)``.
+
+``__attribute__((disable_sanitizer_instrumentation))``
+--------------------------------------------------------
+
+The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
+to prevent all kinds of instrumentation. As a result, it may introduce false
+positives and incorrect stack traces. Therefore, it should be used with care,
+and only if absolutely required; for example for certain code that cannot
+tolerate any instrumentation and resulting side-effects. This attribute
+overrides ``no_sanitize("type")``.
+
+Ignorelist
+----------
+
+TypeSanitizer supports ``src`` and ``fun`` entity types in
+:doc:`SanitizerSpecialCaseList`, that can be used to suppress aliasing
+violation reports in the specified source files or functions. Like
+with other methods of ignoring instrumentation, this can result in false
+positives/ false-negatives.
+
+Limitations
+-----------
+
+* TypeSanitizer uses more real memory than a native run. It uses 8 bytes of
+ shadow memory for each byte of user memory.
+* There are transformation passes which run before TypeSanitizer. If these
+ passes optimize out an aliasing violation, TypeSanitizer cannot catch it.
+* Currently, all instrumentation is inlined. This can result in a **15x**
+ (on average) increase in generated file size, and **3x** to **7x** increase
+ in compile time. In some documented cases this can cause the compiler to hang.
+ There are plans to improve this in the future.
+* Codebases that use unions and struct-initialized variables can see incorrect
+ results, as TypeSanitizer doesn't yet instrument these reliably.
+* Since Clang & LLVM's TBAA system is used to generate the checks used by the
+ instrumentation, TypeSanitizer follows Clang & LLVM's rules for type aliasing.
+ There may be situations where that disagrees with the standard. However this
+ does at least mean that TypeSanitizer will catch any aliasing violations that
+ would cause bugs when compiling with Clang & LLVM.
+* TypeSanitizer cannot currently be run alongside other sanitizers such as
+ AddressSanitizer, ThreadSanitizer or UndefinedBehaviourSanitizer.
+
+Current Status
+--------------
+
+TypeSanitizer is brand new, and still in development. There are some known
+issues, especially in areas where Clang's emitted TBAA data isn't extensive
+enough for TypeSanitizer's runtime.
+
+We are actively working on enhancing the tool --- stay tuned. Any help,
+issues, pull requests, ideas, is more than welcome. You can find the
+`issue tracker here. `_
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 260e84910c6f7..d977868b8a2c6 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -2103,7 +2103,10 @@ are listed below.
``-fsanitize=undefined``: :doc:`UndefinedBehaviorSanitizer`,
a fast and compatible undefined behavior checker.
+ - .. _opt_fsanitize_type:
+ ``-fsanitize=type``: :doc:`TypeSanitizer`, a detector for strict
+ aliasing violations.
- ``-fsanitize=dataflow``: :doc:`DataFlowSanitizer`, a general data
flow analysis.
- ``-fsanitize=cfi``: :doc:`control flow integrity `
@@ -2220,6 +2223,12 @@ are listed below.
This option is currently experimental.
+.. option:: -fsanitize-kcfi-arity
+
+ Extends kernel indirect call forward-edge control flow integrity with
+ additional function arity information (for supported targets). See
+ :doc:`ControlFlowIntegrity` for more details.
+
.. option:: -fstrict-vtable-pointers
Enable optimizations based on the strict rules for overwriting polymorphic
@@ -2486,6 +2495,82 @@ are listed below.
$ clang -fuse-ld=lld -Oz -Wl,--icf=safe -fcodegen-data-use code.cc
+.. _strict_aliasing:
+
+Strict Aliasing
+---------------
+
+The C and C++ standards require accesses to objects in memory to use l-values of
+an appropriate type for the object. This is called *strict aliasing* or
+*type-based alias analysis*. Strict aliasing enhances a variety of powerful
+memory optimizations, including reordering, combining, and eliminating memory
+accesses. These optimizations can lead to unexpected behavior in code that
+violates the strict aliasing rules. For example:
+
+.. code-block:: c++
+
+ void advance(size_t *index, double *data) {
+ double value = data[*index];
+ /* Clang may assume that this store does not change the contents of `data`. */
+ *index += 1;
+ /* Clang may assume that this store does not change the contents of `index`. */
+ data[*index] = value;
+ /* Either of these facts may create significant optimization opportunities
+ if Clang is able to inline this function. */
+ }
+
+Strict aliasing can be explicitly enabled with ``-fstrict-aliasing`` and
+disabled with ``-fno-strict-aliasing``. ``clang-cl`` defaults to
+``-fno-strict-aliasing``; see . Otherwise, Clang defaults to ``-fstrict-aliasing``.
+
+C and C++ specify slightly different rules for strict aliasing. To improve
+language interoperability, Clang allows two types to alias if either language
+would permit it. This includes applying the C++ similar types rule to C,
+allowing ``int **`` to alias ``int const * const *``. Clang also relaxes the
+standard aliasing rules in the following ways:
+
+* All integer types of the same size are permitted to alias each other,
+ including signed and unsigned types.
+* ``void*`` is permitted to alias any pointer type, ``void**`` is permitted to
+ alias any pointer to pointer type, and so on.
+
+Code which violates strict aliasing has undefined behavior. A program that
+works in one version of Clang may not work in another because of changes to the
+optimizer. Clang provides a :doc:`TypeSanitizer` to help detect
+violations of the strict aliasing rules, but it is currently still experimental.
+Code that is known to violate strict aliasing should generally be built with
+``-fno-strict-aliasing`` if the violation cannot be fixed.
+
+Clang supports several ways to fix a violation of strict aliasing:
+
+* L-values of the character types ``char`` and ``unsigned char`` (as well as
+ other types, depending on the standard) are permitted to access objects of
+ any type.
+
+* Library functions such as ``memcpy`` and ``memset`` are specified as treating
+ memory as characters and therefore are not limited by strict aliasing. If a
+ value of one type must be reinterpreted as another (e.g. to read the bits of a
+ floating-point number), use ``memcpy`` to copy the representation to an object
+ of the destination type. This has no overhead over a direct l-value access
+ because Clang should reliably optimize calls to these functions to use simple
+ loads and stores when they are used with small constant sizes.
+
+* The attribute ``may_alias`` can be added to a ``typedef`` to give l-values of
+ that type the same aliasing power as the character types.
+
+Clang makes a best effort to avoid obvious miscompilations from strict aliasing
+by only considering type information when it cannot prove that two accesses must
+refer to the same memory. However, it is not recommended that programmers
+intentionally rely on this instead of using one of the solutions above because
+it is too easy for the compiler's analysis to be blocked in surprising ways.
+
+In Clang 20, Clang strengthened its implementation of strict aliasing for
+accesses of pointer type. Previously, all accesses of pointer type were
+permitted to alias each other, but Clang now distinguishes different pointers
+by their pointee type, except as limited by the relaxations around qualifiers
+and ``void*`` described above. The previous behavior of treating all pointers as
+aliasing can be restored using ``-fno-pointer-tbaa``.
+
Profile Guided Optimization
---------------------------
@@ -2880,7 +2965,8 @@ instrumentation:
environment variable to specify an alternate file. If non-default file name
is specified by both the environment variable and the command line option,
the environment variable takes precedence. The file name pattern specified
- can include different modifiers: ``%p``, ``%h``, ``%m``, ``%t``, and ``%c``.
+ can include different modifiers: ``%p``, ``%h``, ``%m``, ``%b``, ``%t``, and
+ ``%c``.
Any instance of ``%p`` in that file name will be replaced by the process
ID, so that you can easily distinguish the profile output from multiple
@@ -2902,11 +2988,11 @@ instrumentation:
``%p`` is that the storage requirement for raw profile data files is greatly
increased. To avoid issues like this, the ``%m`` specifier can used in the profile
name. When this specifier is used, the profiler runtime will substitute ``%m``
- with a unique integer identifier associated with the instrumented binary. Additionally,
+ with an integer identifier associated with the instrumented binary. Additionally,
multiple raw profiles dumped from different processes that share a file system (can be
on different hosts) will be automatically merged by the profiler runtime during the
dumping. If the program links in multiple instrumented shared libraries, each library
- will dump the profile data into its own profile data file (with its unique integer
+ will dump the profile data into its own profile data file (with its integer
id embedded in the profile name). Note that the merging enabled by ``%m`` is for raw
profile data generated by profiler runtime. The resulting merged "raw" profile data
file still needs to be converted to a different format expected by the compiler (
@@ -2916,6 +3002,12 @@ instrumentation:
$ LLVM_PROFILE_FILE="code-%m.profraw" ./code
+ Although rare, binary signatures used by the ``%m`` specifier can have
+ collisions. In this case, the ``%b`` specifier, which expands to the binary
+ ID (build ID in ELF and COFF), can be added. To use it, the program should be
+ compiled with the build ID linker option (``--build-id`` for GNU ld or LLD,
+ ``/build-id`` for lld-link on Windows). Linux, Windows and AIX are supported.
+
See `this `_ section
about the ``%t``, and ``%c`` modifiers.
@@ -3033,6 +3125,24 @@ indexed format, regardeless whether it is produced by frontend or the IR pass.
overhead. ``prefer-atomic`` will be transformed to ``atomic`` when supported
by the target, or ``single`` otherwise.
+.. option:: -fprofile-continuous
+
+ Enables the continuous instrumentation profiling where profile counter updates
+ are continuously synced to a file. This option sets any neccessary modifiers
+ (currently ``%c``) in the default profile filename and passes any necessary
+ flags to the middle-end to support this mode. Value profiling is not supported
+ in continuous mode.
+
+ .. code-block:: console
+
+ $ clang++ -O2 -fprofile-generate -fprofile-continuous code.cc -o code
+
+ Running ``./code`` will collect the profile and write it to the
+ ``default_xxxx.profraw`` file. However, if ``./code`` abruptly terminates or
+ does not call ``exit()``, in continuous mode the profile collected up to the
+ point of termination will be available in ``default_xxxx.profraw`` while in
+ the non-continuous mode, no profile file is generated.
+
.. option:: -ftemporal-profile
Enables the temporal profiling extension for IRPGO to improve startup time by
@@ -5269,12 +5379,6 @@ The Visual C++ Toolset has a slightly more elaborate mechanism for detection.
Restrictions and Limitations compared to Clang
----------------------------------------------
-Strict Aliasing
-^^^^^^^^^^^^^^^
-
-Strict aliasing (TBAA) is always off by default in clang-cl. Whereas in clang,
-strict aliasing is turned on by default for all optimization levels.
-
-To enable LLVM optimizations based on strict aliasing rules (e.g., optimizations
-based on type of expressions in C/C++), user will need to explicitly pass
-`-fstrict-aliasing` to clang-cl.
+Strict aliasing (TBAA) is always off by default in clang-cl whereas in clang,
+strict aliasing is turned on by default for all optimization levels. For more
+details, see :ref:`Strict aliasing `.
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index e093b2d672a74..707067358fdfe 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -1332,10 +1332,69 @@ security
Security related checkers.
+.. _security-ArrayBound:
+
+security.ArrayBound (C, C++)
+""""""""""""""""""""""""""""
+Report out of bounds access to memory that is before the start or after the end
+of the accessed region (array, heap-allocated region, string literal etc.).
+This usually means incorrect indexing, but the checker also detects access via
+the operators ``*`` and ``->``.
+
+.. code-block:: c
+
+ void test_underflow(int x) {
+ int buf[100][100];
+ if (x < 0)
+ buf[0][x] = 1; // warn
+ }
+
+ void test_overflow() {
+ int buf[100];
+ int *p = buf + 100;
+ *p = 1; // warn
+ }
+
+If checkers like :ref:`unix-Malloc` or :ref:`cplusplus-NewDelete` are enabled
+to model the behavior of ``malloc()``, ``operator new`` and similar
+allocators), then this checker can also reports out of bounds access to
+dynamically allocated memory:
+
+.. code-block:: cpp
+
+ int *test_dynamic() {
+ int *mem = new int[100];
+ mem[-1] = 42; // warn
+ return mem;
+ }
+
+In uncertain situations (when the checker can neither prove nor disprove that
+overflow occurs), the checker assumes that the the index (more precisely, the
+memory offeset) is within bounds.
+
+However, if :ref:`optin-taint-GenericTaint` is enabled and the index/offset is
+tainted (i.e. it is influenced by an untrusted souce), then this checker
+reports the potential out of bounds access:
+
+.. code-block:: c
+
+ void test_with_tainted_index() {
+ char s[] = "abc";
+ int x = getchar();
+ char c = s[x]; // warn: potential out of bounds access with tainted index
+ }
+
+.. note::
+
+ This checker is an improved and renamed version of the checker that was
+ previously known as ``alpha.security.ArrayBoundV2``. The old checker
+ ``alpha.security.ArrayBound`` was removed when the (previously
+ "experimental") V2 variant became stable enough for regular use.
+
.. _security-cert-env-InvalidPtr:
security.cert.env.InvalidPtr
-""""""""""""""""""""""""""""""""""
+""""""""""""""""""""""""""""
Corresponds to SEI CERT Rules `ENV31-C `_ and `ENV34-C `_.
@@ -3216,78 +3275,6 @@ Warns against using one vs. many plural pattern in code when generating localize
alpha.security
^^^^^^^^^^^^^^
-.. _alpha-security-ArrayBound:
-
-alpha.security.ArrayBound (C)
-"""""""""""""""""""""""""""""
-Warn about buffer overflows (older checker).
-
-.. code-block:: c
-
- void test() {
- char *s = "";
- char c = s[1]; // warn
- }
-
- struct seven_words {
- int c[7];
- };
-
- void test() {
- struct seven_words a, *p;
- p = &a;
- p[0] = a;
- p[1] = a;
- p[2] = a; // warn
- }
-
- // note: requires unix.Malloc or
- // alpha.unix.MallocWithAnnotations checks enabled.
- void test() {
- int *p = malloc(12);
- p[3] = 4; // warn
- }
-
- void test() {
- char a[2];
- int *b = (int*)a;
- b[1] = 3; // warn
- }
-
-.. _alpha-security-ArrayBoundV2:
-
-alpha.security.ArrayBoundV2 (C)
-"""""""""""""""""""""""""""""""
-Warn about buffer overflows (newer checker).
-
-.. code-block:: c
-
- void test() {
- char *s = "";
- char c = s[1]; // warn
- }
-
- void test() {
- int buf[100];
- int *p = buf;
- p = p + 99;
- p[1] = 1; // warn
- }
-
- // note: compiler has internal check for this.
- // Use -Wno-array-bounds to suppress compiler warning.
- void test() {
- int buf[100][100];
- buf[0][-1] = 1; // warn
- }
-
- // note: requires optin.taint check turned on.
- void test() {
- char s[] = "abc";
- int x = getchar();
- char c = s[x]; // warn: index is tainted
- }
-
.. _alpha-security-ReturnPtrRange:
alpha.security.ReturnPtrRange (C)
diff --git a/clang/docs/analyzer/developer-docs.rst b/clang/docs/analyzer/developer-docs.rst
index 1b8133ffa8920..60c0e71ad847c 100644
--- a/clang/docs/analyzer/developer-docs.rst
+++ b/clang/docs/analyzer/developer-docs.rst
@@ -11,3 +11,4 @@ Contents:
developer-docs/InitializerLists
developer-docs/nullability
developer-docs/RegionStore
+ developer-docs/PerformanceInvestigation
diff --git a/clang/docs/analyzer/developer-docs/PerformanceInvestigation.rst b/clang/docs/analyzer/developer-docs/PerformanceInvestigation.rst
new file mode 100644
index 0000000000000..ca3a56828209b
--- /dev/null
+++ b/clang/docs/analyzer/developer-docs/PerformanceInvestigation.rst
@@ -0,0 +1,137 @@
+=========================
+Performance Investigation
+=========================
+
+Multiple factors contribute to the time it takes to analyze a file with Clang Static Analyzer.
+A translation unit contains multiple entry points, each of which take multiple steps to analyze.
+
+Performance analysis using ``-ftime-trace``
+===========================================
+
+You can add the ``-ftime-trace=file.json`` option to break down the analysis time into individual entry points and steps within each entry point.
+You can explore the generated JSON file in a Chromium browser using the ``chrome://tracing`` URL,
+or using `speedscope `_.
+Once you narrow down to specific analysis steps you are interested in, you can more effectively employ heavier profilers,
+such as `Perf `_ and `Callgrind `_.
+
+Each analysis step has a time scope in the trace, corresponds to processing of an exploded node, and is designated with a ``ProgramPoint``.
+If the ``ProgramPoint`` is associated with a location, you can see it on the scope metadata label.
+
+Here is an example of a time trace produced with
+
+.. code-block:: bash
+ :caption: Clang Static Analyzer invocation to generate a time trace of string.c analysis.
+
+ clang -cc1 -analyze -verify clang/test/Analysis/string.c \
+ -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection \
+ -ftime-trace=trace.json -ftime-trace-granularity=1
+
+.. image:: ../images/speedscope.png
+
+On the speedscope screenshot above, under the first time ruler is the bird's-eye view of the entire trace that spans a little over 60 milliseconds.
+Under the second ruler (focused on the 18.09-18.13ms time point) you can see a narrowed-down portion.
+The second box ("HandleCode memset...") that spans entire screen (and actually extends beyond it) corresponds to the analysis of ``memset16_region_cast()`` entry point that is defined in the "string.c" test file on line 1627.
+Below it, you can find multiple sub-scopes each corresponding to processing of a single exploded node.
+
+- First: a ``PostStmt`` for some statement on line 1634. This scope has a selected subscope "CheckerManager::runCheckersForCallEvent (Pre)" that takes 5 microseconds.
+- Four other nodes, too small to be discernible at this zoom level
+- Last on this screenshot: another ``PostStmt`` for a statement on line 1635.
+
+In addition to the ``-ftime-trace`` option, you can use ``-ftime-trace-granularity`` to fine-tune the time trace.
+
+- ``-ftime-trace-granularity=NN`` dumps only time scopes that are longer than NN microseconds.
+- ``-ftime-trace-verbose`` enables some additional dumps in the frontend related to template instantiations.
+ At the moment, it has no effect on the traces from the static analyzer.
+
+Note: Both Chrome-tracing and speedscope tools might struggle with time traces above 100 MB in size.
+Luckily, in most cases the default max-steps boundary of 225 000 produces the traces of approximately that size
+for a single entry point.
+You can use ``-analyze-function=get_global_options`` together with ``-ftime-trace`` to narrow down analysis to a specific entry point.
+
+
+Performance analysis using ``perf``
+===================================
+
+`Perf `_ is a tool for conducting sampling-based profiling.
+It's easy to start profiling, you only have 2 prerequisites.
+Build with ``-fno-omit-frame-pointer`` and debug info (``-g``).
+You can use release builds, but probably the easiest is to set the ``CMAKE_BUILD_TYPE=RelWithDebInfo``
+along with ``CMAKE_CXX_FLAGS="-fno-omit-frame-pointer"`` when configuring ``llvm``.
+Here is how to `get started `_ if you are in trouble.
+
+.. code-block:: bash
+ :caption: Running the Clang Static Analyzer through ``perf`` to gather samples of the execution.
+
+ # -F: Sampling frequency, use `-F max` for maximal frequency
+ # -g: Enable call-graph recording for both kernel and user space
+ perf record -F 99 -g -- clang -cc1 -analyze -verify clang/test/Analysis/string.c \
+ -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection
+
+Once you have the profile data, you can use it to produce a Flame graph.
+A Flame graph is a visual representation of the stack frames of the samples.
+Common stack frame prefixes are squashed together, making up a wider bar.
+The wider the bar, the more time was spent under that particular stack frame,
+giving a sense of how the overall execution time was spent.
+
+Clone the `FlameGraph `_ git repository,
+as we will use some scripts from there to convert the ``perf`` samples into a Flame graph.
+It's also useful to check out Brendan Gregg's (the author of FlameGraph)
+`homepage `_.
+
+
+.. code-block:: bash
+ :caption: Converting the ``perf`` profile into a Flamegraph, then opening it in Firefox.
+
+ perf script | /path/to/FlameGraph/stackcollapse-perf.pl > perf.folded
+ /path/to/FlameGraph/flamegraph.pl perf.folded > perf.svg
+ firefox perf.svg
+
+.. image:: ../images/flamegraph.png
+
+
+Performance analysis using ``uftrace``
+======================================
+
+`uftrace `_ is a great tool to generate rich profile data
+that you can use to focus and drill down into the timeline of your application.
+We will use it to generate Chromium trace JSON.
+In contrast to ``perf``, this approach statically instruments every function, so it should be more precise and thorough than the sampling-based approaches like ``perf``.
+In contrast to using ``-ftime-trace``, functions don't need to opt-in to be profiled using ``llvm::TimeTraceScope``.
+All functions are profiled due to automatic static instrumentation.
+
+There is only one prerequisite to use this tool.
+You need to build the binary you are about to instrument using ``-pg`` or ``-finstrument-functions``.
+This will make it run substantially slower but allows rich instrumentation.
+It will also consume many gigabites of storage for a single trace unless filter flags are used during recording.
+
+.. code-block:: bash
+ :caption: Recording with ``uftrace``, then dumping the result as a Chrome trace JSON.
+
+ uftrace record clang -cc1 -analyze -verify clang/test/Analysis/string.c \
+ -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection
+ uftrace dump --filter=".*::AnalysisConsumer::HandleTranslationUnit" --time-filter=300 --chrome > trace.json
+
+.. image:: ../images/uftrace_detailed.png
+
+In this picture, you can see the functions below the Static Analyzer's entry point, which takes at least 300 nanoseconds to run, visualized by Chrome's ``about:tracing`` page
+You can also see how deep function calls we may have due to AST visitors.
+
+Using different filters can reduce the number of functions to record.
+For the common options, refer to the ``uftrace`` `documentation `_.
+
+Similar filters can be applied for dumping too. That way you can reuse the same (detailed)
+recording to selectively focus on some special part using a refinement of the filter flags.
+Remember, the trace JSON needs to fit into Chrome's ``about:tracing`` or `speedscope `_,
+thus it needs to be of a limited size.
+If you do not apply filters on recording, you will collect a large trace and every dump operation
+would need to sieve through the much larger recording which may be annoying if done repeatedly.
+
+If the trace JSON is still too large to load, have a look at the dump as plain text and look for frequent entries that refer to non-interesting parts.
+Once you have some of those, add them as ``--hide`` flags to the ``uftrace dump`` call.
+To see what functions appear frequently in the trace, use this command:
+
+.. code-block:: bash
+
+ cat trace.json | grep -Po '"name":"(.+)"' | sort | uniq -c | sort -nr | head -n 50
+
+``uftrace`` can also dump the report as a Flame graph using ``uftrace dump --framegraph``.
diff --git a/clang/docs/analyzer/images/flamegraph.png b/clang/docs/analyzer/images/flamegraph.png
new file mode 100644
index 0000000000000..b16ec90b9e600
Binary files /dev/null and b/clang/docs/analyzer/images/flamegraph.png differ
diff --git a/clang/docs/analyzer/images/speedscope.png b/clang/docs/analyzer/images/speedscope.png
new file mode 100644
index 0000000000000..767725d68f740
Binary files /dev/null and b/clang/docs/analyzer/images/speedscope.png differ
diff --git a/clang/docs/analyzer/images/uftrace_detailed.png b/clang/docs/analyzer/images/uftrace_detailed.png
new file mode 100644
index 0000000000000..fcf681909d070
Binary files /dev/null and b/clang/docs/analyzer/images/uftrace_detailed.png differ
diff --git a/clang/docs/analyzer/user-docs/Annotations.rst b/clang/docs/analyzer/user-docs/Annotations.rst
index d87e8f4df99c3..11f15939ecfaf 100644
--- a/clang/docs/analyzer/user-docs/Annotations.rst
+++ b/clang/docs/analyzer/user-docs/Annotations.rst
@@ -23,8 +23,8 @@ recognized by GCC. Their use can be conditioned using preprocessor macros
.. contents::
:local:
-Annotations to Enhance Generic Checks
-_____________________________________
+General Purpose Annotations
+___________________________
Null Pointer Checking
#####################
@@ -79,7 +79,7 @@ implemented with a macro, with the macro performing a check for the assertion
condition and, when the check fails, calling an assertion handler. For
example, consider the following code fragment:
-.. code-block: c
+.. code-block:: c
void foo(int *p) {
assert(p != NULL);
@@ -87,7 +87,7 @@ example, consider the following code fragment:
When this code is preprocessed on Mac OS X it expands to the following:
-.. code-block: c
+.. code-block:: c
void foo(int *p) {
(__builtin_expect(!(p != NULL), 0) ? __assert_rtn(__func__, "t.c", 4, "p != NULL") : (void)0);
@@ -131,7 +131,7 @@ return.
On Mac OS X, the function prototype for ``__assert_rtn`` (declared in
``assert.h``) is specifically annotated with the 'noreturn' attribute:
-.. code-block: c
+.. code-block:: c
void __assert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__));
@@ -151,7 +151,7 @@ the use of preprocessor macros.
**Example**
-.. code-block: c
+.. code-block:: c
#ifndef CLANG_ANALYZER_NORETURN
#if __has_feature(attribute_analyzer_noreturn)
@@ -163,6 +163,43 @@ the use of preprocessor macros.
void my_assert_rtn(const char *, const char *, int, const char *) CLANG_ANALYZER_NORETURN;
+Dynamic Memory Modeling Annotations
+###################################
+
+If a project uses custom functions for dynamic memory management (that e.g. act as wrappers around ``malloc``/``free`` or ``new``/``delete`` in C++) and the analyzer cannot "see" the _definitions_ of these functions, it's possible to annotate their declarations to let the analyzer model their behavior. (Otherwise the analyzer cannot know that the opaque ``my_free()`` is basically equivalent to a standard ``free()`` call.)
+
+.. note::
+ **This page only provides a brief list of these annotations.** For a full documentation, see the main `Attributes in Clang <../../AttributeReference.html#ownership-holds-ownership-returns-ownership-takes-clang-static-analyzer>`_ page.
+
+Attribute 'ownership_returns' (Clang-specific)
+----------------------------------------------
+
+Use this attribute to mark functions that return dynamically allocated memory. Takes a single argument, the type of the allocation (e.g. ``malloc`` or ``new``).
+
+.. code-block:: c
+
+ void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
+
+Attribute 'ownership_takes' (Clang-specific)
+--------------------------------------------
+
+Use this attribute to mark functions that deallocate memory. Takes two arguments: the type of the allocation (e.g. ``malloc`` or ``new``) and the index of the parameter that is being deallocated (counting from 1).
+
+.. code-block:: c
+
+ void __attribute((ownership_takes(malloc, 1))) my_free(void *);
+
+Attribute 'ownership_holds' (Clang-specific)
+--------------------------------------------
+
+Use this attribute to mark functions that take ownership of memory and will deallocate it at some unspecified point in the future. Takes two arguments: the type of the allocation (e.g. ``malloc`` or ``new``) and the index of the parameter that is being held (counting from 1).
+
+.. code-block:: c
+
+ void __attribute((ownership_holds(malloc, 2))) store_in_table(int key, record_t *val);
+
+The annotations ``ownership_takes`` and ``ownership_holds`` both prevent memory leak reports (concerning the specified argument); the difference between them is that using taken memory is a use-after-free error, while using held memory is assumed to be legitimate.
+
Mac OS X API Annotations
________________________
@@ -207,7 +244,7 @@ functions allows the analyzer to perform extra checking.
**Example**
-.. code-block: objc
+.. code-block:: objc
#import ;
@@ -597,7 +634,6 @@ returned object.
LIBKERN_RETURNS_NOT_RETAINED OSObject *myFieldGetter();
}
-
// Note that the annotation only has to be applied to the function declaration.
OSObject * MyClass::myFieldGetter() {
return f;
diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 349378b1efa21..6c792af66a62c 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -35,6 +35,7 @@ Using Clang as a Compiler
UndefinedBehaviorSanitizer
DataFlowSanitizer
LeakSanitizer
+ TypeSanitizer
RealtimeSanitizer
SanitizerCoverage
SanitizerStats
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index aac5d1fa8aa2e..61e361faabdaf 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2206,7 +2206,11 @@ enum CXCursorKind {
*/
CXCursor_OpenACCUpdateConstruct = 331,
- CXCursor_LastStmt = CXCursor_OpenACCUpdateConstruct,
+ /** OpenACC atomic Construct.
+ */
+ CXCursor_OpenACCAtomicConstruct = 332,
+
+ CXCursor_LastStmt = CXCursor_OpenACCAtomicConstruct,
/**
* Cursor that represents the translation unit itself.
@@ -5905,66 +5909,6 @@ CINDEX_LINKAGE const char *clang_EvalResult_getAsStr(CXEvalResult E);
* Disposes the created Eval memory.
*/
CINDEX_LINKAGE void clang_EvalResult_dispose(CXEvalResult E);
-/**
- * @}
- */
-
-/** \defgroup CINDEX_REMAPPING Remapping functions
- *
- * @{
- */
-
-/**
- * A remapping of original source files and their translated files.
- */
-typedef void *CXRemapping;
-
-/**
- * Retrieve a remapping.
- *
- * \param path the path that contains metadata about remappings.
- *
- * \returns the requested remapping. This remapping must be freed
- * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred.
- */
-CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *path);
-
-/**
- * Retrieve a remapping.
- *
- * \param filePaths pointer to an array of file paths containing remapping info.
- *
- * \param numFiles number of file paths.
- *
- * \returns the requested remapping. This remapping must be freed
- * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred.
- */
-CINDEX_LINKAGE
-CXRemapping clang_getRemappingsFromFileList(const char **filePaths,
- unsigned numFiles);
-
-/**
- * Determine the number of remappings.
- */
-CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
-
-/**
- * Get the original and the associated filename from the remapping.
- *
- * \param original If non-NULL, will be set to the original filename.
- *
- * \param transformed If non-NULL, will be set to the filename that the original
- * is associated with.
- */
-CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index,
- CXString *original,
- CXString *transformed);
-
-/**
- * Dispose the remapping.
- */
-CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
-
/**
* @}
*/
diff --git a/clang/include/clang/ARCMigrate/ARCMT.h b/clang/include/clang/ARCMigrate/ARCMT.h
deleted file mode 100644
index 2b950e3d2cc2b..0000000000000
--- a/clang/include/clang/ARCMigrate/ARCMT.h
+++ /dev/null
@@ -1,130 +0,0 @@
-//===-- ARCMT.h - ARC Migration Rewriter ------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_H
-#define LLVM_CLANG_ARCMIGRATE_ARCMT_H
-
-#include "clang/ARCMigrate/FileRemapper.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Frontend/CompilerInvocation.h"
-
-namespace clang {
- class ASTContext;
- class DiagnosticConsumer;
- class PCHContainerOperations;
-
-namespace arcmt {
- class MigrationPass;
-
-/// Creates an AST with the provided CompilerInvocation but with these
-/// changes:
-/// -if a PCH/PTH is set, the original header is used instead
-/// -Automatic Reference Counting mode is enabled
-///
-/// It then checks the AST and produces errors/warning for ARC migration issues
-/// that the user needs to handle manually.
-///
-/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
-/// even if the migrator can fix them, but the function will still return false
-/// if all ARC errors can be fixed.
-///
-/// \param plistOut if non-empty, it is the file path to store the plist with
-/// the pre-migration ARC diagnostics.
-///
-/// \returns false if no error is produced, true otherwise.
-bool
-checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input,
- std::shared_ptr PCHContainerOps,
- DiagnosticConsumer *DiagClient,
- bool emitPremigrationARCErrors = false,
- StringRef plistOut = StringRef());
-
-/// Works similar to checkForManualIssues but instead of checking, it
-/// applies automatic modifications to source files to conform to ARC.
-///
-/// \returns false if no error is produced, true otherwise.
-bool
-applyTransformations(CompilerInvocation &origCI,
- const FrontendInputFile &Input,
- std::shared_ptr PCHContainerOps,
- DiagnosticConsumer *DiagClient);
-
-/// Applies automatic modifications and produces temporary files
-/// and metadata into the \p outputDir path.
-///
-/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
-/// even if the migrator can fix them, but the function will still return false
-/// if all ARC errors can be fixed.
-///
-/// \param plistOut if non-empty, it is the file path to store the plist with
-/// the pre-migration ARC diagnostics.
-///
-/// \returns false if no error is produced, true otherwise.
-bool migrateWithTemporaryFiles(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr PCHContainerOps,
- DiagnosticConsumer *DiagClient, StringRef outputDir,
- bool emitPremigrationARCErrors, StringRef plistOut);
-
-/// Get the set of file remappings from the \p outputDir path that
-/// migrateWithTemporaryFiles produced.
-///
-/// \returns false if no error is produced, true otherwise.
-bool getFileRemappings(std::vector > &remap,
- StringRef outputDir,
- DiagnosticConsumer *DiagClient);
-
-/// Get the set of file remappings from a list of files with remapping
-/// info.
-///
-/// \returns false if no error is produced, true otherwise.
-bool getFileRemappingsFromFileList(
- std::vector > &remap,
- ArrayRef remapFiles,
- DiagnosticConsumer *DiagClient);
-
-typedef void (*TransformFn)(MigrationPass &pass);
-
-std::vector getAllTransformations(LangOptions::GCMode OrigGCMode,
- bool NoFinalizeRemoval);
-
-class MigrationProcess {
- CompilerInvocation OrigCI;
- std::shared_ptr PCHContainerOps;
- DiagnosticConsumer *DiagClient;
- FileRemapper Remapper;
-
-public:
- bool HadARCErrors;
-
- MigrationProcess(CompilerInvocation &CI,
- std::shared_ptr PCHContainerOps,
- DiagnosticConsumer *diagClient,
- StringRef outputDir = StringRef());
-
- class RewriteListener {
- public:
- virtual ~RewriteListener();
-
- virtual void start(ASTContext &Ctx) { }
- virtual void finish() { }
-
- virtual void insert(SourceLocation loc, StringRef text) { }
- virtual void remove(CharSourceRange range) { }
- };
-
- bool applyTransform(TransformFn trans, RewriteListener *listener = nullptr);
-
- FileRemapper &getRemapper() { return Remapper; }
-};
-
-} // end namespace arcmt
-
-} // end namespace clang
-
-#endif
diff --git a/clang/include/clang/ARCMigrate/ARCMTActions.h b/clang/include/clang/ARCMigrate/ARCMTActions.h
deleted file mode 100644
index 714f4b33db446..0000000000000
--- a/clang/include/clang/ARCMigrate/ARCMTActions.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//===--- ARCMTActions.h - ARC Migrate Tool Frontend Actions -----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
-#define LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
-
-#include "clang/ARCMigrate/FileRemapper.h"
-#include "clang/Frontend/FrontendAction.h"
-#include
-
-namespace clang {
-namespace arcmt {
-
-class CheckAction : public WrapperFrontendAction {
-protected:
- bool BeginInvocation(CompilerInstance &CI) override;
-
-public:
- CheckAction(std::unique_ptr WrappedAction);
-};
-
-class ModifyAction : public WrapperFrontendAction {
-protected:
- bool BeginInvocation(CompilerInstance &CI) override;
-
-public:
- ModifyAction(std::unique_ptr WrappedAction);
-};
-
-class MigrateSourceAction : public ASTFrontendAction {
- FileRemapper Remapper;
-protected:
- bool BeginInvocation(CompilerInstance &CI) override;
- std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
-};
-
-class MigrateAction : public WrapperFrontendAction {
- std::string MigrateDir;
- std::string PlistOut;
- bool EmitPremigrationARCErrors;
-protected:
- bool BeginInvocation(CompilerInstance &CI) override;
-
-public:
- MigrateAction(std::unique_ptr WrappedAction,
- StringRef migrateDir,
- StringRef plistOut,
- bool emitPremigrationARCErrors);
-};
-
-/// Migrates to modern ObjC syntax.
-class ObjCMigrateAction : public WrapperFrontendAction {
- std::string MigrateDir;
- unsigned ObjCMigAction;
- FileRemapper Remapper;
- CompilerInstance *CompInst;
-public:
- ObjCMigrateAction(std::unique_ptr WrappedAction,
- StringRef migrateDir, unsigned migrateAction);
-
-protected:
- std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
- bool BeginInvocation(CompilerInstance &CI) override;
-};
-
-}
-}
-
-#endif
diff --git a/clang/include/clang/ARCMigrate/FileRemapper.h b/clang/include/clang/ARCMigrate/FileRemapper.h
deleted file mode 100644
index afcee363516a2..0000000000000
--- a/clang/include/clang/ARCMigrate/FileRemapper.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===-- FileRemapper.h - File Remapping Helper ------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
-#define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
-
-#include "clang/Basic/FileEntry.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include
-#include
-
-namespace llvm {
- class MemoryBuffer;
- class MemoryBufferRef;
-}
-
-namespace clang {
- class FileManager;
- class DiagnosticsEngine;
- class PreprocessorOptions;
-
-namespace arcmt {
-
-class FileRemapper {
- // FIXME: Reuse the same FileManager for multiple ASTContexts.
- std::unique_ptr FileMgr;
-
- using Target = std::variant;
- using MappingsTy = llvm::DenseMap;
- MappingsTy FromToMappings;
-
- llvm::DenseMap ToFromMappings;
-
-public:
- FileRemapper();
- ~FileRemapper();
-
- bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
- bool ignoreIfFilesChanged);
- bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
- bool ignoreIfFilesChanged);
- bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag);
- bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag);
-
- bool overwriteOriginal(DiagnosticsEngine &Diag,
- StringRef outputDir = StringRef());
-
- void remap(StringRef filePath, std::unique_ptr memBuf);
-
- void applyMappings(PreprocessorOptions &PPOpts) const;
-
- /// Iterate through all the mappings.
- void forEachMapping(
- llvm::function_ref CaptureFile,
- llvm::function_ref
- CaptureBuffer) const;
-
- void clear(StringRef outputDir = StringRef());
-
-private:
- void remap(FileEntryRef file, std::unique_ptr memBuf);
- void remap(FileEntryRef file, FileEntryRef newfile);
-
- OptionalFileEntryRef getOriginalFile(StringRef filePath);
- void resetTarget(Target &targ);
-
- bool report(const Twine &err, DiagnosticsEngine &Diag);
-
- std::string getRemapInfoFile(StringRef outputDir);
-};
-
-} // end namespace arcmt
-
-} // end namespace clang
-
-#endif
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
index 833a78c77871d..9999a30c51ade 100644
--- a/clang/include/clang/AST/APValue.h
+++ b/clang/include/clang/AST/APValue.h
@@ -161,8 +161,9 @@ class APValue {
template T get() const { return cast(Ptr); }
- template
- T dyn_cast() const { return Ptr.dyn_cast(); }
+ template T dyn_cast() const {
+ return dyn_cast_if_present(Ptr);
+ }
void *getOpaqueValue() const;
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 4e9b961688d55..a96b9c0a17045 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -769,7 +769,7 @@ class ASTContext : public RefCountedBase {
/// pool.
DeclListNode *AllocateDeclListNode(clang::NamedDecl *ND) {
if (DeclListNode *Alloc = ListNodeFreeList) {
- ListNodeFreeList = Alloc->Rest.dyn_cast();
+ ListNodeFreeList = dyn_cast_if_present(Alloc->Rest);
Alloc->D = ND;
Alloc->Rest = nullptr;
return Alloc;
@@ -1733,6 +1733,47 @@ class ASTContext : public RefCountedBase {
unsigned NumPositiveBits, QualType &BestType,
QualType &BestPromotionType);
+ /// Determine whether the given integral value is representable within
+ /// the given type T.
+ bool isRepresentableIntegerValue(llvm::APSInt &Value, QualType T);
+
+ /// Compute NumNegativeBits and NumPositiveBits for an enum based on
+ /// the constant values of its enumerators.
+ template
+ bool computeEnumBits(RangeT EnumConstants, unsigned &NumNegativeBits,
+ unsigned &NumPositiveBits) {
+ NumNegativeBits = 0;
+ NumPositiveBits = 0;
+ bool MembersRepresentableByInt = true;
+ for (auto *Elem : EnumConstants) {
+ EnumConstantDecl *ECD = cast_or_null(Elem);
+ if (!ECD)
+ continue; // Already issued a diagnostic.
+
+ llvm::APSInt InitVal = ECD->getInitVal();
+ if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
+ // If the enumerator is zero that should still be counted as a positive
+ // bit since we need a bit to store the value zero.
+ unsigned ActiveBits = InitVal.getActiveBits();
+ NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
+ } else {
+ NumNegativeBits =
+ std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
+ }
+
+ MembersRepresentableByInt &= isRepresentableIntegerValue(InitVal, IntTy);
+ }
+
+ // If we have an empty set of enumerators we still need one bit.
+ // From [dcl.enum]p8
+ // If the enumerator-list is empty, the values of the enumeration are as if
+ // the enumeration had a single enumerator with value 0
+ if (!NumPositiveBits && !NumNegativeBits)
+ NumPositiveBits = 1;
+
+ return MembersRepresentableByInt;
+ }
+
QualType
getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const;
diff --git a/clang/include/clang/AST/ASTLambda.h b/clang/include/clang/AST/ASTLambda.h
index 646cb574847fe..a1854b6a1a949 100644
--- a/clang/include/clang/AST/ASTLambda.h
+++ b/clang/include/clang/AST/ASTLambda.h
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "llvm/Support/Casting.h"
namespace clang {
inline StringRef getLambdaStaticInvokerName() {
@@ -35,6 +36,12 @@ inline bool isLambdaCallOperator(const DeclContext *DC) {
return isLambdaCallOperator(cast(DC));
}
+inline bool isLambdaMethod(const DeclContext *DC) {
+ if (const auto *MD = dyn_cast_if_present(DC))
+ return MD->getParent()->isLambda();
+ return false;
+}
+
inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) {
return isLambdaCallOperator(DC) &&
cast(DC)->isExplicitObjectMemberFunction();
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index d01681483a918..f305cbbce4c60 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -698,6 +698,10 @@ class ValueDecl : public NamedDecl {
return const_cast(this)->getPotentiallyDecomposedVarDecl();
}
+ /// Determine whether this value is actually a function parameter pack,
+ /// init-capture pack, or structured binding pack
+ bool isParameterPack() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
@@ -1527,10 +1531,6 @@ class VarDecl : public DeclaratorDecl, public Redeclarable {
NonParmVarDeclBits.IsInitCapture = IC;
}
- /// Determine whether this variable is actually a function parameter pack or
- /// init-capture pack.
- bool isParameterPack() const;
-
/// Whether this local extern variable declaration's previous declaration
/// was declared in the same block scope. Only correct in C++.
bool isPreviousDeclInSameBlockScope() const {
@@ -2298,6 +2298,13 @@ class FunctionDecl : public DeclaratorDecl,
FunctionDeclBits.IsLateTemplateParsed = ILT;
}
+ bool isInstantiatedFromMemberTemplate() const {
+ return FunctionDeclBits.IsInstantiatedFromMemberTemplate;
+ }
+ void setInstantiatedFromMemberTemplate(bool Val = true) {
+ FunctionDeclBits.IsInstantiatedFromMemberTemplate = Val;
+ }
+
/// Whether this function is "trivial" in some specialized C++ senses.
/// Can only be true for default constructors, copy constructors,
/// copy assignment operators, and destructors. Not meaningful until
@@ -4035,7 +4042,7 @@ class EnumDecl : public TagDecl {
/// Return the type source info for the underlying integer type,
/// if no type source info exists, return 0.
TypeSourceInfo *getIntegerTypeSourceInfo() const {
- return IntegerType.dyn_cast();
+ return dyn_cast_if_present(IntegerType);
}
/// Retrieve the source range that covers the underlying type if
@@ -5139,6 +5146,12 @@ static constexpr StringRef getOpenMPVariantManglingSeparatorStr() {
bool IsArmStreamingFunction(const FunctionDecl *FD,
bool IncludeLocallyStreaming);
+/// Returns whether the given FunctionDecl has Arm ZA state.
+bool hasArmZAState(const FunctionDecl *FD);
+
+/// Returns whether the given FunctionDecl has Arm ZT0 state.
+bool hasArmZT0State(const FunctionDecl *FD);
+
} // namespace clang
#endif // LLVM_CLANG_AST_DECL_H
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 573b46a2321c5..648dae2838e03 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1257,8 +1257,11 @@ class alignas(8) Decl {
int64_t getID() const;
/// Looks through the Decl's underlying type to extract a FunctionType
- /// when possible. Will return null if the type underlying the Decl does not
- /// have a FunctionType.
+ /// when possible. This includes direct FunctionDecls, along with various
+ /// function types and typedefs. This includes function pointers/references,
+ /// member function pointers, and optionally if \p BlocksToo is set
+ /// Objective-C block pointers. Returns nullptr if the type underlying the
+ /// Decl does not have a FunctionType.
const FunctionType *getFunctionType(bool BlocksToo = true) const;
// Looks through the Decl's underlying type to determine if it's a
@@ -1391,7 +1394,7 @@ class DeclContextLookupResult {
const_iterator end() const { return iterator(); }
bool empty() const { return Result.isNull(); }
- bool isSingleResult() const { return Result.dyn_cast(); }
+ bool isSingleResult() const { return isa_and_present(Result); }
reference front() const { return *begin(); }
// Find the first declaration of the given type in the list. Note that this
@@ -1777,6 +1780,8 @@ class DeclContext {
uint64_t HasImplicitReturnZero : 1;
LLVM_PREFERRED_TYPE(bool)
uint64_t IsLateTemplateParsed : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ uint64_t IsInstantiatedFromMemberTemplate : 1;
/// Kind of contexpr specifier as defined by ConstexprSpecKind.
LLVM_PREFERRED_TYPE(ConstexprSpecKind)
@@ -1827,7 +1832,7 @@ class DeclContext {
};
/// Number of inherited and non-inherited bits in FunctionDeclBitfields.
- enum { NumFunctionDeclBits = NumDeclContextBits + 31 };
+ enum { NumFunctionDeclBits = NumDeclContextBits + 32 };
/// Stores the bits used by CXXConstructorDecl. If modified
/// NumCXXConstructorDeclBits and the accessor
@@ -1838,12 +1843,12 @@ class DeclContext {
LLVM_PREFERRED_TYPE(FunctionDeclBitfields)
uint64_t : NumFunctionDeclBits;
- /// 20 bits to fit in the remaining available space.
+ /// 19 bits to fit in the remaining available space.
/// Note that this makes CXXConstructorDeclBitfields take
/// exactly 64 bits and thus the width of NumCtorInitializers
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
- uint64_t NumCtorInitializers : 17;
+ uint64_t NumCtorInitializers : 16;
LLVM_PREFERRED_TYPE(bool)
uint64_t IsInheritingConstructor : 1;
@@ -1857,7 +1862,7 @@ class DeclContext {
};
/// Number of inherited and non-inherited bits in CXXConstructorDeclBitfields.
- enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 20 };
+ enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 19 };
/// Stores the bits used by ObjCMethodDecl.
/// If modified NumObjCMethodDeclBits and the accessor
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index fa3f4ec98eb36..766821b4fb25c 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1967,17 +1967,29 @@ class ExplicitSpecifier {
class CXXDeductionGuideDecl : public FunctionDecl {
void anchor() override;
+public:
+ // Represents the relationship between this deduction guide and the
+ // deduction guide that it was generated from (or lack thereof).
+ // See the SourceDeductionGuide member for more details.
+ enum class SourceDeductionGuideKind : uint8_t {
+ None,
+ Alias,
+ };
+
private:
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
ExplicitSpecifier ES,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, SourceLocation EndLocation,
CXXConstructorDecl *Ctor, DeductionCandidate Kind,
- Expr *TrailingRequiresClause)
+ Expr *TrailingRequiresClause,
+ const CXXDeductionGuideDecl *GeneratedFrom,
+ SourceDeductionGuideKind SourceKind)
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
SC_None, false, false, ConstexprSpecKind::Unspecified,
TrailingRequiresClause),
- Ctor(Ctor), ExplicitSpec(ES) {
+ Ctor(Ctor), ExplicitSpec(ES),
+ SourceDeductionGuide(GeneratedFrom, SourceKind) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
setDeductionCandidateKind(Kind);
@@ -1985,6 +1997,12 @@ class CXXDeductionGuideDecl : public FunctionDecl {
CXXConstructorDecl *Ctor;
ExplicitSpecifier ExplicitSpec;
+ // The deduction guide, if any, that this deduction guide was generated from,
+ // in the case of alias template deduction. The SourceDeductionGuideKind
+ // member indicates which of these sources applies, or is None otherwise.
+ llvm::PointerIntPair
+ SourceDeductionGuide;
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
public:
@@ -1997,7 +2015,9 @@ class CXXDeductionGuideDecl : public FunctionDecl {
TypeSourceInfo *TInfo, SourceLocation EndLocation,
CXXConstructorDecl *Ctor = nullptr,
DeductionCandidate Kind = DeductionCandidate::Normal,
- Expr *TrailingRequiresClause = nullptr);
+ Expr *TrailingRequiresClause = nullptr,
+ const CXXDeductionGuideDecl *SourceDG = nullptr,
+ SourceDeductionGuideKind SK = SourceDeductionGuideKind::None);
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
@@ -2017,6 +2037,25 @@ class CXXDeductionGuideDecl : public FunctionDecl {
/// this is an implicit deduction guide.
CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; }
+ /// Get the deduction guide from which this deduction guide was generated,
+ /// if it was generated as part of alias template deduction or from an
+ /// inherited constructor.
+ const CXXDeductionGuideDecl *getSourceDeductionGuide() const {
+ return SourceDeductionGuide.getPointer();
+ }
+
+ void setSourceDeductionGuide(CXXDeductionGuideDecl *DG) {
+ SourceDeductionGuide.setPointer(DG);
+ }
+
+ SourceDeductionGuideKind getSourceDeductionGuideKind() const {
+ return SourceDeductionGuide.getInt();
+ }
+
+ void setSourceDeductionGuideKind(SourceDeductionGuideKind SK) {
+ SourceDeductionGuide.setInt(SK);
+ }
+
void setDeductionCandidateKind(DeductionCandidate K) {
FunctionDeclBits.DeductionCandidateKind = static_cast(K);
}
@@ -4136,8 +4175,9 @@ class BindingDecl : public ValueDecl {
/// binding).
Expr *Binding = nullptr;
- BindingDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id)
- : ValueDecl(Decl::Binding, DC, IdLoc, Id, QualType()) {}
+ BindingDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T)
+ : ValueDecl(Decl::Binding, DC, IdLoc, Id, T) {}
void anchor() override;
@@ -4145,7 +4185,8 @@ class BindingDecl : public ValueDecl {
friend class ASTDeclReader;
static BindingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation IdLoc, IdentifierInfo *Id);
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T);
static BindingDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Get the expression to which this declaration is bound. This may be null
@@ -4153,14 +4194,13 @@ class BindingDecl : public ValueDecl {
/// decomposition declaration, and when the initializer is type-dependent.
Expr *getBinding() const { return Binding; }
+ // Get the array of Exprs when the binding represents a pack.
+ llvm::ArrayRef getBindingPackExprs() const;
+
/// Get the decomposition declaration that this binding represents a
/// decomposition of.
ValueDecl *getDecomposedDecl() const { return Decomp; }
- /// Get the variable (if any) that holds the value of evaluating the binding.
- /// Only present for user-defined bindings for tuple-like types.
- VarDecl *getHoldingVar() const;
-
/// Set the binding for this BindingDecl, along with its declared type (which
/// should be a possibly-cv-qualified form of the type of the binding, or a
/// reference to such a type).
@@ -4172,6 +4212,10 @@ class BindingDecl : public ValueDecl {
/// Set the decomposed variable for this BindingDecl.
void setDecomposedDecl(ValueDecl *Decomposed) { Decomp = Decomposed; }
+ /// Get the variable (if any) that holds the value of evaluating the binding.
+ /// Only present for user-defined bindings for tuple-like types.
+ VarDecl *getHoldingVar() const;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::Binding; }
};
@@ -4199,8 +4243,16 @@ class DecompositionDecl final
NumBindings(Bindings.size()) {
std::uninitialized_copy(Bindings.begin(), Bindings.end(),
getTrailingObjects());
- for (auto *B : Bindings)
+ for (auto *B : Bindings) {
B->setDecomposedDecl(this);
+ if (B->isParameterPack() && B->getBinding()) {
+ for (Expr *E : B->getBindingPackExprs()) {
+ auto *DRE = cast(E);
+ auto *NestedB = cast(DRE->getDecl());
+ NestedB->setDecomposedDecl(this);
+ }
+ }
+ }
}
void anchor() override;
@@ -4218,8 +4270,33 @@ class DecompositionDecl final
static DecompositionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumBindings);
- ArrayRef bindings() const {
- return llvm::ArrayRef(getTrailingObjects(), NumBindings);
+ // Provide the range of bindings which may have a nested pack.
+ llvm::ArrayRef bindings() const {
+ return {getTrailingObjects(), NumBindings};
+ }
+
+ // Provide a flattened range to visit each binding.
+ auto flat_bindings() const {
+ llvm::ArrayRef Bindings = bindings();
+ llvm::ArrayRef PackExprs;
+
+ // Split the bindings into subranges split by the pack.
+ auto S1 = Bindings.take_until(
+ [](BindingDecl *BD) { return BD->isParameterPack(); });
+
+ Bindings = Bindings.drop_front(S1.size());
+ if (!Bindings.empty()) {
+ PackExprs = Bindings.front()->getBindingPackExprs();
+ Bindings = Bindings.drop_front();
+ }
+
+ auto S2 = llvm::map_range(PackExprs, [](Expr *E) {
+ auto *DRE = cast(E);
+ return cast(DRE->getDecl());
+ });
+
+ return llvm::concat(std::move(S1), std::move(S2),
+ std::move(Bindings));
}
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 8c2da97c07a3b..b82f75dd63fa5 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1011,6 +1011,26 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
return getTemplatedDecl()->isThisDeclarationADefinition();
}
+ bool isCompatibleWithDefinition() const {
+ return getTemplatedDecl()->isInstantiatedFromMemberTemplate() ||
+ isThisDeclarationADefinition();
+ }
+
+ // This bit closely tracks 'RedeclarableTemplateDecl::InstantiatedFromMember',
+ // except this is per declaration, while the redeclarable field is
+ // per chain. This indicates a template redeclaration which
+ // is compatible with the definition, in the non-trivial case
+ // where this is not already a definition.
+ // This is only really needed for instantiating the definition of friend
+ // function templates, which can have redeclarations in different template
+ // contexts.
+ // The bit is actually stored in the FunctionDecl for space efficiency
+ // reasons.
+ void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *D) {
+ getTemplatedDecl()->setInstantiatedFromMemberTemplate();
+ RedeclarableTemplateDecl::setInstantiatedFromMemberTemplate(D);
+ }
+
/// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
FunctionDecl *findSpecialization(ArrayRef Args,
@@ -1841,15 +1861,23 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
LLVM_PREFERRED_TYPE(TemplateSpecializationKind)
unsigned SpecializationKind : 3;
+ /// Indicate that we have matched a parameter pack with a non pack
+ /// argument, when the opposite match is also allowed.
+ /// This needs to be cached as deduction is performed during declaration,
+ /// and we need the information to be preserved so that it is consistent
+ /// during instantiation.
+ bool StrictPackMatch : 1;
+
protected:
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate,
ArrayRef Args,
+ bool StrictPackMatch,
ClassTemplateSpecializationDecl *PrevDecl);
- explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
+ ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
public:
friend class ASTDeclReader;
@@ -1859,7 +1887,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate,
- ArrayRef Args,
+ ArrayRef Args, bool StrictPackMatch,
ClassTemplateSpecializationDecl *PrevDecl);
static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
@@ -1930,6 +1958,10 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
SpecializationKind = TSK;
}
+ bool hasStrictPackMatch() const { return StrictPackMatch; }
+
+ void setStrictPackMatch(bool Val) { StrictPackMatch = Val; }
+
/// Get the point of instantiation (if any), or null if none.
SourceLocation getPointOfInstantiation() const {
return PointOfInstantiation;
@@ -2009,7 +2041,8 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// Retrieve the template argument list as written in the sources,
/// if any.
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
return Info->TemplateArgsAsWritten;
return cast(ExplicitInfo);
}
@@ -2017,7 +2050,8 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// Set the template argument list as written in the sources.
void
setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
Info->TemplateArgsAsWritten = ArgsWritten;
else
ExplicitInfo = ArgsWritten;
@@ -2031,7 +2065,8 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// Gets the location of the extern keyword, if present.
SourceLocation getExternKeywordLoc() const {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
return Info->ExternKeywordLoc;
return SourceLocation();
}
@@ -2041,7 +2076,8 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
return Info->TemplateKeywordLoc;
return SourceLocation();
}
@@ -2778,7 +2814,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Retrieve the template argument list as written in the sources,
/// if any.
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
return Info->TemplateArgsAsWritten;
return cast(ExplicitInfo);
}
@@ -2786,7 +2823,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Set the template argument list as written in the sources.
void
setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
Info->TemplateArgsAsWritten = ArgsWritten;
else
ExplicitInfo = ArgsWritten;
@@ -2800,7 +2838,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Gets the location of the extern keyword, if present.
SourceLocation getExternKeywordLoc() const {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
return Info->ExternKeywordLoc;
return SourceLocation();
}
@@ -2810,7 +2849,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
- if (auto *Info = ExplicitInfo.dyn_cast())
+ if (auto *Info =
+ dyn_cast_if_present(ExplicitInfo))
return Info->TemplateKeywordLoc;
return SourceLocation();
}
diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
index 4382d20990829..703cca22777ad 100644
--- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h
@@ -52,7 +52,11 @@ class ASTContext;
/// WalkUpFromX or post-order traversal).
///
/// \see RecursiveASTVisitor.
-class DynamicRecursiveASTVisitor {
+template class DynamicRecursiveASTVisitorBase {
+protected:
+ template
+ using MaybeConst = std::conditional_t;
+
public:
/// Whether this visitor should recurse into template instantiations.
bool ShouldVisitTemplateInstantiations = false;
@@ -68,28 +72,29 @@ class DynamicRecursiveASTVisitor {
bool ShouldVisitLambdaBody = true;
protected:
- DynamicRecursiveASTVisitor() = default;
- DynamicRecursiveASTVisitor(DynamicRecursiveASTVisitor &&) = default;
- DynamicRecursiveASTVisitor(const DynamicRecursiveASTVisitor &) = default;
- DynamicRecursiveASTVisitor &
- operator=(DynamicRecursiveASTVisitor &&) = default;
- DynamicRecursiveASTVisitor &
- operator=(const DynamicRecursiveASTVisitor &) = default;
+ DynamicRecursiveASTVisitorBase() = default;
+ DynamicRecursiveASTVisitorBase(DynamicRecursiveASTVisitorBase &&) = default;
+ DynamicRecursiveASTVisitorBase(const DynamicRecursiveASTVisitorBase &) =
+ default;
+ DynamicRecursiveASTVisitorBase &
+ operator=(DynamicRecursiveASTVisitorBase &&) = default;
+ DynamicRecursiveASTVisitorBase &
+ operator=(const DynamicRecursiveASTVisitorBase &) = default;
public:
virtual void anchor();
- virtual ~DynamicRecursiveASTVisitor() = default;
+ virtual ~DynamicRecursiveASTVisitorBase() = default;
/// Recursively visits an entire AST, starting from the TranslationUnitDecl.
/// \returns false if visitation was terminated early.
- virtual bool TraverseAST(ASTContext &AST);
+ virtual bool TraverseAST(MaybeConst &AST);
/// Recursively visit an attribute, by dispatching to
/// Traverse*Attr() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is a Null type location).
- virtual bool TraverseAttr(Attr *At);
+ virtual bool TraverseAttr(MaybeConst *At);
/// Recursively visit a constructor initializer. This
/// automatically dispatches to another visitor for the initializer
@@ -97,7 +102,8 @@ class DynamicRecursiveASTVisitor {
/// be overridden for clients that need access to the name.
///
/// \returns false if the visitation was terminated early, true otherwise.
- virtual bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
+ virtual bool
+ TraverseConstructorInitializer(MaybeConst *Init);
/// Recursively visit a base specifier. This can be overridden by a
/// subclass.
@@ -110,7 +116,7 @@ class DynamicRecursiveASTVisitor {
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is NULL).
- virtual bool TraverseDecl(Decl *D);
+ virtual bool TraverseDecl(MaybeConst *D);
/// Recursively visit a name with its location information.
///
@@ -121,13 +127,15 @@ class DynamicRecursiveASTVisitor {
/// will be used to initialize the capture.
///
/// \returns false if the visitation was terminated early, true otherwise.
- virtual bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
- Expr *Init);
+ virtual bool TraverseLambdaCapture(MaybeConst *LE,
+ const LambdaCapture *C,
+ MaybeConst *Init);
/// Recursively visit a C++ nested-name-specifier.
///
/// \returns false if the visitation was terminated early, true otherwise.
- virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+ virtual bool
+ TraverseNestedNameSpecifier(MaybeConst *NNS);
/// Recursively visit a C++ nested-name-specifier with location
/// information.
@@ -140,7 +148,7 @@ class DynamicRecursiveASTVisitor {
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is nullptr).
- virtual bool TraverseStmt(Stmt *S);
+ virtual bool TraverseStmt(MaybeConst *S);
/// Recursively visit a template argument and dispatch to the
/// appropriate method for the argument type.
@@ -190,41 +198,51 @@ class DynamicRecursiveASTVisitor {
/// Traverse a concept (requirement).
virtual bool TraverseTypeConstraint(const TypeConstraint *C);
- virtual bool TraverseConceptRequirement(concepts::Requirement *R);
- virtual bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
- virtual bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
- virtual bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
- virtual bool TraverseConceptReference(ConceptReference *CR);
- virtual bool VisitConceptReference(ConceptReference *CR) { return true; }
+ virtual bool TraverseConceptRequirement(MaybeConst *R);
+
+ virtual bool
+ TraverseConceptTypeRequirement(MaybeConst *R);
+
+ virtual bool
+ TraverseConceptExprRequirement(MaybeConst *R);
+
+ virtual bool
+ TraverseConceptNestedRequirement(MaybeConst *R);
+
+ virtual bool TraverseConceptReference(MaybeConst *CR);
+ virtual bool VisitConceptReference(MaybeConst *CR) {
+ return true;
+ }
/// Visit a node.
- virtual bool VisitAttr(Attr *A) { return true; }
- virtual bool VisitDecl(Decl *D) { return true; }
- virtual bool VisitStmt(Stmt *S) { return true; }
- virtual bool VisitType(Type *T) { return true; }
+ virtual bool VisitAttr(MaybeConst *A) { return true; }
+ virtual bool VisitDecl(MaybeConst *D) { return true; }
+ virtual bool VisitStmt(MaybeConst *S) { return true; }
+ virtual bool VisitType(MaybeConst *T) { return true; }
virtual bool VisitTypeLoc(TypeLoc TL) { return true; }
/// Walk up from a node.
- bool WalkUpFromDecl(Decl *D) { return VisitDecl(D); }
- bool WalkUpFromStmt(Stmt *S) { return VisitStmt(S); }
- bool WalkUpFromType(Type *T) { return VisitType(T); }
+ bool WalkUpFromDecl(MaybeConst *D) { return VisitDecl(D); }
+ bool WalkUpFromStmt(MaybeConst *S) { return VisitStmt(S); }
+ bool WalkUpFromType(MaybeConst *T) { return VisitType(T); }
bool WalkUpFromTypeLoc(TypeLoc TL) { return VisitTypeLoc(TL); }
/// Invoked before visiting a statement or expression via data recursion.
///
/// \returns false to skip visiting the node, true otherwise.
- virtual bool dataTraverseStmtPre(Stmt *S) { return true; }
+ virtual bool dataTraverseStmtPre(MaybeConst *S) { return true; }
/// Invoked after visiting a statement or expression via data recursion.
/// This is not invoked if the previously invoked \c dataTraverseStmtPre
/// returned false.
///
/// \returns false if the visitation was terminated early, true otherwise.
- virtual bool dataTraverseStmtPost(Stmt *S) { return true; }
- virtual bool dataTraverseNode(Stmt *S);
+ virtual bool dataTraverseStmtPost(MaybeConst *S) { return true; }
+ virtual bool dataTraverseNode(MaybeConst *S);
#define DEF_TRAVERSE_TMPL_INST(kind) \
- virtual bool TraverseTemplateInstantiations(kind##TemplateDecl *D);
+ virtual bool TraverseTemplateInstantiations( \
+ MaybeConst *D);
DEF_TRAVERSE_TMPL_INST(Class)
DEF_TRAVERSE_TMPL_INST(Var)
DEF_TRAVERSE_TMPL_INST(Function)
@@ -232,32 +250,34 @@ class DynamicRecursiveASTVisitor {
// Decls.
#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) virtual bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#define DECL(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##Decl(MaybeConst *D); \
+ virtual bool Traverse##CLASS##Decl(MaybeConst *D);
#include "clang/AST/DeclNodes.inc"
#define DECL(CLASS, BASE) \
- bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D); \
- virtual bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
+ virtual bool Visit##CLASS##Decl(MaybeConst *D) { return true; }
#include "clang/AST/DeclNodes.inc"
// Stmts.
#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(CLASS *S);
+#define STMT(CLASS, PARENT) virtual bool Traverse##CLASS(MaybeConst *S);
#include "clang/AST/StmtNodes.inc"
#define STMT(CLASS, PARENT) \
- bool WalkUpFrom##CLASS(CLASS *S); \
- virtual bool Visit##CLASS(CLASS *S) { return true; }
+ bool WalkUpFrom##CLASS(MaybeConst *S); \
+ virtual bool Visit##CLASS(MaybeConst *S) { return true; }
#include "clang/AST/StmtNodes.inc"
// Types.
#define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE) virtual bool Traverse##CLASS##Type(CLASS##Type *T);
+#define TYPE(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##Type(MaybeConst *T); \
+ virtual bool Traverse##CLASS##Type(MaybeConst *T);
#include "clang/AST/TypeNodes.inc"
#define TYPE(CLASS, BASE) \
- bool WalkUpFrom##CLASS##Type(CLASS##Type *T); \
- virtual bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
+ virtual bool Visit##CLASS##Type(MaybeConst *T) { return true; }
#include "clang/AST/TypeNodes.inc"
// TypeLocs.
@@ -271,6 +291,14 @@ class DynamicRecursiveASTVisitor {
virtual bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
#include "clang/AST/TypeLocNodes.def"
};
+
+extern template class DynamicRecursiveASTVisitorBase;
+extern template class DynamicRecursiveASTVisitorBase;
+
+using DynamicRecursiveASTVisitor =
+ DynamicRecursiveASTVisitorBase*Const=*/false>;
+using ConstDynamicRecursiveASTVisitor =
+ DynamicRecursiveASTVisitorBase*Const=*/true>;
} // namespace clang
#endif // LLVM_CLANG_AST_DYNAMIC_RECURSIVE_AST_VISITOR_H
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 708c8656decbe..cd584d9621a22 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -5180,7 +5180,7 @@ class InitListExpr : public Expr {
/// than there are initializers in the list, specifies an expression to be
/// used for value initialization of the rest of the elements.
Expr *getArrayFiller() {
- return ArrayFillerOrUnionFieldInit.dyn_cast();
+ return dyn_cast_if_present(ArrayFillerOrUnionFieldInit);
}
const Expr *getArrayFiller() const {
return const_cast(this)->getArrayFiller();
@@ -5205,7 +5205,7 @@ class InitListExpr : public Expr {
/// union. However, a designated initializer can specify the
/// initialization of a different field within the union.
FieldDecl *getInitializedFieldInUnion() {
- return ArrayFillerOrUnionFieldInit.dyn_cast();
+ return dyn_cast_if_present(ArrayFillerOrUnionFieldInit);
}
const FieldDecl *getInitializedFieldInUnion() const {
return const_cast(this)->getInitializedFieldInUnion();
@@ -6678,7 +6678,6 @@ class PseudoObjectExpr final
class AtomicExpr : public Expr {
public:
enum AtomicOp {
-#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID,
#include "clang/Basic/Builtins.inc"
// Avoid trailing comma
@@ -6742,7 +6741,6 @@ class AtomicExpr : public Expr {
AtomicOp getOp() const { return Op; }
StringRef getOpAsString() const {
switch (Op) {
-#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
case AO##ID: \
return #ID;
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 4cec89c979f77..98ba2bb41bb54 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2847,8 +2847,8 @@ class TypeTraitExpr final
///
/// Example:
/// \code
-/// __array_rank(int[10][20]) == 2
-/// __array_extent(int, 1) == 20
+/// __array_rank(int[10][20]) == 2
+/// __array_extent(int[10][20], 1) == 20
/// \endcode
class ArrayTypeTraitExpr : public Expr {
/// The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
@@ -4326,8 +4326,6 @@ class SizeOfPackExpr final
/// Retrieve the parameter pack.
NamedDecl *getPack() const { return Pack; }
- void setPack(NamedDecl *NewPack) { Pack = NewPack; }
-
/// Retrieve the length of the parameter pack.
///
/// This routine may only be invoked when the expression is not
@@ -5026,11 +5024,11 @@ class CXXParenListInitExpr final
void setArrayFiller(Expr *E) { ArrayFillerOrUnionFieldInit = E; }
Expr *getArrayFiller() {
- return ArrayFillerOrUnionFieldInit.dyn_cast();
+ return dyn_cast_if_present(ArrayFillerOrUnionFieldInit);
}
const Expr *getArrayFiller() const {
- return ArrayFillerOrUnionFieldInit.dyn_cast();
+ return dyn_cast_if_present