Compare commits

..

14 Commits

Author SHA1 Message Date
Sergio Afonso
bdd6b36a93 [OMPIRBuilder] Add support for explicit deallocation points
In this patch, some OMPIRBuilder codegen functions and callbacks are updated to
work with arrays of deallocation insertion points. The purpose of this is to
enable the replacement of `alloca`s with other types of allocations that
require explicit deallocations in a way that makes it possible for
`CodeExtractor` instances created during OMPIRBuilder finalization to also use
them.

The OpenMP to LLVM IR MLIR translation pass is updated to properly store and
forward deallocation points together with their matching allocation point to
the OMPIRBuilder.

Currently, only the `DeviceSharedMemCodeExtractor` uses this feature to get the
`CodeExtractor` to use device shared memory for intermediate allocations when
outlining a parallel region inside of a Generic kernel (code path that is only
used by Flang via MLIR, currently). However, long term this might also be
useful to refactor finalization of variables with destructors, potentially
reducing the use of callbacks and simplifying privatization and reductions.

Instead of a single deallocation point, lists of those are used. This is to
cover cases where there are multiple exit blocks originating from a single
entry. If an allocation needing explicit deallocation is placed in the entry
block of such cases, it would need to be deallocated before each of the exits.
2025-08-21 14:06:32 +01:00
Sergio Afonso
2d33426786 Address review comments 2025-08-15 15:50:06 +01:00
Sergio Afonso
38a38bb056 [OpenMPOpt] Make parallel regions reachable from new DeviceRTL loop functions
This patch updates the OpenMP optimization pass to know about the new DeviceRTL
functions for loop constructs.

This change marks these functions as potentially containing parallel regions,
which fixes a current bug with the state machine rewrite optimization. It
previously failed to identify parallel regions located inside of the callbacks
passed to these new DeviceRTL functions, causing the resulting code to skip
executing these parallel regions.

As a result, Generic kernels produced by Flang that contain parallel regions
now work properly.

One known related issue not fixed by this patch is that the presence of calls
to these functions will prevent the SPMD-ization of Generic kernels by
OpenMPOpt. Previously, this was due to assuming there was no parallel region.
This is changed by this patch, but instead we now mark it temporarily as
unsupported in an SPMD context. The reason is that, without additional changes,
code intended for the main thread of the team located outside of the parallel
region would not be guarded properly, resulting in race conditions and
generally invalid behavior.
2025-08-15 15:50:06 +01:00
Sergio Afonso
e57c671e6f Address review comments 2025-08-15 15:49:47 +01:00
Sergio Afonso
bd81572292 [OpenMP][OMPIRBuilder] Support parallel in Generic kernels
This patch introduces codegen logic to produce a wrapper function argument for
the `__kmpc_parallel_51` DeviceRTL function needed to handle arguments passed
using device shared memory in Generic mode.
2025-08-15 15:49:47 +01:00
Sergio Afonso
be955670bb Replace CodeExtractor callbacks with subclasses and simplify their creation based on OutlineInfo structures 2025-08-15 15:49:17 +01:00
Sergio Afonso
06a2570f2b Address nits 2025-08-14 12:40:09 +01:00
Sergio Afonso
4da11cfd7d Address intermittent ICE triggered from the OpenMPIRBuilder::finalize method due to an invalid builder insertion point 2025-08-13 14:36:52 +01:00
Sergio Afonso
688b61435b [OpenMP][OMPIRBuilder] Use device shared memory for arg structures
Argument structures are created when sections of the LLVM IR corresponding to
an OpenMP construct are outlined into their own function. For this, stack
allocations are used.

This patch modifies this behavior when compiling for a target device and
outlining `parallel`-related IR, so that it uses device shared memory instead
of private stack space. This is needed in order for threads to have access to
these arguments.
2025-08-13 14:36:51 +01:00
Sergio Afonso
1b7dd6ce24 Address review comments 2025-08-13 14:17:47 +01:00
Sergio Afonso
5a73674be8 [MLIR][OpenMP] Support allocations of device shared memory
This patch updates the allocation of some reduction and private variables
within target regions to use device shared memory rather than private memory.
This is a prerequisite to produce working Generic kernels containing parallel
regions.

In particular, the following situations result in the usage of device shared
memory (only when compiling for the target device if they are placed inside of
a target region representing a Generic kernel):
- Reduction variables on `teams` constructs.
- Private variables on `teams` and `distribute` constructs that are reduced or
used inside of a `parallel` region.

Currently, there is no support for delayed privatization on `teams` constructs,
so private variables on these constructs won't currently be affected. When
support is added, if it uses the existing `allocatePrivateVars` and
`cleanupPrivateVars` functions, usage of device shared memory will be
introduced automatically.
2025-08-13 13:27:32 +01:00
Sergio Afonso
94936248fd [OpenMP][OMPIRBuilder] Add device shared memory allocation support
This patch adds the `__kmpc_alloc_shared` and `__kmpc_free_shared` DeviceRTL
functions to the list of those the OMPIRBuilder is able to create.
2025-08-13 12:54:48 +01:00
Sergio Afonso
9e948a58af Update TargetRegionFlags to mirror OMPTgtExecModeFlags 2025-08-13 12:53:34 +01:00
Sergio Afonso
39800face1 [MLIR][OpenMP] Remove Generic-SPMD early detection
This patch removes logic from MLIR to attempt identifying Generic kernels that
could be executed in SPMD mode.

This optimization is done by the OpenMPOpt pass for Clang and is only required
here to circumvent missing support for the new DeviceRTL APIs used in MLIR to
LLVM IR translation that Clang doesn't currently use (e.g.
`kmpc_distribute_static_loop` ). Removing checks in MLIR avoids duplicating the
logic that should be centralized in the OpenMPOpt pass.

Additionally, offloading kernels currently compiled through the OpenMP dialect
fail to run parallel regions properly when in Generic mode. By disabling early
detection, this issue becomes apparent for a range of kernels where this was
masked by having them run in SPMD mode.
2025-08-12 16:49:37 +01:00
5467 changed files with 107018 additions and 270112 deletions

View File

@ -49,7 +49,8 @@ DEPENDENTS_TO_TEST = {
"flang",
},
"lld": {"bolt", "cross-project-tests"},
"clang": {"clang-tools-extra", "cross-project-tests", "lldb"},
# TODO(issues/132795): LLDB should be enabled on clang changes.
"clang": {"clang-tools-extra", "cross-project-tests"},
"mlir": {"flang"},
# Test everything if ci scripts are changed.
".ci": {

View File

@ -83,11 +83,11 @@ class TestComputeProjects(unittest.TestCase):
)
self.assertEqual(
env_variables["projects_to_build"],
"clang;clang-tools-extra;lld;lldb;llvm",
"clang;clang-tools-extra;lld;llvm",
)
self.assertEqual(
env_variables["project_check_targets"],
"check-clang check-clang-tools check-lldb",
"check-clang check-clang-tools",
)
self.assertEqual(
env_variables["runtimes_to_build"], "compiler-rt;libcxx;libcxxabi;libunwind"
@ -158,11 +158,11 @@ class TestComputeProjects(unittest.TestCase):
)
self.assertEqual(
env_variables["projects_to_build"],
"clang;clang-tools-extra;lld;lldb;llvm;mlir",
"clang;clang-tools-extra;lld;llvm;mlir",
)
self.assertEqual(
env_variables["project_check_targets"],
"check-clang check-clang-cir check-clang-tools check-lldb",
"check-clang check-clang-cir check-clang-tools",
)
self.assertEqual(
env_variables["runtimes_to_build"], "compiler-rt;libcxx;libcxxabi;libunwind"

View File

@ -60,8 +60,7 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
-D MLIR_ENABLE_BINDINGS_PYTHON=ON \
-D LLDB_ENABLE_PYTHON=ON \
-D LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS=ON \
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
-D CMAKE_EXE_LINKER_FLAGS="-no-pie"
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
start-group "ninja"

View File

@ -24,7 +24,6 @@ function at-exit {
retcode=$?
mkdir -p artifacts
sccache --show-stats
sccache --show-stats >> artifacts/sccache_stats.txt
cp "${BUILD_DIR}"/.ninja_log artifacts/.ninja_log
cp "${MONOREPO_ROOT}"/*.log artifacts/ || :

View File

@ -90,6 +90,9 @@ LTO:
- llvm/lib/Transforms/*/FunctionImport*
- llvm/tools/gold/**
mc:
- llvm/*/MC/**
clang:driver:
- clang/*/Driver/**
@ -618,12 +621,6 @@ llvm:adt:
llvm:support:
- llvm/**/Support/**
# Skip llvm/test/MC and llvm/unittests/MC, which includes target-specific directories.
llvm:mc:
- llvm/include/llvm/MC/**
- llvm/lib/MC/**
- llvm/tools/llvm-mc/**
llvm:transforms:
- llvm/lib/Transforms/**
- llvm/include/llvm/Transforms/**

View File

@ -1,32 +0,0 @@
name: Bazel Checks
permissions:
contents: read
on:
push:
paths:
- '.github/workflows/bazel-checks.yml'
- 'utils/bazel/**'
branches:
- main
pull_request:
paths:
- '.github/workflows/bazel-checks.yml'
- 'utils/bazel/**'
jobs:
buildifier:
name: "Buildifier"
runs-on: ubuntu-24.04
if: github.repository == 'llvm/llvm-project'
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Buildifier
run: |
sudo curl -L https://github.com/bazelbuild/buildtools/releases/download/v8.2.1/buildifier-linux-amd64 -o /usr/bin/buildifier
sudo chmod +x /usr/bin/buildifier
- name: Run Buildifier
run: |
buildifier --mode=check $(find ./utils/bazel -name *BUILD*)

View File

@ -25,7 +25,7 @@ jobs:
container-filename: ${{ steps.vars.outputs.container-filename }}
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/workflows/containers/github-action-ci-windows
- name: Write Variables

View File

@ -30,7 +30,7 @@ jobs:
runs-on: depot-ubuntu-24.04-arm-16
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/workflows/containers/github-action-ci/
# podman is not installed by default on the ARM64 images.

View File

@ -27,7 +27,7 @@ jobs:
container-filename: ${{ steps.vars.outputs.container-filename }}
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .ci/metrics/
- name: Write Variables

View File

@ -22,7 +22,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .ci
- name: Setup Python

View File

@ -41,7 +41,7 @@ jobs:
LLVM_VERSION: 18
steps:
- name: Checkout Source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup ccache
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17

View File

@ -18,7 +18,7 @@ jobs:
github.event.label.name == 'infra:commit-access-request'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
sparse-checkout: llvm/utils/git/

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install dependencies
run: |

View File

@ -90,7 +90,7 @@ RUN powershell -Command \
RUN git config --system core.longpaths true & \
git config --global core.autocrlf false
ARG RUNNER_VERSION=2.328.0
ARG RUNNER_VERSION=2.327.1
ENV RUNNER_VERSION=$RUNNER_VERSION
RUN powershell -Command \

View File

@ -81,8 +81,6 @@ RUN curl -L 'https://github.com/mozilla/sccache/releases/download/v0.10.0/sccach
ENV LLVM_SYSROOT=$LLVM_SYSROOT
ENV PATH=${LLVM_SYSROOT}/bin:${PATH}
ENV CC=clang
ENV CXX=clang++
# Create a new user to avoid test failures related to a lack of expected
# permissions issues in some tests. Set the user id to 1001 as that is the
@ -99,7 +97,7 @@ WORKDIR /home/gha
FROM ci-container as ci-container-agent
ENV GITHUB_RUNNER_VERSION=2.328.0
ENV GITHUB_RUNNER_VERSION=2.327.1
RUN mkdir actions-runner && \
cd actions-runner && \

View File

@ -55,7 +55,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 2
- name: Get subprojects that have doc changes

View File

@ -14,7 +14,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}

View File

@ -29,25 +29,25 @@ jobs:
runs-on: ${{ inputs.SKU }}
steps:
- name: Checkout DXC
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: Microsoft/DirectXShaderCompiler
ref: main
path: DXC
submodules: true
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ inputs.LLVM-branch }}
path: llvm-project
- name: Checkout OffloadTest
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: llvm/offload-test-suite
ref: main
path: OffloadTest
- name: Checkout Golden Images
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: llvm/offload-golden-images
ref: main

View File

@ -42,7 +42,7 @@ jobs:
contains(github.event.action == 'opened' && github.event.issue.body || github.event.comment.body, '/cherry-pick')
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: llvm/llvm-project
# GitHub stores the token used for checkout and uses it for pushes

View File

@ -14,7 +14,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Checkout Automation Script
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: llvm/utils/git/
ref: main

View File

@ -25,7 +25,7 @@ jobs:
)
steps:
- name: Fetch Sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: |
.github/workflows/unprivileged-download-artifact/action.yml

View File

@ -52,7 +52,7 @@ jobs:
# - c_compiler: gcc
# cpp_compiler: g++
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Libc's build is relatively small comparing with other components of LLVM.
# A fresh fullbuild takes about 190MiB of uncompressed disk space, which can

View File

@ -41,7 +41,7 @@ jobs:
cpp_compiler: clang++
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Libc's build is relatively small comparing with other components of LLVM.
# A fresh linux overlay takes about 180MiB of uncompressed disk space, which can

View File

@ -38,7 +38,7 @@ jobs:
LLVM_VERSION_PATCH: ${{ steps.version.outputs.patch }}
steps:
- name: Checkout source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 250

View File

@ -4,6 +4,7 @@ permissions:
contents: read
on:
workflow_dispatch:
push:
branches:
- 'main'
@ -12,46 +13,29 @@ on:
- 'clang/tools/libclang/**'
- 'clang/CMakeList.txt'
- '.github/workflows/libclang-python-tests.yml'
- '.github/workflows/llvm-project-tests.yml'
pull_request:
paths:
- 'clang/bindings/python/**'
- 'clang/tools/libclang/**'
- 'clang/CMakeList.txt'
- '.github/workflows/libclang-python-tests.yml'
- '.github/workflows/llvm-project-tests.yml'
jobs:
check-clang-python:
# Build libclang and then run the libclang Python binding's unit tests.
# There is an issue running on "windows-2019".
# See https://github.com/llvm/llvm-project/issues/76601#issuecomment-1873049082.
name: Build and run Python unit tests
if: github.repository == 'llvm/llvm-project'
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.13"]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
with:
python-version: ${{ matrix.python-version }}
- name: Setup ccache
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
with:
max-size: 2G
key: spirv-ubuntu-24.04
variant: sccache
- name: Build and Test
run: |
mkdir build
cmake -GNinja \
-S llvm \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache \
-DLLVM_ENABLE_PROJECTS=clang
ninja -C build check-clang-python
uses: ./.github/workflows/llvm-project-tests.yml
with:
build_target: check-clang-python
projects: clang
# There is an issue running on "windows-2019".
# See https://github.com/llvm/llvm-project/issues/76601#issuecomment-1873049082.
os_list: '["ubuntu-24.04"]'
python_version: ${{ matrix.python-version }}

View File

@ -36,7 +36,7 @@ concurrency:
jobs:
stage1:
if: github.repository_owner == 'llvm'
runs-on: llvm-premerge-libcxx-next-runners
runs-on: llvm-premerge-libcxx-runners
continue-on-error: false
strategy:
fail-fast: false
@ -47,14 +47,14 @@ jobs:
'generic-cxx26',
'generic-modules'
]
cc: [ 'clang-22' ]
cxx: [ 'clang++-22' ]
cc: [ 'clang-21' ]
cxx: [ 'clang++-21' ]
include:
- config: 'generic-gcc'
cc: 'gcc-15'
cxx: 'g++-15'
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ${{ matrix.config }}.${{ matrix.cxx }}
run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
env:
@ -73,7 +73,7 @@ jobs:
**/crash_diagnostics/*
stage2:
if: github.repository_owner == 'llvm'
runs-on: llvm-premerge-libcxx-next-runners
runs-on: llvm-premerge-libcxx-runners
needs: [ stage1 ]
continue-on-error: false
strategy:
@ -86,20 +86,20 @@ jobs:
'generic-cxx20',
'generic-cxx23'
]
cc: [ 'clang-22' ]
cxx: [ 'clang++-22' ]
cc: [ 'clang-21' ]
cxx: [ 'clang++-21' ]
include:
- config: 'generic-gcc-cxx11'
cc: 'gcc-15'
cxx: 'g++-15'
- config: 'generic-cxx26'
cc: 'clang-21'
cxx: 'clang++-21'
- config: 'generic-cxx26'
cc: 'clang-20'
cxx: 'clang++-20'
- config: 'generic-cxx26'
cc: 'clang-19'
cxx: 'clang++-19'
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ${{ matrix.config }}
run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
env:
@ -148,27 +148,27 @@ jobs:
'generic-static',
'bootstrapping-build'
]
machine: [ 'llvm-premerge-libcxx-next-runners' ]
machine: [ 'llvm-premerge-libcxx-runners' ]
include:
- config: 'generic-cxx26'
machine: llvm-premerge-libcxx-next-runners
machine: llvm-premerge-libcxx-runners
- config: 'generic-asan'
machine: llvm-premerge-libcxx-next-runners
machine: llvm-premerge-libcxx-runners
- config: 'generic-tsan'
machine: llvm-premerge-libcxx-next-runners
machine: llvm-premerge-libcxx-runners
- config: 'generic-ubsan'
machine: llvm-premerge-libcxx-next-runners
machine: llvm-premerge-libcxx-runners
# Use a larger machine for MSAN to avoid timeout and memory allocation issues.
- config: 'generic-msan'
machine: llvm-premerge-libcxx-next-runners
machine: llvm-premerge-libcxx-runners
runs-on: ${{ matrix.machine }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ${{ matrix.config }}
run: libcxx/utils/ci/run-buildbot ${{ matrix.config }}
env:
CC: clang-22
CXX: clang++-22
CC: clang-21
CXX: clang++-21
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
if: always()
with:
@ -211,7 +211,7 @@ jobs:
os: macos-15
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
# https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
@ -252,7 +252,7 @@ jobs:
- { config: mingw-dll-i686, mingw: true }
- { config: mingw-incomplete-sysroot, mingw: true }
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install dependencies
run: |
choco install -y ninja

View File

@ -30,7 +30,7 @@ jobs:
packages: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build the Linux builder image
working-directory: libcxx/utils/ci

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install dependencies
uses: aminya/setup-cpp@17c11551771948abc5752bbf3183482567c7caf0 # v1.1.1

149
.github/workflows/llvm-project-tests.yml vendored Normal file
View File

@ -0,0 +1,149 @@
name: LLVM Project Tests
permissions:
contents: read
on:
workflow_dispatch:
inputs:
build_target:
required: false
projects:
required: false
extra_cmake_args:
required: false
os_list:
required: false
default: '["ubuntu-24.04", "windows-2019", "macOS-13"]'
python_version:
required: false
type: string
default: '3.11'
workflow_call:
inputs:
build_target:
required: false
type: string
default: "all"
projects:
required: true
type: string
extra_cmake_args:
required: false
type: string
os_list:
required: false
type: string
# Use windows-2019 due to:
# https://developercommunity.visualstudio.com/t/Prev-Issue---with-__assume-isnan-/1597317
default: '["ubuntu-24.04", "windows-2019", "macOS-13"]'
python_version:
required: false
type: string
default: '3.11'
concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
# If the group name here is the same as the group name in the workflow that includes
# this one, then the action will try to wait on itself and get stuck.
group: llvm-project-${{ github.workflow }}-${{ inputs.projects }}-${{ inputs.python_version }}${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
lit-tests:
name: Lit Tests
runs-on: ${{ matrix.os }}
container:
image: ${{(startsWith(matrix.os, 'ubuntu') && 'ghcr.io/llvm/ci-ubuntu-24.04:latest') || null}}
volumes:
- /mnt/:/mnt/
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON(inputs.os_list) }}
steps:
- name: Setup Windows
if: startsWith(matrix.os, 'windows')
uses: llvm/actions/setup-windows@main
with:
arch: amd64
# On Windows, starting with win19/20220814.1, cmake choose the 32-bit
# python3.10.6 libraries instead of the 64-bit libraries when building
# lldb. Using this setup-python action to make 3.10 the default
# python fixes this.
- name: Setup Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
with:
python-version: ${{ inputs.python_version }}
- name: Install Ninja
if: runner.os != 'Linux'
uses: llvm/actions/install-ninja@main
# actions/checkout deletes any existing files in the new git directory,
# so this needs to either run before ccache-action or it has to use
# clean: false.
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 250
- name: Setup ccache
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
with:
# A full build of llvm, clang, lld, and lldb takes about 250MB
# of ccache space. There's not much reason to have more than this,
# because we usually won't need to save cache entries from older
# builds. Also, there is an overall 10GB cache limit, and each
# run creates a new cache entry so we want to ensure that we have
# enough cache space for all the tests to run at once and still
# fit under the 10 GB limit.
# Default to 2G to workaround: https://github.com/hendrikmuhs/ccache-action/issues/174
max-size: 2G
key: ${{ matrix.os }}
variant: sccache
- name: Build and Test
env:
# Workaround for https://github.com/actions/virtual-environments/issues/5900.
# This should be a no-op for non-mac OSes
PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//12
shell: bash
id: build-llvm
run: |
if [ "${{ runner.os }}" == "Linux" ]; then
builddir="/mnt/build/"
sudo mkdir -p $builddir
sudo chown gha $builddir
extra_cmake_args="-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang"
else
builddir="$(pwd)"/build
fi
if [ "${{ runner.os }}" == "macOS" ]; then
# Workaround test failure on some lld tests on MacOS
# https://github.com/llvm/llvm-project/issues/81967
extra_cmake_args="-DLLVM_DISABLE_ASSEMBLY_FILES=ON"
fi
echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT"
cmake -G Ninja \
-B "$builddir" \
-S llvm \
-DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DLLDB_INCLUDE_TESTS=OFF \
-DLIBCLC_TARGETS_TO_BUILD="amdgcn--;amdgcn--amdhsa;r600--;nvptx--;nvptx64--;nvptx--nvidiacl;nvptx64--nvidiacl" \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache \
$extra_cmake_args \
${{ inputs.extra_cmake_args }}
ninja -C "$builddir" '${{ inputs.build_target }}'
- name: Build and Test libclc
if: "!startsWith(matrix.os, 'windows') && contains(inputs.projects, 'libclc')"
env:
LLVM_BUILDDIR: ${{ steps.build-llvm.outputs.llvm-builddir }}
run: |
# The libclc tests don't have a generated check target so all we can
# do is build it.
ninja -C "$LLVM_BUILDDIR"

View File

@ -0,0 +1,32 @@
# This workflow will test the llvm-project-tests workflow in PRs
# targetting the main branch. Since this workflow doesn't normally
# run on main PRs, we need some way to test it to ensure new updates
# don't break it.
name: LLVM Workflow Test
permissions:
contents: read
on:
pull_request:
branches:
- 'main'
paths:
- '.github/workflows/llvm-project-tests.yml'
- '.github/workflows/llvm-project-workflow-tests.yml'
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:
llvm-test:
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

View File

@ -38,7 +38,7 @@ jobs:
LLVM_VERSION_PATCH: ${{ steps.version.outputs.patch }}
steps:
- name: Checkout source
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 250

View File

@ -21,7 +21,7 @@ jobs:
(github.event.pull_request.merged == true)
steps:
- name: Checkout Automation Script
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: llvm/utils/git/
ref: main

View File

@ -24,28 +24,9 @@ jobs:
check_spirv:
if: github.repository_owner == 'llvm'
name: Test MLIR SPIR-V
runs-on: ubuntu-24.04
container:
image: ghcr.io/llvm/ci-ubuntu-24.04:latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup ccache
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
with:
max-size: 2G
key: spirv-mlir-ubuntu-24.04
variant: sccache
- name: Build and Test
run: |
mkdir build
cmake -GNinja \
-S llvm \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache \
-DLLVM_TARGETS_TO_BUILD="host" \
-DLLVM_INCLUDE_SPIRV_TOOLS_TESTS=ON \
-DLLVM_ENABLE_PROJECTS=mlir
ninja -C build check-mlir
uses: ./.github/workflows/llvm-project-tests.yml
with:
build_target: check-mlir
projects: mlir
extra_cmake_args: '-DLLVM_TARGETS_TO_BUILD="host" -DLLVM_INCLUDE_SPIRV_TOOLS_TESTS=ON'
os_list: '["ubuntu-24.04"]'

View File

@ -35,7 +35,7 @@ jobs:
(github.event.pull_request.author_association != 'OWNER')
steps:
- name: Checkout Automation Script
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: llvm/utils/git/
ref: main

View File

@ -19,7 +19,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 2
@ -35,7 +35,7 @@ jobs:
# We need to pull the script from the main branch, so that we ensure
# we get the latest version of this script.
- name: Fetch code formatting utils
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: ${{ github.repository }}
ref: ${{ github.base_ref }}
@ -70,6 +70,8 @@ jobs:
- name: Run code formatter
env:
GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
START_REV: ${{ github.event.pull_request.base.sha }}
END_REV: ${{ github.event.pull_request.head.sha }}
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
# Create an empty comments file so the pr-write job doesn't fail.
run: |

View File

@ -19,7 +19,7 @@ jobs:
# We need to pull the script from the main branch, so that we ensure
# we get the latest version of this script.
- name: Checkout Scripts
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
sparse-checkout: |
llvm/utils/git/requirements.txt

View File

@ -14,7 +14,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Checkout Automation Script
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: llvm/utils/git/
ref: main

View File

@ -31,7 +31,7 @@ jobs:
runs-on: llvm-premerge-linux-runners
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 2
- name: Build and Test
@ -69,11 +69,6 @@ jobs:
./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}" "${runtimes_check_targets_needs_reconfig}" "${enable_cir}"
- name: Upload Artifacts
# In some cases, Github will fail to upload the artifact. We want to
# continue anyways as a failed artifact upload is an infra failure, not
# a checks failure.
# https://github.com/actions/upload-artifact/issues/569
continue-on-error: true
if: '!cancelled()'
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
@ -93,7 +88,7 @@ jobs:
shell: bash
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 2
- name: Compute Projects
@ -119,11 +114,6 @@ jobs:
# these environment variables.
bash -c "export SCCACHE_GCS_BUCKET=$CACHE_GCS_BUCKET; export SCCACHE_GCS_RW_MODE=READ_WRITE; export SCCACHE_IDLE_TIMEOUT=0; sccache --start-server; .ci/monolithic-windows.sh \"${{ steps.vars.outputs.windows-projects }}\" \"${{ steps.vars.outputs.windows-check-targets }}\""
- name: Upload Artifacts
# In some cases, Github will fail to upload the artifact. We want to
# continue anyways as a failed artifact upload is an infra failure, not
# a checks failure.
# https://github.com/actions/upload-artifact/issues/569
continue-on-error: true
if: '!cancelled()'
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
@ -142,7 +132,7 @@ jobs:
(github.event_name != 'pull_request' || github.event.action != 'closed')
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 2
- name: Setup ccache

View File

@ -23,7 +23,7 @@ jobs:
if: github.repository == 'llvm/llvm-project'
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: |
.github/workflows/release-asset-audit.py

View File

@ -73,7 +73,7 @@ jobs:
python-version: '3.12'
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Install Dependencies
shell: bash
@ -195,7 +195,7 @@ jobs:
steps:
- name: Checkout Actions
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ (github.event_name == 'pull_request' && github.sha) || 'main' }}
sparse-checkout: |
@ -216,7 +216,7 @@ jobs:
run: mv workflows ../workflows-main
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ needs.prepare.outputs.ref }}
@ -286,7 +286,7 @@ jobs:
steps:
- name: Checkout Release Scripts
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
sparse-checkout: |
llvm/utils/release/github-upload-release.py
@ -338,7 +338,7 @@ jobs:
runs-on: ${{ needs.prepare.outputs.test-runs-on }}
steps:
- name: Checkout Actions
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ (github.event_name == 'pull_request' && github.sha) || 'main' }}
sparse-checkout: |

View File

@ -34,7 +34,7 @@ jobs:
upload: ${{ inputs.upload && !contains(inputs.release-version, 'rc') }}
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Python env
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
@ -66,7 +66,7 @@ jobs:
- name: Clone www-releases
if: env.upload
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: ${{ github.repository_owner }}/www-releases
ref: main

View File

@ -40,7 +40,7 @@ jobs:
upload: ${{ inputs.upload && !contains(inputs.release-version, 'rc') }}
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Python env
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0

View File

@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: "llvmorg-${{ inputs.release-version }}"

View File

@ -71,7 +71,7 @@ jobs:
attestations: write
steps:
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ needs.inputs.outputs.ref }}
fetch-tags: true

View File

@ -38,7 +38,7 @@ jobs:
sudo apt-get install python3-github
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Create Release
env:
@ -129,7 +129,7 @@ jobs:
sudo apt-get install python3-github
- name: Checkout LLVM
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
sparse-checkout: llvm/utils/release/github-upload-release.py
sparse-checkout-cone-mode: false

View File

@ -31,7 +31,7 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

View File

@ -4,6 +4,7 @@ permissions:
contents: read
on:
workflow_dispatch:
pull_request:
paths:
- 'llvm/lib/Target/SPIRV/**'
@ -20,27 +21,9 @@ jobs:
check_spirv:
if: github.repository_owner == 'llvm'
name: Test SPIR-V
runs-on: ubuntu-24.04
container:
image: ghcr.io/llvm/ci-ubuntu-24.04:latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup ccache
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
with:
max-size: 2G
key: spirv-ubuntu-24.04
variant: sccache
- name: Build and Test
run: |
mkdir build
cmake -GNinja \
-S llvm \
-B build \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache \
-DLLVM_TARGETS_TO_BUILD="SPIRV" \
-DLLVM_INCLUDE_SPIRV_TOOLS_TESTS=ON
ninja -C build check-llvm-codegen-spirv
uses: ./.github/workflows/llvm-project-tests.yml
with:
build_target: check-llvm-codegen-spirv
projects:
extra_cmake_args: '-DLLVM_TARGETS_TO_BUILD="SPIRV" -DLLVM_INCLUDE_SPIRV_TOOLS_TESTS=ON'
os_list: '["ubuntu-24.04"]'

View File

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Fetch LLVM sources
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0

5
.gitignore vendored
View File

@ -52,11 +52,6 @@ autoconf/autom4te.cache
# CLion project configuration
/.idea
/cmake-build*
# Coding assistants' stuff
/CLAUDE.md
/.claude/
/GEMINI.md
/.gemini/
#==============================================================================#
# Directories to ignore (do not add trailing '/'s, they skip symlinks).

View File

@ -138,12 +138,6 @@
Dump function CFGs to graphviz format after each stage;enable '-print-loops'
for color-coded blocks
- `--dump-dot-func=<func1,func2,func3...>`
Dump function CFGs to graphviz format for specified functions only;
takes function name patterns (regex supported). Note: C++ function names
must be passed using their mangled names
- `--dump-linux-exceptions`
Dump Linux kernel exception table

View File

@ -1196,6 +1196,11 @@ public:
return getSecondaryEntryPointSymbol(BB.getLabel());
}
/// Remove a label from the secondary entry point map.
void removeSymbolFromSecondaryEntryPointMap(const MCSymbol *Label) {
SecondaryEntryPoints.erase(Label);
}
/// Return true if the basic block is an entry point into the function
/// (either primary or secondary).
bool isEntryPoint(const BinaryBasicBlock &BB) const {

View File

@ -740,10 +740,6 @@ public:
return false;
}
/// Return true if the hlt instruction under the x86, otherwise, default to
/// false.
virtual bool isX86HLT(const MCInst &Inst) const { return false; }
/// Return the width, in bytes, of the memory access performed by \p Inst, if
/// this is a pop instruction. Return zero otherwise.
virtual int getPopSize(const MCInst &Inst) const {

View File

@ -241,7 +241,7 @@ private:
/// Adjust function sizes and set proper maximum size values after the whole
/// symbol table has been processed.
void adjustFunctionBoundaries(DenseMap<uint64_t, MarkerSymType> &MarkerSyms);
void adjustFunctionBoundaries();
/// Make .eh_frame section relocatable.
void relocateEHFrameSection();

View File

@ -15,12 +15,6 @@
#include "llvm/Support/CommandLine.h"
namespace llvm {
namespace bolt {
class BinaryFunction;
}
} // namespace llvm
namespace opts {
enum HeatmapModeKind {
@ -106,9 +100,6 @@ extern llvm::cl::opt<unsigned> Verbosity;
/// Return true if we should process all functions in the binary.
bool processAllFunctions();
/// Return true if we should dump dot graphs for the given function.
bool shouldDumpDot(const llvm::bolt::BinaryFunction &Function);
enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;

View File

@ -2517,7 +2517,7 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
// Clean-up the effect of the code emission.
for (const MCSymbol &Symbol : Assembler.symbols()) {
MCSymbol *MutableSymbol = const_cast<MCSymbol *>(&Symbol);
MutableSymbol->setFragment(nullptr);
MutableSymbol->setUndefined();
MutableSymbol->setIsRegistered(false);
}

View File

@ -1915,9 +1915,13 @@ void BinaryFunction::postProcessEntryPoints() {
continue;
// If we have grabbed a wrong code label which actually points to some
// constant island inside the function, ignore this label.
if (isStartOfConstantIsland(Offset))
// constant island inside the function, ignore this label and remove it
// from the secondary entry point map.
if (isStartOfConstantIsland(Offset)) {
BC.SymbolToFunctionMap.erase(Label);
removeSymbolFromSecondaryEntryPointMap(Label);
continue;
}
BC.errs() << "BOLT-WARNING: reference in the middle of instruction "
"detected in function "

View File

@ -30,11 +30,6 @@ using namespace bolt;
using namespace MCPlus;
namespace opts {
cl::opt<bool>
TerminalHLT("terminal-x86-hlt",
cl::desc("Assume that execution stops at x86 HLT instruction"),
cl::init(true), cl::Hidden, cl::cat(BoltCategory));
cl::opt<bool>
TerminalTrap("terminal-trap",
cl::desc("Assume that execution stops at trap instruction"),
@ -137,13 +132,8 @@ bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B,
}
bool MCPlusBuilder::isTerminator(const MCInst &Inst) const {
if (isX86HLT(Inst))
return opts::TerminalHLT;
if (Info->get(Inst.getOpcode()).isTrap())
return opts::TerminalTrap;
return Analysis->isTerminator(Inst);
return Analysis->isTerminator(Inst) ||
(opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap());
}
void MCPlusBuilder::setTailCall(MCInst &Inst) const {

View File

@ -662,7 +662,7 @@ Error CleanMCState::runOnFunctions(BinaryContext &BC) {
if (S->isDefined()) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName()
<< "\" is already defined\n");
const_cast<MCSymbol *>(S)->setFragment(nullptr);
const_cast<MCSymbol *>(S)->setUndefined();
}
if (S->isRegistered()) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName()

View File

@ -52,7 +52,6 @@ namespace opts {
extern cl::opt<bool> PrintAll;
extern cl::opt<bool> PrintDynoStats;
extern cl::opt<bool> DumpDotAll;
extern bool shouldDumpDot(const bolt::BinaryFunction &Function);
extern cl::opt<std::string> AsmDump;
extern cl::opt<bolt::PLTCall::OptType> PLT;
extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
@ -341,7 +340,7 @@ Error BinaryFunctionPassManager::runPasses() {
Function.print(BC.outs(), Message);
if (opts::shouldDumpDot(Function))
if (opts::DumpDotAll)
Function.dumpGraphForPass(PassIdName);
}
}

View File

@ -84,7 +84,6 @@ extern cl::opt<bool> KeepNops;
extern cl::opt<bool> Lite;
extern cl::list<std::string> ReorderData;
extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
extern cl::opt<bool> TerminalHLT;
extern cl::opt<bool> TerminalTrap;
extern cl::opt<bool> TimeBuild;
extern cl::opt<bool> TimeRewrite;
@ -115,35 +114,6 @@ cl::opt<bool> DumpDotAll(
"enable '-print-loops' for color-coded blocks"),
cl::Hidden, cl::cat(BoltCategory));
cl::list<std::string> DumpDotFunc(
"dump-dot-func", cl::CommaSeparated,
cl::desc(
"dump function CFGs to graphviz format for specified functions only;"
"takes function name patterns (regex supported)"),
cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory));
bool shouldDumpDot(const bolt::BinaryFunction &Function) {
// If dump-dot-all is enabled, dump all functions
if (DumpDotAll)
return !Function.isIgnored();
// If no specific functions specified in dump-dot-func, don't dump any
if (DumpDotFunc.empty())
return false;
if (Function.isIgnored())
return false;
// Check if function matches any of the specified patterns
for (const std::string &Name : DumpDotFunc) {
if (Function.hasNameRegex(Name)) {
return true;
}
}
return false;
}
static cl::list<std::string>
ForceFunctionNames("funcs",
cl::CommaSeparated,
@ -910,9 +880,14 @@ void RewriteInstance::discoverFileObjects() {
// code section (see IHI0056B). $d identifies data contents.
// Compilers usually merge multiple data objects in a single $d-$x interval,
// but we need every data object to be marked with $d. Because of that we
// keep track of marker symbols with all locations of data objects.
// create a vector of MarkerSyms with all locations of data objects.
DenseMap<uint64_t, MarkerSymType> MarkerSymbols;
struct MarkerSym {
uint64_t Address;
MarkerSymType Type;
};
std::vector<MarkerSym> SortedMarkerSymbols;
auto addExtraDataMarkerPerSymbol = [&]() {
bool IsData = false;
uint64_t LastAddr = 0;
@ -936,14 +911,14 @@ void RewriteInstance::discoverFileObjects() {
}
if (MarkerType != MarkerSymType::NONE) {
MarkerSymbols[SymInfo.Address] = MarkerType;
SortedMarkerSymbols.push_back(MarkerSym{SymInfo.Address, MarkerType});
LastAddr = SymInfo.Address;
IsData = MarkerType == MarkerSymType::DATA;
continue;
}
if (IsData) {
MarkerSymbols[SymInfo.Address] = MarkerSymType::DATA;
SortedMarkerSymbols.push_back({SymInfo.Address, MarkerSymType::DATA});
LastAddr = SymInfo.Address;
}
}
@ -1308,24 +1283,27 @@ void RewriteInstance::discoverFileObjects() {
BC->setHasSymbolsWithFileName(FileSymbols.size());
// Now that all the functions were created - adjust their boundaries.
adjustFunctionBoundaries(MarkerSymbols);
adjustFunctionBoundaries();
// Annotate functions with code/data markers in AArch64
for (auto &[Address, Type] : MarkerSymbols) {
auto *BF = BC->getBinaryFunctionContainingAddress(Address, true, true);
for (auto ISym = SortedMarkerSymbols.begin();
ISym != SortedMarkerSymbols.end(); ++ISym) {
auto *BF =
BC->getBinaryFunctionContainingAddress(ISym->Address, true, true);
if (!BF) {
// Stray marker
continue;
}
const auto EntryOffset = Address - BF->getAddress();
if (Type == MarkerSymType::CODE) {
const auto EntryOffset = ISym->Address - BF->getAddress();
if (ISym->Type == MarkerSymType::CODE) {
BF->markCodeAtOffset(EntryOffset);
continue;
}
if (Type == MarkerSymType::DATA) {
if (ISym->Type == MarkerSymType::DATA) {
BF->markDataAtOffset(EntryOffset);
BC->AddressToConstantIslandMap[Address] = BF;
BC->AddressToConstantIslandMap[ISym->Address] = BF;
continue;
}
llvm_unreachable("Unknown marker");
@ -1854,8 +1832,7 @@ void RewriteInstance::disassemblePLT() {
}
}
void RewriteInstance::adjustFunctionBoundaries(
DenseMap<uint64_t, MarkerSymType> &MarkerSyms) {
void RewriteInstance::adjustFunctionBoundaries() {
for (auto BFI = BC->getBinaryFunctions().begin(),
BFE = BC->getBinaryFunctions().end();
BFI != BFE; ++BFI) {
@ -1893,15 +1870,12 @@ void RewriteInstance::adjustFunctionBoundaries(
continue;
}
auto It = MarkerSyms.find(NextSymRefI->first);
if (It == MarkerSyms.end() || It->second != MarkerSymType::DATA) {
// This is potentially another entry point into the function.
uint64_t EntryOffset = NextSymRefI->first - Function.getAddress();
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: adding entry point to function "
<< Function << " at offset 0x"
<< Twine::utohexstr(EntryOffset) << '\n');
Function.addEntryPointAtOffset(EntryOffset);
}
// This is potentially another entry point into the function.
uint64_t EntryOffset = NextSymRefI->first - Function.getAddress();
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: adding entry point to function "
<< Function << " at offset 0x"
<< Twine::utohexstr(EntryOffset) << '\n');
Function.addEntryPointAtOffset(EntryOffset);
++NextSymRefI;
}
@ -2203,9 +2177,7 @@ void RewriteInstance::adjustCommandLineOptions() {
if (!opts::KeepNops.getNumOccurrences())
opts::KeepNops = true;
// Linux kernel may resume execution after a trap or x86 HLT instruction.
if (!opts::TerminalHLT.getNumOccurrences())
opts::TerminalHLT = false;
// Linux kernel may resume execution after a trap instruction in some cases.
if (!opts::TerminalTrap.getNumOccurrences())
opts::TerminalTrap = false;
}
@ -3598,7 +3570,7 @@ void RewriteInstance::postProcessFunctions() {
if (opts::PrintAll || opts::PrintCFG)
Function.print(BC->outs(), "after building cfg");
if (opts::shouldDumpDot(Function))
if (opts::DumpDotAll)
Function.dumpGraphForPass("00_build-cfg");
if (opts::PrintLoopInfo) {

View File

@ -223,10 +223,6 @@ public:
return Inst.getOpcode() == X86::ENDBR32 || Inst.getOpcode() == X86::ENDBR64;
}
bool isX86HLT(const MCInst &Inst) const override {
return Inst.getOpcode() == X86::HLT;
}
int getPopSize(const MCInst &Inst) const override {
switch (Inst.getOpcode()) {
case X86::POP16r:

View File

@ -1,38 +0,0 @@
# This test is to ensure that we query data marker symbols to avoid
# misidentifying constant data island symbol as extra entry point.
# RUN: %clang %cflags %s -o %t.so -Wl,-q -Wl,--init=_bar -Wl,--fini=_bar
# RUN: llvm-bolt %t.so -o %t.instr.so
.text
.global _start
.type _start, %function
_start:
ret
.text
.global _foo
.type _foo, %function
_foo:
cbz x1, _foo_2
_foo_1:
add x1, x2, x0
b _foo
_foo_2:
ret
# None of these constant island symbols should be identified as extra entry
# point for function `_foo'.
.align 4
_const1: .short 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80
_const2: .short 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0
_const3: .short 0x04, 0x08, 0x0c, 0x20, 0x60, 0x80, 0xa0, 0xc0
.text
.global _bar
.type _bar, %function
_bar:
ret
# Dummy relocation to force relocation mode
.reloc 0, R_AARCH64_NONE

View File

@ -1,24 +0,0 @@
#include <iostream>
// Multiple functions to test selective dumping
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main_helper() {
std::cout << "Helper function" << std::endl;
return 42;
}
int main_secondary() { return add(5, 3); }
void other_function() { std::cout << "Other function" << std::endl; }
int main() {
int result = add(10, 20);
result = multiply(result, 2);
main_helper();
main_secondary();
other_function();
return result;
}

View File

@ -1,24 +0,0 @@
## Check that HLT instruction is handled differently depending on the flags.
## It's a terminator in the user-level code, but the execution can resume in
## ring 0.
# RUN: %clang %cflags %s -static -o %t.exe -nostdlib
# RUN: llvm-bolt %t.exe --print-cfg --print-only=main --terminal-x86-hlt=0 \
# RUN: -o %t.ring0 2>&1 | FileCheck %s --check-prefix=CHECK-RING0
# RUN: llvm-bolt %t.exe --print-cfg --print-only=main \
# RUN: -o %t.ring3 2>&1 | FileCheck %s --check-prefix=CHECK-RING3
# RUN: llvm-objdump -d %t.ring0 --print-imm-hex | FileCheck %s --check-prefix=CHECK-BIN
# CHECK-RING0: BB Count : 1
# CHECK-RING3: BB Count : 2
# CHECK-BIN: <main>:
# CHECK-BIN-NEXT: f4 hlt
# CHECK-BIN-NEXT: c3 retq
.global main
.type main, %function
main:
hlt
retq
.size main, .-main

View File

@ -1,52 +0,0 @@
# Test the --dump-dot-func option with multiple functions
# (includes tests for both mangled/unmangled names)
RUN: %clang++ %p/Inputs/multi-func.cpp -o %t.exe -Wl,-q
# Test 1: --dump-dot-func with specific function name (mangled)
RUN: llvm-bolt %t.exe -o %t.bolt1 --dump-dot-func=_Z3addii -v=1 2>&1 | FileCheck %s --check-prefix=ADD
# Test 2: --dump-dot-func with regex pattern (main.*)
RUN: llvm-bolt %t.exe -o %t.bolt2 --dump-dot-func="main.*" -v=1 2>&1 | FileCheck %s --check-prefix=MAIN-REGEX
# Test 3: --dump-dot-func with multiple specific functions (mangled names)
RUN: llvm-bolt %t.exe -o %t.bolt3 --dump-dot-func=_Z3addii,_Z8multiplyii -v=1 2>&1 | FileCheck %s --check-prefix=MULTI
# Test 4: No option specified should create no dot files
RUN: llvm-bolt %t.exe -o %t.bolt4 2>&1 | FileCheck %s --check-prefix=NONE
# Test 5: --dump-dot-func with non-existent function
RUN: llvm-bolt %t.exe -o %t.bolt5 --dump-dot-func=nonexistent -v=1 2>&1 | FileCheck %s --check-prefix=NONEXISTENT
# Test 6: Backward compatibility - --dump-dot-all should still work
RUN: llvm-bolt %t.exe -o %t.bolt6 --dump-dot-all -v=1 2>&1 | FileCheck %s --check-prefix=ALL
# Test 7: Test with unmangled function name (main function)
RUN: llvm-bolt %t.exe -o %t.bolt7 --dump-dot-func=main -v=1 2>&1 | FileCheck %s --check-prefix=MAIN-UNMANGLED
# Check that specific functions are dumped
ADD: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to _Z11main_helperv-00_build-cfg.dot
MAIN-REGEX-DAG: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-REGEX-NOT: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MAIN-REGEX-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
MULTI-DAG: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MULTI-DAG: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
MULTI-NOT: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MULTI-NOT: BOLT-INFO: dumping CFG to _Z11main_helperv-00_build-cfg.dot
# Should be no dumping messages when no option is specified
NONE-NOT: BOLT-INFO: dumping CFG
# Should be no dumping messages for non-existent function
NONEXISTENT-NOT: BOLT-INFO: dumping CFG
ALL: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-UNMANGLED: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-UNMANGLED-NOT: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MAIN-UNMANGLED-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot

View File

@ -144,22 +144,17 @@ Error MustacheHTMLGenerator::generateDocs(
} else
return JSONGenerator.takeError();
}
SmallString<128> JSONPath;
sys::path::native(RootDir.str() + "/json", JSONPath);
StringMap<json::Value> JSONFileMap;
{
llvm::TimeTraceScope TS("Iterate JSON files");
std::error_code EC;
sys::fs::directory_iterator JSONIter(JSONPath, EC);
sys::fs::directory_iterator JSONIter(RootDir, EC);
std::vector<json::Value> JSONFiles;
JSONFiles.reserve(Infos.size());
if (EC)
return createStringError("Failed to create directory iterator.");
SmallString<128> HTMLDirPath(RootDir.str() + "/html/");
if (auto EC = sys::fs::create_directories(HTMLDirPath))
return createFileError(HTMLDirPath, EC);
while (JSONIter != sys::fs::directory_iterator()) {
if (EC)
return createFileError("Failed to iterate: " + JSONIter->path(), EC);
@ -182,15 +177,14 @@ Error MustacheHTMLGenerator::generateDocs(
return Parsed.takeError();
std::error_code FileErr;
SmallString<128> HTMLFilePath(HTMLDirPath);
sys::path::append(HTMLFilePath, sys::path::filename(Path));
sys::path::replace_extension(HTMLFilePath, "html");
raw_fd_ostream InfoOS(HTMLFilePath, FileErr, sys::fs::OF_None);
SmallString<16> HTMLPath(Path.begin(), Path.end());
sys::path::replace_extension(HTMLPath, "html");
raw_fd_ostream InfoOS(HTMLPath, FileErr, sys::fs::OF_None);
if (FileErr)
return createFileOpenError(Path, FileErr);
if (Error Err = generateDocForJSON(*Parsed, sys::path::stem(HTMLFilePath),
HTMLFilePath, InfoOS, CDCtx))
if (Error Err = generateDocForJSON(*Parsed, sys::path::stem(HTMLPath),
HTMLPath, InfoOS, CDCtx))
return Err;
JSONIter.increment(EC);
}

View File

@ -600,9 +600,7 @@ Error JSONGenerator::generateDocs(
Info *Info = Group.getValue().get();
SmallString<128> Path;
auto RootDirStr = RootDir.str() + "/json";
StringRef JSONDir = StringRef(RootDirStr);
sys::path::native(JSONDir, Path);
sys::path::native(RootDir, Path);
if (!CreatedDirs.contains(Path)) {
if (std::error_code Err = sys::fs::create_directories(Path);
Err != std::error_code())

View File

@ -424,10 +424,6 @@ ClangTidyASTConsumerFactory::createASTConsumer(
FinderOptions.CheckProfiling.emplace(Profiling->Records);
}
// Avoid processing system headers, unless the user explicitly requests it
if (!Context.getOptions().SystemHeaders.value_or(false))
FinderOptions.IgnoreSystemHeaders = true;
std::unique_ptr<ast_matchers::MatchFinder> Finder(
new ast_matchers::MatchFinder(std::move(FinderOptions)));
@ -544,7 +540,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
ArrayRef<std::string> InputFiles,
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool ApplyAnyFix, bool EnableCheckProfile,
llvm::StringRef StoreCheckProfile, bool Quiet) {
llvm::StringRef StoreCheckProfile) {
ClangTool Tool(Compilations, InputFiles,
std::make_shared<PCHContainerOperations>(), BaseFS);
@ -581,9 +577,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
class ActionFactory : public FrontendActionFactory {
public:
ActionFactory(ClangTidyContext &Context,
IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool Quiet)
: ConsumerFactory(Context, std::move(BaseFS)), Quiet(Quiet) {}
IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS)
: ConsumerFactory(Context, std::move(BaseFS)) {}
std::unique_ptr<FrontendAction> create() override {
return std::make_unique<Action>(&ConsumerFactory);
}
@ -594,8 +589,6 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
DiagnosticConsumer *DiagConsumer) override {
// Explicitly ask to define __clang_analyzer__ macro.
Invocation->getPreprocessorOpts().SetUpStaticAnalyzer = true;
if (Quiet)
Invocation->getDiagnosticOpts().ShowCarets = false;
return FrontendActionFactory::runInvocation(
Invocation, Files, PCHContainerOps, DiagConsumer);
}
@ -614,10 +607,9 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
};
ClangTidyASTConsumerFactory ConsumerFactory;
bool Quiet;
};
ActionFactory Factory(Context, std::move(BaseFS), Quiet);
ActionFactory Factory(Context, std::move(BaseFS));
Tool.run(&Factory);
return DiagConsumer.take();
}

View File

@ -94,8 +94,7 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
ArrayRef<std::string> InputFiles,
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> BaseFS,
bool ApplyAnyFix, bool EnableCheckProfile = false,
llvm::StringRef StoreCheckProfile = StringRef(),
bool Quiet = false);
llvm::StringRef StoreCheckProfile = StringRef());
/// Controls what kind of fixes clang-tidy is allowed to apply.
enum FixBehaviour {

View File

@ -89,9 +89,13 @@ def write_header(
+ check_name_camel.upper()
+ "_H"
)
f.write("//===--- ")
f.write(os.path.basename(filename))
f.write(" - clang-tidy ")
f.write("-" * max(0, 42 - len(os.path.basename(filename))))
f.write("*- C++ -*-===//")
f.write(
"""
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -141,9 +145,13 @@ def write_implementation(
filename = os.path.join(module_path, check_name_camel) + ".cpp"
print("Creating %s..." % filename)
with io.open(filename, "w", encoding="utf8", newline="\n") as f:
f.write("//===--- ")
f.write(os.path.basename(filename))
f.write(" - clang-tidy ")
f.write("-" * max(0, 51 - len(os.path.basename(filename))))
f.write("-===//")
f.write(
"""
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1575,10 +1575,6 @@ template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallSetMap =
llvm::DenseMap<const ParmVarDecl *, llvm::SmallSet<T, N>>;
template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallPtrSetMap =
llvm::DenseMap<const ParmVarDecl *, llvm::SmallPtrSet<T, N>>;
/// Returns whether the sets mapped to the two elements in the map have at
/// least one element in common.
template <typename MapTy, typename ElemTy>
@ -1703,7 +1699,7 @@ public:
/// Implements the heuristic that marks two parameters related if the same
/// member is accessed (referred to) inside the current function's body.
class AccessedSameMemberOf {
ParamToSmallPtrSetMap<const Decl *> AccessedMembers;
ParamToSmallSetMap<const Decl *> AccessedMembers;
public:
void setup(const FunctionDecl *FD) {

View File

@ -188,7 +188,7 @@ static bool isKnownToHaveValue(const Expr &Cond, const ASTContext &Ctx,
/// \return true iff all `CallExprs` visited have callees; false otherwise
/// indicating there is an unresolved indirect call.
static bool populateCallees(const Stmt *StmtNode,
llvm::SmallPtrSet<const Decl *, 16> &Callees) {
llvm::SmallSet<const Decl *, 16> &Callees) {
if (const auto *Call = dyn_cast<CallExpr>(StmtNode)) {
const Decl *Callee = Call->getDirectCallee();
@ -212,7 +212,7 @@ static bool populateCallees(const Stmt *StmtNode,
/// returns true iff `SCC` contains `Func` and its' function set overlaps with
/// `Callees`
static bool overlap(ArrayRef<CallGraphNode *> SCC,
const llvm::SmallPtrSet<const Decl *, 16> &Callees,
const llvm::SmallSet<const Decl *, 16> &Callees,
const Decl *Func) {
bool ContainsFunc = false, Overlap = false;
@ -264,7 +264,7 @@ static bool hasRecursionOverStaticLoopCondVariables(const Expr *Cond,
if (!hasStaticLocalVariable(Cond))
return false;
llvm::SmallPtrSet<const Decl *, 16> CalleesInLoop;
llvm::SmallSet<const Decl *, 16> CalleesInLoop;
if (!populateCallees(LoopStmt, CalleesInLoop)) {
// If there are unresolved indirect calls, we assume there could

View File

@ -15,12 +15,14 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
namespace {
// Determine if the result of an expression is "stored" in some way.
// It is true if the value is stored into a variable or used as initialization
// or passed to a function or constructor.
// For this use case compound assignments are not counted as a "store" (the 'E'
// expression should have pointer type).
static bool isExprValueStored(const Expr *E, ASTContext &C) {
bool isExprValueStored(const Expr *E, ASTContext &C) {
E = E->IgnoreParenCasts();
// Get first non-paren, non-cast parent.
ParentMapContext &PMap = C.getParentMapContext();
@ -47,8 +49,6 @@ static bool isExprValueStored(const Expr *E, ASTContext &C) {
return isa<CallExpr, CXXConstructExpr>(ParentE);
}
namespace {
AST_MATCHER_P(CXXTryStmt, hasHandlerFor,
ast_matchers::internal::Matcher<QualType>, InnerMatcher) {
for (unsigned NH = Node.getNumHandlers(), I = 0; I < NH; ++I) {

View File

@ -14,8 +14,10 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
const StringLiteral *Lit) {
namespace {
bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
const StringLiteral *Lit) {
// String literals surrounded by parentheses are assumed to be on purpose.
// i.e.: const char* Array[] = { ("a" "b" "c"), "d", [...] };
@ -56,8 +58,6 @@ static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
return false;
}
namespace {
AST_MATCHER_P(StringLiteral, isConcatenatedLiteral, unsigned,
MaxConcatenatedTokens) {
return Node.getNumConcatenated() > 1 &&

View File

@ -46,9 +46,7 @@ enum class ConversionKind {
ToLongDouble
};
} // namespace
static ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
return llvm::StringSwitch<ConversionKind>(FD->getName())
.Cases("atoi", "atol", ConversionKind::ToInt)
.Case("atoll", ConversionKind::ToLongInt)
@ -56,8 +54,8 @@ static ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
.Default(ConversionKind::None);
}
static ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
// Scan the format string for the first problematic format specifier, then
// report that as the conversion type. This will miss additional conversion
// specifiers, but that is acceptable behavior.
@ -130,7 +128,7 @@ static ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
return H.get();
}
static StringRef classifyConversionType(ConversionKind K) {
StringRef classifyConversionType(ConversionKind K) {
switch (K) {
case ConversionKind::None:
llvm_unreachable("Unexpected conversion kind");
@ -150,7 +148,7 @@ static StringRef classifyConversionType(ConversionKind K) {
llvm_unreachable("Unknown conversion kind");
}
static StringRef classifyReplacement(ConversionKind K) {
StringRef classifyReplacement(ConversionKind K) {
switch (K) {
case ConversionKind::None:
llvm_unreachable("Unexpected conversion kind");
@ -175,6 +173,7 @@ static StringRef classifyReplacement(ConversionKind K) {
}
llvm_unreachable("Unknown conversion kind");
}
} // unnamed namespace
void StrToNumCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("expr");

View File

@ -191,9 +191,6 @@ void PreferMemberInitializerCheck::check(
if (!AssignmentToMember)
continue;
const FieldDecl *Field = AssignmentToMember->Field;
// Skip if the field is inherited from a base class.
if (Field->getParent() != Class)
continue;
const Expr *InitValue = AssignmentToMember->Init;
updateAssignmentLevel(Field, InitValue, Ctor, AssignedFields);
if (!canAdvanceAssignment(AssignedFields[Field]))

View File

@ -32,7 +32,6 @@ add_clang_library(clangTidyMiscModule STATIC
NoRecursionCheck.cpp
NonCopyableObjects.cpp
NonPrivateMemberVariablesInClassesCheck.cpp
OverrideWithDifferentVisibilityCheck.cpp
RedundantExpressionCheck.cpp
StaticAssertCheck.cpp
ThrowByValueCatchByReferenceCheck.cpp

View File

@ -22,7 +22,6 @@
#include "NoRecursionCheck.h"
#include "NonCopyableObjects.h"
#include "NonPrivateMemberVariablesInClassesCheck.h"
#include "OverrideWithDifferentVisibilityCheck.h"
#include "RedundantExpressionCheck.h"
#include "StaticAssertCheck.h"
#include "ThrowByValueCatchByReferenceCheck.h"
@ -82,8 +81,6 @@ public:
"misc-use-anonymous-namespace");
CheckFactories.registerCheck<UseInternalLinkageCheck>(
"misc-use-internal-linkage");
CheckFactories.registerCheck<OverrideWithDifferentVisibilityCheck>(
"misc-override-with-different-visibility");
}
};

View File

@ -59,9 +59,7 @@ AST_MATCHER(FunctionDecl, isPlacementOverload) {
return true;
}
} // namespace
static OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
switch (FD->getOverloadedOperator()) {
default:
break;
@ -77,7 +75,7 @@ static OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
llvm_unreachable("Not an overloaded allocation operator");
}
static const char *getOperatorName(OverloadedOperatorKind K) {
const char *getOperatorName(OverloadedOperatorKind K) {
switch (K) {
default:
break;
@ -93,14 +91,13 @@ static const char *getOperatorName(OverloadedOperatorKind K) {
llvm_unreachable("Not an overloaded allocation operator");
}
static bool areCorrespondingOverloads(const FunctionDecl *LHS,
const FunctionDecl *RHS) {
bool areCorrespondingOverloads(const FunctionDecl *LHS,
const FunctionDecl *RHS) {
return RHS->getOverloadedOperator() == getCorrespondingOverload(LHS);
}
static bool
hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
const CXXRecordDecl *RD = nullptr) {
bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
const CXXRecordDecl *RD = nullptr) {
if (RD) {
// Check the methods in the given class and accessible to derived classes.
for (const auto *BMD : RD->methods())
@ -127,6 +124,8 @@ hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
return false;
}
} // anonymous namespace
void NewDeleteOverloadsCheck::registerMatchers(MatchFinder *Finder) {
// Match all operator new and operator delete overloads (including the array
// forms). Do not match implicit operators, placement operators, or

View File

@ -1,150 +0,0 @@
//===--- OverrideWithDifferentVisibilityCheck.cpp - clang-tidy ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "OverrideWithDifferentVisibilityCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
using namespace clang;
namespace {
AST_MATCHER(NamedDecl, isOperatorDecl) {
DeclarationName::NameKind const NK = Node.getDeclName().getNameKind();
return NK != DeclarationName::Identifier &&
NK != DeclarationName::CXXConstructorName &&
NK != DeclarationName::CXXDestructorName;
}
} // namespace
namespace clang::tidy {
template <>
struct OptionEnumMapping<
misc::OverrideWithDifferentVisibilityCheck::ChangeKind> {
static llvm::ArrayRef<std::pair<
misc::OverrideWithDifferentVisibilityCheck::ChangeKind, StringRef>>
getEnumMapping() {
static constexpr std::pair<
misc::OverrideWithDifferentVisibilityCheck::ChangeKind, StringRef>
Mapping[] = {
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Any,
"any"},
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Widening,
"widening"},
{misc::OverrideWithDifferentVisibilityCheck::ChangeKind::Narrowing,
"narrowing"},
};
return {Mapping};
}
};
namespace misc {
OverrideWithDifferentVisibilityCheck::OverrideWithDifferentVisibilityCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
DetectVisibilityChange(
Options.get("DisallowedVisibilityChange", ChangeKind::Any)),
CheckDestructors(Options.get("CheckDestructors", false)),
CheckOperators(Options.get("CheckOperators", false)),
IgnoredFunctions(utils::options::parseStringList(
Options.get("IgnoredFunctions", ""))) {}
void OverrideWithDifferentVisibilityCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "DisallowedVisibilityChange", DetectVisibilityChange);
Options.store(Opts, "CheckDestructors", CheckDestructors);
Options.store(Opts, "CheckOperators", CheckOperators);
Options.store(Opts, "IgnoredFunctions",
utils::options::serializeStringList(IgnoredFunctions));
}
void OverrideWithDifferentVisibilityCheck::registerMatchers(
MatchFinder *Finder) {
const auto IgnoredDecl =
namedDecl(matchers::matchesAnyListedName(IgnoredFunctions));
const auto FilterDestructors =
CheckDestructors ? decl() : decl(unless(cxxDestructorDecl()));
const auto FilterOperators =
CheckOperators ? namedDecl() : namedDecl(unless(isOperatorDecl()));
Finder->addMatcher(
cxxMethodDecl(
isVirtual(), FilterDestructors, FilterOperators,
ofClass(
cxxRecordDecl(unless(isExpansionInSystemHeader())).bind("class")),
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")),
unless(IgnoredDecl))
.bind("base_func")))
.bind("func"),
this);
}
void OverrideWithDifferentVisibilityCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *const MatchedFunction =
Result.Nodes.getNodeAs<FunctionDecl>("func");
if (!MatchedFunction->isCanonicalDecl())
return;
const auto *const ParentClass =
Result.Nodes.getNodeAs<CXXRecordDecl>("class");
const auto *const BaseClass = Result.Nodes.getNodeAs<CXXRecordDecl>("base");
CXXBasePaths Paths;
if (!ParentClass->isDerivedFrom(BaseClass, Paths))
return;
const auto *const OverriddenFunction =
Result.Nodes.getNodeAs<FunctionDecl>("base_func");
AccessSpecifier const ActualAccess = MatchedFunction->getAccess();
AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
for (const CXXBasePath &Path : Paths) {
for (const CXXBasePathElement &Elem : Path) {
if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
OverriddenAccess = Elem.Base->getAccessSpecifier();
InheritanceWithStrictVisibility = Elem.Base;
}
}
}
if (ActualAccess != OverriddenAccess) {
if (DetectVisibilityChange == ChangeKind::Widening &&
ActualAccess > OverriddenAccess)
return;
if (DetectVisibilityChange == ChangeKind::Narrowing &&
ActualAccess < OverriddenAccess)
return;
if (InheritanceWithStrictVisibility) {
diag(MatchedFunction->getLocation(),
"visibility of function %0 is changed from %1 (through %1 "
"inheritance of class %2) to %3")
<< MatchedFunction << OverriddenAccess
<< InheritanceWithStrictVisibility->getType() << ActualAccess;
diag(InheritanceWithStrictVisibility->getBeginLoc(),
"%0 is inherited as %1 here", DiagnosticIDs::Note)
<< InheritanceWithStrictVisibility->getType() << OverriddenAccess;
} else {
diag(MatchedFunction->getLocation(),
"visibility of function %0 is changed from %1 in class %2 to %3")
<< MatchedFunction << OverriddenAccess << BaseClass << ActualAccess;
}
diag(OverriddenFunction->getLocation(), "function declared here as %0",
DiagnosticIDs::Note)
<< OverriddenFunction->getAccess();
}
}
} // namespace misc
} // namespace clang::tidy

View File

@ -1,43 +0,0 @@
//===--- OverrideWithDifferentVisibilityCheck.h - clang-tidy --*- 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_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H
#include "../ClangTidyCheck.h"
namespace clang::tidy::misc {
/// Finds virtual function overrides with different visibility than the function
/// in the base class.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/override-with-different-visibility.html
class OverrideWithDifferentVisibilityCheck : public ClangTidyCheck {
public:
enum class ChangeKind { Any, Widening, Narrowing };
OverrideWithDifferentVisibilityCheck(StringRef Name,
ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
private:
ChangeKind DetectVisibilityChange;
bool CheckDestructors;
bool CheckOperators;
std::vector<llvm::StringRef> IgnoredFunctions;
};
} // namespace clang::tidy::misc
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_OVERRIDEWITHDIFFERENTVISIBILITYCHECK_H

View File

@ -29,13 +29,11 @@ void UnconventionalAssignOperatorCheck::registerMatchers(
const auto HasGoodReturnType =
cxxMethodDecl(returns(hasCanonicalType(lValueReferenceType(pointee(
unless(isConstQualified()),
anyOf(autoType(),
hasDeclaration(declaresSameEntityAsBoundNode("class"))))))));
anyOf(autoType(), hasDeclaration(equalsBoundNode("class"))))))));
const auto IsSelf = qualType(hasCanonicalType(
anyOf(hasDeclaration(declaresSameEntityAsBoundNode("class")),
referenceType(pointee(
hasDeclaration(declaresSameEntityAsBoundNode("class")))))));
anyOf(hasDeclaration(equalsBoundNode("class")),
referenceType(pointee(hasDeclaration(equalsBoundNode("class")))))));
const auto IsAssign =
cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
hasName("operator="), ofClass(recordDecl().bind("class")))

View File

@ -395,12 +395,16 @@ void MacroToEnumCallbacks::Endif(SourceLocation Loc, SourceLocation IfLoc) {
--CurrentFile->ConditionScopes;
}
namespace {
template <size_t N>
static bool textEquals(const char (&Needle)[N], const char *HayStack) {
bool textEquals(const char (&Needle)[N], const char *HayStack) {
return StringRef{HayStack, N - 1} == Needle;
}
template <size_t N> static size_t len(const char (&)[N]) { return N - 1; }
template <size_t N> size_t len(const char (&)[N]) { return N - 1; }
} // namespace
void MacroToEnumCallbacks::PragmaDirective(SourceLocation Loc,
PragmaIntroducerKind Introducer) {

View File

@ -16,13 +16,14 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
static constexpr char ConstructorCall[] = "constructorCall";
static constexpr char ResetCall[] = "resetCall";
static constexpr char NewExpression[] = "newExpression";
namespace {
static std::string getNewExprName(const CXXNewExpr *NewExpr,
const SourceManager &SM,
const LangOptions &Lang) {
constexpr char ConstructorCall[] = "constructorCall";
constexpr char ResetCall[] = "resetCall";
constexpr char NewExpression[] = "newExpression";
std::string getNewExprName(const CXXNewExpr *NewExpr, const SourceManager &SM,
const LangOptions &Lang) {
StringRef WrittenName = Lexer::getSourceText(
CharSourceRange::getTokenRange(
NewExpr->getAllocatedTypeSourceInfo()->getTypeLoc().getSourceRange()),
@ -33,6 +34,8 @@ static std::string getNewExprName(const CXXNewExpr *NewExpr,
return WrittenName.str();
}
} // namespace
const char MakeSmartPtrCheck::PointerType[] = "pointerType";
MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,

View File

@ -19,7 +19,9 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
static bool containsEscapes(StringRef HayStack, StringRef Escapes) {
namespace {
bool containsEscapes(StringRef HayStack, StringRef Escapes) {
size_t BackSlash = HayStack.find('\\');
if (BackSlash == StringRef::npos)
return false;
@ -33,16 +35,16 @@ static bool containsEscapes(StringRef HayStack, StringRef Escapes) {
return true;
}
static bool isRawStringLiteral(StringRef Text) {
bool isRawStringLiteral(StringRef Text) {
// Already a raw string literal if R comes before ".
const size_t QuotePos = Text.find('"');
assert(QuotePos != StringRef::npos);
return (QuotePos > 0) && (Text[QuotePos - 1] == 'R');
}
static bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
const StringLiteral *Literal,
const CharsBitSet &DisallowedChars) {
bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
const StringLiteral *Literal,
const CharsBitSet &DisallowedChars) {
// FIXME: Handle L"", u8"", u"" and U"" literals.
if (!Literal->isOrdinary())
return false;
@ -62,12 +64,14 @@ static bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
return containsEscapes(Text, R"('\"?x01)");
}
static bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
return Bytes.find(Delimiter.empty()
? std::string(R"lit()")lit")
: (")" + Delimiter + R"(")")) != StringRef::npos;
}
} // namespace
RawStringLiteralCheck::RawStringLiteralCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -29,13 +29,12 @@
using namespace clang::ast_matchers;
namespace clang::tidy::objc {
namespace {
static constexpr StringRef WeakText = "__weak";
static constexpr StringRef StrongText = "__strong";
static constexpr StringRef UnsafeUnretainedText = "__unsafe_unretained";
namespace {
/// Matches ObjCIvarRefExpr, DeclRefExpr, or MemberExpr that reference
/// Objective-C object (or block) variables or fields whose object lifetimes
/// are not __unsafe_unretained.
@ -50,8 +49,6 @@ AST_POLYMORPHIC_MATCHER(isObjCManagedLifetime,
QT.getQualifiers().getObjCLifetime() > Qualifiers::OCL_ExplicitNone;
}
} // namespace
static std::optional<FixItHint>
fixItHintReplacementForOwnershipString(StringRef Text, CharSourceRange Range,
StringRef Ownership) {
@ -96,6 +93,8 @@ fixItHintForVarDecl(const VarDecl *VD, const SourceManager &SM,
return FixItHint::CreateInsertion(Range.getBegin(), "__unsafe_unretained ");
}
} // namespace
void NSInvocationArgumentLifetimeCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
traverse(

View File

@ -27,14 +27,11 @@ enum NamingStyle {
CategoryProperty = 2,
};
} // namespace
/// For now we will only fix 'CamelCase' or 'abc_CamelCase' property to
/// 'camelCase' or 'abc_camelCase'. For other cases the users need to
/// come up with a proper name by their own.
/// FIXME: provide fix for snake_case to snakeCase
static FixItHint generateFixItHint(const ObjCPropertyDecl *Decl,
NamingStyle Style) {
FixItHint generateFixItHint(const ObjCPropertyDecl *Decl, NamingStyle Style) {
auto Name = Decl->getName();
auto NewName = Decl->getName().str();
size_t Index = 0;
@ -53,7 +50,7 @@ static FixItHint generateFixItHint(const ObjCPropertyDecl *Decl,
return {};
}
static std::string validPropertyNameRegex(bool UsedInMatcher) {
std::string validPropertyNameRegex(bool UsedInMatcher) {
// Allow any of these names:
// foo
// fooBar
@ -75,13 +72,13 @@ static std::string validPropertyNameRegex(bool UsedInMatcher) {
return StartMatcher + "([a-z]|[A-Z][A-Z0-9])[a-z0-9A-Z]*$";
}
static bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
auto RegexExp =
llvm::Regex("^[a-zA-Z][a-zA-Z0-9]*_[a-zA-Z0-9][a-zA-Z0-9_]+$");
return RegexExp.match(PropertyName);
}
static bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
size_t Start = PropertyName.find_first_of('_');
assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
auto Prefix = PropertyName.substr(0, Start);
@ -91,6 +88,7 @@ static bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
auto RegexExp = llvm::Regex(llvm::StringRef(validPropertyNameRegex(false)));
return RegexExp.match(PropertyName.substr(Start + 1));
}
} // namespace
void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(objcPropertyDecl(

View File

@ -17,6 +17,7 @@
#include <optional>
namespace clang::tidy::performance {
namespace {
using namespace ::clang::ast_matchers;
using llvm::StringRef;
@ -29,8 +30,8 @@ static constexpr StringRef MethodDeclId = "methodDecl";
static constexpr StringRef FunctionDeclId = "functionDecl";
static constexpr StringRef OldVarDeclId = "oldVarDecl";
static void recordFixes(const VarDecl &Var, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
void recordFixes(const VarDecl &Var, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context);
if (!Var.getType().isLocalConstQualified()) {
if (std::optional<FixItHint> Fix = utils::fixit::addQualifierToVarDecl(
@ -39,8 +40,8 @@ static void recordFixes(const VarDecl &Var, ASTContext &Context,
}
}
static std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
SourceManager &SM) {
std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
SourceManager &SM) {
bool Invalid = false;
const char *TextAfter = SM.getCharacterData(Loc, &Invalid);
if (Invalid) {
@ -50,8 +51,8 @@ static std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
return Loc.getLocWithOffset(TextAfter[Offset] == '\0' ? Offset : Offset + 1);
}
static void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
auto &SM = Context.getSourceManager();
// Attempt to remove trailing comments as well.
auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM,
@ -73,8 +74,6 @@ static void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
}
}
namespace {
AST_MATCHER_FUNCTION_P(StatementMatcher,
isRefReturningMethodCallWithConstOverloads,
std::vector<StringRef>, ExcludedContainerTypes) {
@ -131,8 +130,6 @@ AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst,
hasUnaryOperand(OldVarDeclRef)))));
}
} // namespace
// This checks that the variable itself is only used as const, and also makes
// sure that it does not reference another variable that could be modified in
// the BlockStmt. It does this by checking the following:
@ -183,13 +180,13 @@ static bool isInitializingVariableImmutable(
return false;
}
static bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
return allDeclRefExprs(Var, BlockStmt, Context).empty();
}
static const SubstTemplateTypeParmType *
getSubstitutedType(const QualType &Type, ASTContext &Context) {
const SubstTemplateTypeParmType *getSubstitutedType(const QualType &Type,
ASTContext &Context) {
auto Matches = match(
qualType(anyOf(substTemplateTypeParmType().bind("subst"),
hasDescendant(substTemplateTypeParmType().bind("subst")))),
@ -197,9 +194,9 @@ getSubstitutedType(const QualType &Type, ASTContext &Context) {
return selectFirst<SubstTemplateTypeParmType>("subst", Matches);
}
static bool differentReplacedTemplateParams(const QualType &VarType,
const QualType &InitializerType,
ASTContext &Context) {
bool differentReplacedTemplateParams(const QualType &VarType,
const QualType &InitializerType,
ASTContext &Context) {
if (const SubstTemplateTypeParmType *VarTmplType =
getSubstitutedType(VarType, Context)) {
if (const SubstTemplateTypeParmType *InitializerTmplType =
@ -215,8 +212,8 @@ static bool differentReplacedTemplateParams(const QualType &VarType,
return false;
}
static QualType constructorArgumentType(const VarDecl *OldVar,
const BoundNodes &Nodes) {
QualType constructorArgumentType(const VarDecl *OldVar,
const BoundNodes &Nodes) {
if (OldVar) {
return OldVar->getType();
}
@ -227,6 +224,8 @@ static QualType constructorArgumentType(const VarDecl *OldVar,
return MethodDecl->getReturnType();
}
} // namespace
UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -21,14 +21,16 @@ using namespace clang::ast_matchers;
namespace clang::tidy::performance {
static std::string paramNameOrIndex(StringRef Name, size_t Index) {
namespace {
std::string paramNameOrIndex(StringRef Name, size_t Index) {
return (Name.empty() ? llvm::Twine('#') + llvm::Twine(Index + 1)
: llvm::Twine('\'') + Name + llvm::Twine('\''))
.str();
}
static bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
ASTContext &Context) {
bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
ASTContext &Context) {
auto Matches = match(
traverse(TK_AsIs,
decl(forEachDescendant(declRefExpr(
@ -39,6 +41,8 @@ static bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
return Matches.empty();
}
} // namespace
UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -122,15 +122,15 @@ AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
return !AllEnumeratorsArePowersOfTwo;
}
} // namespace
static std::string getName(const EnumDecl *Decl) {
std::string getName(const EnumDecl *Decl) {
if (!Decl->getDeclName())
return "<unnamed>";
return Decl->getQualifiedNameAsString();
}
} // namespace
EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -144,8 +144,6 @@ struct CognitiveComplexity final {
void account(SourceLocation Loc, unsigned short Nesting, Criteria C);
};
} // namespace
// All the possible messages that can be output. The choice of the message
// to use is based of the combination of the CognitiveComplexity::Criteria.
// It would be nice to have it in CognitiveComplexity struct, but then it is
@ -165,27 +163,23 @@ static const std::array<const StringRef, 4> Msgs = {{
}};
// Criteria is a bitset, thus a few helpers are needed.
static CognitiveComplexity::Criteria
operator|(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria operator|(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
return static_cast<CognitiveComplexity::Criteria>(llvm::to_underlying(LHS) |
llvm::to_underlying(RHS));
}
static CognitiveComplexity::Criteria
operator&(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria operator&(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
return static_cast<CognitiveComplexity::Criteria>(llvm::to_underlying(LHS) &
llvm::to_underlying(RHS));
}
static CognitiveComplexity::Criteria &
operator|=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria &operator|=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
LHS = operator|(LHS, RHS);
return LHS;
}
static CognitiveComplexity::Criteria &
operator&=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
CognitiveComplexity::Criteria &operator&=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
LHS = operator&(LHS, RHS);
return LHS;
}
@ -205,8 +199,6 @@ void CognitiveComplexity::account(SourceLocation Loc, unsigned short Nesting,
Total += Increase;
}
namespace {
class FunctionASTVisitor final
: public RecursiveASTVisitor<FunctionASTVisitor> {
using Base = RecursiveASTVisitor<FunctionASTVisitor>;

View File

@ -41,11 +41,9 @@ AST_MATCHER(Stmt, isNULLMacroExpansion) {
return isNULLMacroExpansion(&Node, Finder->getASTContext());
}
} // namespace
static StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type,
ASTContext &Context) {
StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type,
ASTContext &Context) {
switch (CastExprKind) {
case CK_IntegralToBoolean:
return Type->isUnsignedIntegerType() ? "0u" : "0";
@ -64,15 +62,15 @@ static StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
}
}
static bool isUnaryLogicalNotOperator(const Stmt *Statement) {
bool isUnaryLogicalNotOperator(const Stmt *Statement) {
const auto *UnaryOperatorExpr = dyn_cast<UnaryOperator>(Statement);
return UnaryOperatorExpr && UnaryOperatorExpr->getOpcode() == UO_LNot;
}
static void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
const Stmt *Parent, ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast, const Stmt *Parent,
ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
// In case of expressions like (! integer), we should remove the redundant not
// operator and use inverted comparison (integer == 0).
bool InvertComparison =
@ -135,8 +133,8 @@ static void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
}
static StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
ASTContext &Context) {
StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
ASTContext &Context) {
if (isNULLMacroExpansion(Expression, Context)) {
return "false";
}
@ -163,7 +161,7 @@ static StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
return {};
}
static bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
SourceRange PrefixRange(Loc.getLocWithOffset(-1), Loc);
StringRef SpaceBeforeStmtStr = Lexer::getSourceText(
CharSourceRange::getCharRange(PrefixRange), Context.getSourceManager(),
@ -175,10 +173,9 @@ static bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
return !AllowedCharacters.contains(SpaceBeforeStmtStr.back());
}
static void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context,
StringRef OtherType) {
void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context, StringRef OtherType) {
if (!Context.getLangOpts().CPlusPlus) {
Diag << FixItHint::CreateInsertion(Cast->getBeginLoc(),
(Twine("(") + OtherType + ")").str());
@ -203,9 +200,8 @@ static void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
}
}
static StringRef
getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
QualType DestType, ASTContext &Context) {
StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
QualType DestType, ASTContext &Context) {
// Prior to C++11, false literal could be implicitly converted to pointer.
if (!Context.getLangOpts().CPlusPlus11 &&
(DestType->isPointerType() || DestType->isMemberPointerType()) &&
@ -226,8 +222,8 @@ getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
return BoolLiteral->getValue() ? "1" : "0";
}
static bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
ASTContext &Context) {
bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
ASTContext &Context) {
std::queue<const Stmt *> Q;
Q.push(Cast);
@ -255,6 +251,8 @@ static bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
return false;
}
} // anonymous namespace
ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -28,11 +28,8 @@ AST_MATCHER_P(QualType, hasUnqualifiedType,
enum class Qualifier { Const, Volatile, Restrict };
} // namespace
static std::optional<Token>
findQualToken(const VarDecl *Decl, Qualifier Qual,
const MatchFinder::MatchResult &Result) {
std::optional<Token> findQualToken(const VarDecl *Decl, Qualifier Qual,
const MatchFinder::MatchResult &Result) {
// Since either of the locs can be in a macro, use `makeFileCharRange` to be
// sure that we have a consistent `CharSourceRange`, located entirely in the
// source file.
@ -61,7 +58,7 @@ findQualToken(const VarDecl *Decl, Qualifier Qual,
*Result.SourceManager);
}
static std::optional<SourceRange>
std::optional<SourceRange>
getTypeSpecifierLocation(const VarDecl *Var,
const MatchFinder::MatchResult &Result) {
SourceRange TypeSpecifier(
@ -76,8 +73,8 @@ getTypeSpecifierLocation(const VarDecl *Var,
return TypeSpecifier;
}
static std::optional<SourceRange>
mergeReplacementRange(SourceRange &TypeSpecifier, const Token &ConstToken) {
std::optional<SourceRange> mergeReplacementRange(SourceRange &TypeSpecifier,
const Token &ConstToken) {
if (TypeSpecifier.getBegin().getLocWithOffset(-1) == ConstToken.getEndLoc()) {
TypeSpecifier.setBegin(ConstToken.getLocation());
return std::nullopt;
@ -89,19 +86,21 @@ mergeReplacementRange(SourceRange &TypeSpecifier, const Token &ConstToken) {
return SourceRange(ConstToken.getLocation(), ConstToken.getEndLoc());
}
static bool isPointerConst(QualType QType) {
bool isPointerConst(QualType QType) {
QualType Pointee = QType->getPointeeType();
assert(!Pointee.isNull() && "can't have a null Pointee");
return Pointee.isConstQualified();
}
static bool isAutoPointerConst(QualType QType) {
bool isAutoPointerConst(QualType QType) {
QualType Pointee =
cast<AutoType>(QType->getPointeeType().getTypePtr())->desugar();
assert(!Pointee.isNull() && "can't have a null Pointee");
return Pointee.isConstQualified();
}
} // namespace
QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -14,18 +14,19 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
static const char *const RedundantReturnDiag =
"redundant return statement at the end "
"of a function with a void return type";
static const char *const RedundantContinueDiag =
"redundant continue statement at the "
"end of loop statement";
namespace {
static bool isLocationInMacroExpansion(const SourceManager &SM,
SourceLocation Loc) {
const char *const RedundantReturnDiag = "redundant return statement at the end "
"of a function with a void return type";
const char *const RedundantContinueDiag = "redundant continue statement at the "
"end of loop statement";
bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) {
return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
}
} // namespace
void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
functionDecl(isDefinition(), returns(voidType()),

View File

@ -162,19 +162,14 @@ in .clang-tidy file, if any.
cl::init(false), cl::cat(ClangTidyCategory));
static cl::opt<std::string> LineFilter("line-filter", desc(R"(
List of files and line ranges to output diagnostics from.
The range is inclusive on both ends. Can be used together
with -header-filter. The format of the list is a JSON
array of objects. For example:
List of files with line ranges to filter the
warnings. Can be used together with
-header-filter. The format of the list is a
JSON array of objects:
[
{"name":"file1.cpp","lines":[[1,3],[5,7]]},
{"name":"file2.h"}
]
This will output diagnostics from 'file1.cpp' only for
the line ranges [1,3] and [5,7], as well as all from the
entire 'file2.h'.
)"),
cl::init(""),
cl::cat(ClangTidyCategory));
@ -717,7 +712,7 @@ int clangTidyMain(int argc, const char **argv) {
EnableModuleHeadersParsing);
std::vector<ClangTidyError> Errors =
runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS,
FixNotes, EnableCheckProfile, ProfilePrefix, Quiet);
FixNotes, EnableCheckProfile, ProfilePrefix);
bool FoundErrors = llvm::any_of(Errors, [](const ClangTidyError &E) {
return E.DiagLevel == ClangTidyError::Error;
});

View File

@ -28,7 +28,6 @@ import glob
import json
import multiprocessing
import os
import queue
import re
import shutil
import subprocess
@ -43,6 +42,13 @@ try:
except ImportError:
yaml = None
is_py2 = sys.version[0] == "2"
if is_py2:
import Queue as queue
else:
import queue as queue
def run_tidy(task_queue, lock, timeout, failed_files):
watchdog = None

View File

@ -483,7 +483,7 @@ async def main() -> None:
parser.add_argument(
"-line-filter",
default=None,
help="List of files and line ranges to output diagnostics from.",
help="List of files with line ranges to filter the warnings.",
)
if yaml:
parser.add_argument(

View File

@ -13,14 +13,16 @@
namespace clang::tidy::utils::type_traits {
static bool classHasTrivialCopyAndDestroy(QualType Type) {
namespace {
bool classHasTrivialCopyAndDestroy(QualType Type) {
auto *Record = Type->getAsCXXRecordDecl();
return Record && Record->hasDefinition() &&
!Record->hasNonTrivialCopyConstructor() &&
!Record->hasNonTrivialDestructor();
}
static bool hasDeletedCopyConstructor(QualType Type) {
bool hasDeletedCopyConstructor(QualType Type) {
auto *Record = Type->getAsCXXRecordDecl();
if (!Record || !Record->hasDefinition())
return false;
@ -31,6 +33,8 @@ static bool hasDeletedCopyConstructor(QualType Type) {
return false;
}
} // namespace
std::optional<bool> isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
if (Type->isDependentType() || Type->isIncompleteType())

View File

@ -985,7 +985,7 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) {
// Recurse on pack parameters
size_t Depth = 0;
const FunctionDecl *CurrentFunction = D;
llvm::SmallPtrSet<const FunctionTemplateDecl *, 4> SeenTemplates;
llvm::SmallSet<const FunctionTemplateDecl *, 4> SeenTemplates;
if (const auto *Template = D->getPrimaryTemplate()) {
SeenTemplates.insert(Template);
}

View File

@ -6,7 +6,7 @@ add_subdirectory(support)
# Configure the Features.inc file.
if (NOT DEFINED CLANGD_BUILD_XPC)
if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CLANGD_BUILD_XPC_DEFAULT ON)
else ()
set(CLANGD_BUILD_XPC_DEFAULT OFF)
@ -193,7 +193,7 @@ if(CLANGD_TIDY_CHECKS)
endif()
add_subdirectory(refactor/tweaks)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
# FIXME: Make fuzzer not use linux-specific APIs, build it everywhere.
add_subdirectory(fuzzer)
endif()

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