.github/CODEOWNERS
@@ -131,7 +131,7 @@
/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci @yota9 /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci @yota9
# Bazel build system. # Bazel build system.
-/utils/bazel/ @rupprecht @keith+/utils/bazel/ @rupprecht @keith @aaronmondal
# InstallAPI and TextAPI # InstallAPI and TextAPI
/llvm/**/TextAPI/ @cyndyishida /llvm/**/TextAPI/ @cyndyishida
.github/workflows/build-ci-container.yml
@@ -20,24 +20,31 @@ on:
jobs: jobs:
build-ci-container: build-ci-container:
if: github.repository_owner == 'llvm' if: github.repository_owner == 'llvm'
- runs-on: depot-ubuntu-22.04-16+ runs-on: ${{ matrix.runs-on }}
- outputs:+ strategy:
- container-name: ${{ steps.vars.outputs.container-name }}+ matrix:
- container-name-agent: ${{ steps.vars.outputs.container-name-agent }}+ include:
- container-name-tag: ${{ steps.vars.outputs.container-name-tag }}+ # The arch names should match the names used on dockerhub.
- container-name-agent-tag: ${{ steps.vars.outputs.container-name-agent-tag }}+ # See https://github.com/docker-library/official-images#architectures-other-than-amd64
- container-filename: ${{ steps.vars.outputs.container-filename }}+ - arch: amd64
- container-agent-filename: ${{ steps.vars.outputs.container-agent-filename }}+ runs-on: depot-ubuntu-22.04-16
+ - arch: arm64v8
+ runs-on: depot-ubuntu-22.04-arm-16
steps: steps:
- name: Checkout LLVM - name: Checkout LLVM
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
sparse-checkout: .github/workflows/containers/github-action-ci/ sparse-checkout: .github/workflows/containers/github-action-ci/
+ # podman is not installed by default on the ARM64 images.
+ - name: Install Podman
+ if: runner.arch == 'ARM64'
+ run: |
+ sudo apt-get install podman
- name: Write Variables - name: Write Variables
id: vars id: vars
run: | run: |
- tag=`date +%s`+ tag=$(git rev-parse --short=12 HEAD)
- container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/ci-ubuntu-22.04"+ container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/${{ matrix.arch }}/ci-ubuntu-22.04"
echo "container-name=$container_name" >> $GITHUB_OUTPUT echo "container-name=$container_name" >> $GITHUB_OUTPUT
echo "container-name-agent=$container_name-agent" >> $GITHUB_OUTPUT echo "container-name-agent=$container_name-agent" >> $GITHUB_OUTPUT
echo "container-name-tag=$container_name:$tag" >> $GITHUB_OUTPUT echo "container-name-tag=$container_name:$tag" >> $GITHUB_OUTPUT
@@ -61,7 +68,7 @@ jobs:
- name: Upload container image - name: Upload container image
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
- name: container+ name: container-${{ matrix.arch }}
path: "*.tar" path: "*.tar"
retention-days: 14 retention-days: 14
@@ -84,18 +91,29 @@ jobs:
steps: steps:
- name: Download container - name: Download container
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
- with:
- name: container
- name: Push Container - name: Push Container
run: | run: |
- podman load -i ${{ needs.build-ci-container.outputs.container-filename }}+ function push_container {
- podman tag ${{ needs.build-ci-container.outputs.container-name-tag }} ${{ needs.build-ci-container.outputs.container-name }}:latest+ image_name=$1
+ latest_name=$(echo $image_name | sed 's/:[a-f0-9]\+$/:latest/g')
+ podman tag $image_name $latest_name
+ echo "Pushing $image_name ..."
+ podman push $image_name
+ echo "Pushing $latest_name ..."
+ podman push $latest_name
+ }
+
podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io
- podman push ${{ needs.build-ci-container.outputs.container-name-tag }}+ for f in $(find . -iname *.tar); do
- podman push ${{ needs.build-ci-container.outputs.container-name }}:latest+ image_name=$(podman load -q -i $f | sed 's/Loaded image: //g')
+ push_container $image_name
- podman load -i ${{ needs.build-ci-container.outputs.container-agent-filename }}+ if echo $image_name | grep '/amd64/'; then
- podman tag ${{ needs.build-ci-container.outputs.container-name-agent-tag }} ${{ needs.build-ci-container.outputs.container-name-agent }}:latest+ # For amd64, create an alias with the arch component removed.
- podman push ${{ needs.build-ci-container.outputs.container-name-agent-tag }}+ # This matches the convention used on dockerhub.
- podman push ${{ needs.build-ci-container.outputs.container-name-agent }}:latest+ default_image_name=$(echo $(dirname $(dirname $image_name))/$(basename $image_name))
+ podman tag $image_name $default_image_name
+ push_container $default_image_name
+ fi
+ done
.github/workflows/libc-fullbuild-tests.yml
@@ -15,6 +15,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
+ build_type: [Debug, Release, MinSizeRel]
include: include:
- os: ubuntu-24.04 - os: ubuntu-24.04
ccache-variant: sccache ccache-variant: sccache
@@ -68,7 +69,7 @@ jobs:
cmake -B ${{ steps.strings.outputs.build-output-dir }} cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
- -DCMAKE_BUILD_TYPE=MinSizeRel+ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} -DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-install-dir }} -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-install-dir }}
.github/workflows/libc-overlay-tests.yml
@@ -16,6 +16,7 @@ jobs:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations.
fail-fast: false fail-fast: false
matrix: matrix:
+ build_type: [Debug, Release, MinSizeRel]
include: include:
# TODO: add linux gcc when it is fixed # TODO: add linux gcc when it is fixed
- os: ubuntu-24.04 - os: ubuntu-24.04
@@ -95,7 +96,7 @@ jobs:
cmake -B ${{ steps.strings.outputs.build-output-dir }} cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp_compiler }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.compiler.c_compiler }} -DCMAKE_C_COMPILER=${{ matrix.compiler.c_compiler }}
- -DCMAKE_BUILD_TYPE=MinSizeRel+ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} -DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }}
-DCMAKE_POLICY_DEFAULT_CMP0141=NEW -DCMAKE_POLICY_DEFAULT_CMP0141=NEW
.github/workflows/libcxx-build-containers.yml
@@ -9,7 +9,6 @@ name: Build Docker images for libc++ CI
permissions: permissions:
contents: read contents: read
- packages: write
on: on:
push: push:
.github/workflows/premerge.yaml
@@ -5,6 +5,15 @@ permissions:
on: on:
pull_request: pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # When a PR is closed, we still start this workflow, but then skip
+ # all the jobs, which makes it effectively a no-op. The reason to
+ # do this is that it allows us to take advantage of concurrency groups
+ # to cancel in progress CI jobs whenever the PR is closed.
+ - closed
paths: paths:
- .github/workflows/premerge.yaml - .github/workflows/premerge.yaml
push: push:
@@ -12,13 +21,16 @@ on:
- 'main' - 'main'
- 'release/**' - 'release/**'
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
jobs: jobs:
premerge-checks-linux: premerge-checks-linux:
- if: github.repository_owner == 'llvm'+ if: >-
+ github.repository_owner == 'llvm' &&
+ (github.event_name != 'pull_request' || github.event.action != 'closed')
runs-on: llvm-premerge-linux-runners runs-on: llvm-premerge-linux-runners
- concurrency:
- group: ${{ github.workflow }}-linux-${{ github.event.pull_request.number || github.sha }}
- cancel-in-progress: true
steps: steps:
- name: Checkout LLVM - name: Checkout LLVM
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -73,11 +85,10 @@ jobs:
./.ci/monolithic-linux.sh "$(echo ${linux_projects} | tr ' ' ';')" "$(echo ${linux_check_targets})" "$(echo ${linux_runtimes} | tr ' ' ';')" "$(echo ${linux_runtime_check_targets})" ./.ci/monolithic-linux.sh "$(echo ${linux_projects} | tr ' ' ';')" "$(echo ${linux_check_targets})" "$(echo ${linux_runtimes} | tr ' ' ';')" "$(echo ${linux_runtime_check_targets})"
premerge-checks-windows: premerge-checks-windows:
- if: github.repository_owner == 'llvm'+ if: >-
+ github.repository_owner == 'llvm' &&
+ (github.event_name != 'pull_request' || github.event.action != 'closed')
runs-on: llvm-premerge-windows-runners runs-on: llvm-premerge-windows-runners
- concurrency:
- group: ${{ github.workflow }}-windows-${{ github.event.pull_request.number || github.sha }}
- cancel-in-progress: true
defaults: defaults:
run: run:
shell: bash shell: bash
@@ -135,13 +146,11 @@ jobs:
permerge-check-macos: permerge-check-macos:
runs-on: macos-14 runs-on: macos-14
- concurrency:
- group: ${{ github.workflow }}-macos-${{ github.event.pull_request.number || github.sha }}
- cancel-in-progress: true
if: >- if: >-
github.repository_owner == 'llvm' && github.repository_owner == 'llvm' &&
(startswith(github.ref_name, 'release/') || (startswith(github.ref_name, 'release/') ||
- startswith(github.base_ref, 'release/'))+ startswith(github.base_ref, 'release/')) &&
+ (github.event_name != 'pull_request' || github.event.action != 'closed')
steps: steps:
- name: Checkout LLVM - name: Checkout LLVM
uses: actions/checkout@v4 uses: actions/checkout@v4
.github/workflows/release-binaries.yml
@@ -58,7 +58,6 @@ jobs:
target-cmake-flags: ${{ steps.vars.outputs.target-cmake-flags }} target-cmake-flags: ${{ steps.vars.outputs.target-cmake-flags }}
ccache: ${{ steps.vars.outputs.ccache }} ccache: ${{ steps.vars.outputs.ccache }}
build-flang: ${{ steps.vars.outputs.build-flang }} build-flang: ${{ steps.vars.outputs.build-flang }}
- enable-pgo: ${{ steps.vars.outputs.enable-pgo }}
release-binary-basename: ${{ steps.vars.outputs.release-binary-basename }} release-binary-basename: ${{ steps.vars.outputs.release-binary-basename }}
release-binary-filename: ${{ steps.vars.outputs.release-binary-filename }} release-binary-filename: ${{ steps.vars.outputs.release-binary-filename }}
build-runs-on: ${{ steps.vars.outputs.build-runs-on }} build-runs-on: ${{ steps.vars.outputs.build-runs-on }}
@@ -130,9 +129,6 @@ jobs:
echo ccache=sccache >> $GITHUB_OUTPUT echo ccache=sccache >> $GITHUB_OUTPUT
fi fi
- # Detect necessary CMake flags
- echo "enable-pgo=false" >> $GITHUB_OUTPUT
- target_cmake_flags="-DLLVM_RELEASE_ENABLE_PGO=OFF"
# The macOS builds try to cross compile some libraries so we need to # The macOS builds try to cross compile some libraries so we need to
# add extra CMake args to disable them. # add extra CMake args to disable them.
# See https://github.com/llvm/llvm-project/issues/99767 # See https://github.com/llvm/llvm-project/issues/99767
@@ -238,13 +234,14 @@ jobs:
${{ needs.prepare.outputs.target-cmake-flags }} \ ${{ needs.prepare.outputs.target-cmake-flags }} \
-C clang/cmake/caches/Release.cmake \ -C clang/cmake/caches/Release.cmake \
-DBOOTSTRAP_LLVM_PARALLEL_LINK_JOBS=1 \ -DBOOTSTRAP_LLVM_PARALLEL_LINK_JOBS=1 \
- -DBOOTSTRAP_CPACK_PACKAGE_FILE_NAME="${{ needs.prepare.outputs.release-binary-basename }}"+ -DBOOTSTRAP_BOOTSTRAP_CPACK_PACKAGE_FILE_NAME="${{ needs.prepare.outputs.release-binary-basename }}"
- name: Build - name: Build
shell: bash shell: bash
run: | run: |
ninja -v -C ${{ steps.setup-stage.outputs.build-prefix }}/build stage2-package ninja -v -C ${{ steps.setup-stage.outputs.build-prefix }}/build stage2-package
- mv ${{ steps.setup-stage.outputs.build-prefix }}/build/tools/clang/stage2-bins/${{ needs.prepare.outputs.release-binary-filename }} .+ release_dir=`find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname 'stage2-bins'`
+ mv $release_dir/${{ needs.prepare.outputs.release-binary-filename }} .
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
with: with:
@@ -259,7 +256,7 @@ jobs:
shell: bash shell: bash
run: | run: |
find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname ${{ needs.prepare.outputs.release-binary-filename }} -delete find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname ${{ needs.prepare.outputs.release-binary-filename }} -delete
- rm -Rf ${{ steps.setup-stage.outputs.build-prefix }}/build/tools/clang/stage2-bins/_CPack_Packages+ find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname _CPack_Packages -prune -exec rm -r {} +
- name: Save Stage - name: Save Stage
uses: ./workflows-main/.github/workflows/release-binaries-save-stage uses: ./workflows-main/.github/workflows/release-binaries-save-stage
.github/workflows/release-tasks.yml
@@ -89,20 +89,10 @@ jobs:
needs: needs:
- validate-tag - validate-tag
- release-create - release-create
- strategy:+ uses: ./.github/workflows/release-binaries-all.yml
- fail-fast: false
- matrix:
- runs-on:
- - ubuntu-22.04
- - windows-2022
- - macos-13
- - macos-14
-
- uses: ./.github/workflows/release-binaries.yml
with: with:
release-version: ${{ needs.validate-tag.outputs.release-version }} release-version: ${{ needs.validate-tag.outputs.release-version }}
upload: true upload: true
- runs-on: ${{ matrix.runs-on }}
# Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use. # Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use.
secrets: secrets:
RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }}
bolt/include/bolt/Core/BinaryContext.h
@@ -1435,6 +1435,17 @@ public:
bool PrintRelocations = false, bool PrintRelocations = false,
StringRef Endl = "\n") const; StringRef Endl = "\n") const;
+ /// Print data when embedded in the instruction stream keeping the format
+ /// similar to printInstruction().
+ void printData(raw_ostream &OS, ArrayRef<uint8_t> Data,
+ uint64_t Offset) const;
+
+ /// Extract data from the binary corresponding to [Address, Address + Size)
+ /// range. Return an empty ArrayRef if the address range does not belong to
+ /// any section in the binary, crosses a section boundary, or falls into a
+ /// virtual section.
+ ArrayRef<uint8_t> extractData(uint64_t Address, uint64_t Size) const;
+
/// Print a range of instructions. /// Print a range of instructions.
template <typename Itr> template <typename Itr>
uint64_t uint64_t
bolt/include/bolt/Core/BinaryFunction.h
@@ -2060,6 +2060,11 @@ public:
return Islands ? Islands->getAlignment() : 1; return Islands ? Islands->getAlignment() : 1;
} }
+ /// If there is a constant island in the range [StartOffset, EndOffset),
+ /// return its address.
+ std::optional<uint64_t> getIslandInRange(uint64_t StartOffset,
+ uint64_t EndOffset) const;
+
uint64_t uint64_t
estimateConstantIslandSize(const BinaryFunction *OnBehalfOf = nullptr) const { estimateConstantIslandSize(const BinaryFunction *OnBehalfOf = nullptr) const {
if (!Islands) if (!Islands)
bolt/lib/Core/BinaryContext.cpp
@@ -1759,7 +1759,11 @@ void BinaryContext::preprocessDebugInfo() {
dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr); dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
if (std::optional<uint64_t> DWOID = CU->getDWOId()) { if (std::optional<uint64_t> DWOID = CU->getDWOId()) {
auto Iter = DWOCUs.find(*DWOID); auto Iter = DWOCUs.find(*DWOID);
- assert(Iter != DWOCUs.end() && "DWO CU was not found.");+ if (Iter == DWOCUs.end()) {
+ this->errs() << "BOLT-ERROR: DWO CU was not found for " << Name
+ << '\n';
+ exit(1);
+ }
Name = dwarf::toString( Name = dwarf::toString(
Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr); Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
} }
@@ -1942,6 +1946,43 @@ static void printDebugInfo(raw_ostream &OS, const MCInst &Instruction,
OS << " discriminator:" << Row.Discriminator; OS << " discriminator:" << Row.Discriminator;
} }
+ArrayRef<uint8_t> BinaryContext::extractData(uint64_t Address,
+ uint64_t Size) const {
+ ArrayRef<uint8_t> Res;
+
+ const ErrorOr<const BinarySection &> Section = getSectionForAddress(Address);
+ if (!Section || Section->isVirtual())
+ return Res;
+
+ if (!Section->containsRange(Address, Size))
+ return Res;
+
+ auto *Bytes =
+ reinterpret_cast<const uint8_t *>(Section->getContents().data());
+ return ArrayRef<uint8_t>(Bytes + Address - Section->getAddress(), Size);
+}
+
+void BinaryContext::printData(raw_ostream &OS, ArrayRef<uint8_t> Data,
+ uint64_t Offset) const {
+ DataExtractor DE(Data, AsmInfo->isLittleEndian(),
+ AsmInfo->getCodePointerSize());
+ uint64_t DataOffset = 0;
+ while (DataOffset + 4 <= Data.size()) {
+ OS << format(" %08" PRIx64 ": \t.word\t0x", Offset + DataOffset);
+ const auto Word = DE.getUnsigned(&DataOffset, 4);
+ OS << Twine::utohexstr(Word) << '\n';
+ }
+ if (DataOffset + 2 <= Data.size()) {
+ OS << format(" %08" PRIx64 ": \t.short\t0x", Offset + DataOffset);
+ const auto Short = DE.getUnsigned(&DataOffset, 2);
+ OS << Twine::utohexstr(Short) << '\n';
+ }
+ if (DataOffset + 1 == Data.size()) {
+ OS << format(" %08" PRIx64 ": \t.byte\t0x%x\n", Offset + DataOffset,
+ Data[DataOffset]);
+ }
+}
+
void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction, void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction,
uint64_t Offset, uint64_t Offset,
const BinaryFunction *Function, const BinaryFunction *Function,
bolt/lib/Core/BinaryFunction.cpp
@@ -491,11 +491,27 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
// Offset of the instruction in function. // Offset of the instruction in function.
uint64_t Offset = 0; uint64_t Offset = 0;
+ auto printConstantIslandInRange = [&](uint64_t Start, uint64_t End) {
+ assert(Start <= End && "Invalid range");
+ std::optional<uint64_t> IslandOffset = getIslandInRange(Start, End);
+
+ if (!IslandOffset)
+ return;
+
+ const size_t IslandSize = getSizeOfDataInCodeAt(*IslandOffset);
+ BC.printData(OS, BC.extractData(getAddress() + *IslandOffset, IslandSize),
+ *IslandOffset);
+ };
+
if (BasicBlocks.empty() && !Instructions.empty()) { if (BasicBlocks.empty() && !Instructions.empty()) {
// Print before CFG was built. // Print before CFG was built.
+ uint64_t PrevOffset = 0;
for (const std::pair<const uint32_t, MCInst> &II : Instructions) { for (const std::pair<const uint32_t, MCInst> &II : Instructions) {
Offset = II.first; Offset = II.first;
+ // Print any constant islands inbeetween the instructions.
+ printConstantIslandInRange(PrevOffset, Offset);
+
// Print label if exists at this offset. // Print label if exists at this offset.
auto LI = Labels.find(Offset); auto LI = Labels.find(Offset);
if (LI != Labels.end()) { if (LI != Labels.end()) {
@@ -506,7 +522,12 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
} }
BC.printInstruction(OS, II.second, Offset, this); BC.printInstruction(OS, II.second, Offset, this);
+
+ PrevOffset = Offset;
} }
+
+ // Print any data at the end of the function.
+ printConstantIslandInRange(PrevOffset, getMaxSize());
} }
StringRef SplitPointMsg = ""; StringRef SplitPointMsg = "";
@@ -1048,6 +1069,19 @@ size_t BinaryFunction::getSizeOfDataInCodeAt(uint64_t Offset) const {
return getSize() - Offset; return getSize() - Offset;
} }
+std::optional<uint64_t>
+BinaryFunction::getIslandInRange(uint64_t StartOffset,
+ uint64_t EndOffset) const {
+ if (!Islands)
+ return std::nullopt;
+
+ auto Iter = llvm::lower_bound(Islands->DataOffsets, StartOffset);
+ if (Iter != Islands->DataOffsets.end() && *Iter < EndOffset)
+ return *Iter;
+
+ return std::nullopt;
+}
+
bool BinaryFunction::isZeroPaddingAt(uint64_t Offset) const { bool BinaryFunction::isZeroPaddingAt(uint64_t Offset) const {
ArrayRef<uint8_t> FunctionData = *getData(); ArrayRef<uint8_t> FunctionData = *getData();
uint64_t EndOfCode = getSize(); uint64_t EndOfCode = getSize();
bolt/lib/RuntimeLibs/RuntimeLibrary.cpp
@@ -18,6 +18,7 @@
#include "llvm/Object/Archive.h" #include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
#define DEBUG_TYPE "bolt-rtlib" #define DEBUG_TYPE "bolt-rtlib"
@@ -38,6 +39,23 @@ std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX); llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
} }
llvm::sys::path::append(LibPath, LibFileName); llvm::sys::path::append(LibPath, LibFileName);
+ if (!llvm::sys::fs::exists(LibPath)) {
+ // If it is a symlink, check the directory that the symlink points to.
+ if (llvm::sys::fs::is_symlink_file(ToolPath)) {
+ SmallString<256> RealPath;
+ llvm::sys::fs::real_path(ToolPath, RealPath);
+ if (llvm::ErrorOr<std::string> P =
+ llvm::sys::findProgramByName(RealPath)) {
+ outs() << "BOLT-INFO: library not found: " << LibPath << "\n"
+ << "BOLT-INFO: " << ToolPath << " is a symlink; will look up "
+ << LibFileName
+ << " at the target directory that the symlink points to\n";
+ return getLibPath(*P, LibFileName);
+ }
+ }
+ errs() << "BOLT-ERROR: library not found: " << LibPath << "\n";
+ exit(1);
+ }
return std::string(LibPath); return std::string(LibPath);
} }
bolt/test/AArch64/data-in-code.s
@@ -0,0 +1,31 @@
+## Check that llvm-bolt prints data embedded in code.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -fno-PIC -no-pie %t.o -o %t.exe -nostdlib \
+# RUN: -fuse-ld=lld -Wl,-q
+
+## Check disassembly of BOLT input.
+# RUN: llvm-objdump %t.exe -d | FileCheck %s
+
+# RUN: llvm-bolt %t.exe -o %t.bolt --print-disasm | FileCheck %s
+
+.text
+.balign 4
+
+.global _start
+.type _start, %function
+_start:
+ mov x0, #0x0
+ .word 0x4f82e010
+ ret
+ .byte 0x0, 0xff, 0x42
+# CHECK-LABEL: _start
+# CHECK: mov x0, #0x0
+# CHECK-NEXT: .word 0x4f82e010
+# CHECK-NEXT: ret
+# CHECK-NEXT: .short 0xff00
+# CHECK-NEXT: .byte 0x42
+.size _start, .-_start
+
+## Force relocation mode.
+ .reloc 0, R_AARCH64_NONE
bolt/test/AArch64/exceptions-plt.cpp
@@ -2,7 +2,9 @@
// REQUIRES: system-linux // REQUIRES: system-linux
-// RUN: %clangxx %cxxflags -O1 -Wl,-q,-znow %s -o %t.exe+// RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+// RUN: %clangxx %cxxflags -O1 -Wl,-q,-znow %s %t.so -o %t.exe
// RUN: llvm-bolt %t.exe -o %t.bolt.exe --plt=all --print-only=.*main.* \ // RUN: llvm-bolt %t.exe -o %t.bolt.exe --plt=all --print-only=.*main.* \
// RUN: --print-finalized 2>&1 | FileCheck %s // RUN: --print-finalized 2>&1 | FileCheck %s
bolt/test/AArch64/plt-call.test
@@ -1,6 +1,8 @@
// Verify that PLTCall optimization works. // Verify that PLTCall optimization works.
-RUN: %clang %cflags %p/../Inputs/plt-tailcall.c \+RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+RUN: %clang %cflags %p/../Inputs/plt-tailcall.c %t.so \
RUN: -o %t -Wl,-q RUN: -o %t -Wl,-q
RUN: llvm-bolt %t -o %t.bolt --plt=all --print-plt --print-only=foo | FileCheck %s RUN: llvm-bolt %t -o %t.bolt --plt=all --print-plt --print-only=foo | FileCheck %s
bolt/test/X86/callcont-fallthru.s
@@ -1,7 +1,9 @@
## Ensures that a call continuation fallthrough count is set when using ## Ensures that a call continuation fallthrough count is set when using
## pre-aggregated perf data. ## pre-aggregated perf data.
-# RUN: %clangxx %cxxflags %s -o %t -Wl,-q -nostdlib+# RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+## Link against a DSO to ensure PLT entries.
+# RUN: %clangxx %cxxflags %s %t.so -o %t -Wl,-q -nostdlib
# RUN: link_fdata %s %t %t.pa1 PREAGG # RUN: link_fdata %s %t %t.pa1 PREAGG
# RUN: link_fdata %s %t %t.pa2 PREAGG2 # RUN: link_fdata %s %t %t.pa2 PREAGG2
# RUN: link_fdata %s %t %t.pa3 PREAGG3 # RUN: link_fdata %s %t %t.pa3 PREAGG3
bolt/test/X86/cfi-instrs-reordered.s
@@ -3,7 +3,9 @@
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: llvm-strip --strip-unneeded %t.o # RUN: llvm-strip --strip-unneeded %t.o
-# RUN: %clangxx %cflags %t.o -o %t.exe+# RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+## Link against a DSO to ensure PLT entries.
+# RUN: %clangxx %cflags %t.o %t.so -o %t.exe
# RUN: llvm-bolt %t.exe -o %t --reorder-blocks=cache --print-after-lowering \ # RUN: llvm-bolt %t.exe -o %t --reorder-blocks=cache --print-after-lowering \
# RUN: --print-only=_Z10SolveCubicddddPiPd 2>&1 | FileCheck %s # RUN: --print-only=_Z10SolveCubicddddPiPd 2>&1 | FileCheck %s
# #
bolt/test/X86/plt-call.test
@@ -1,6 +1,8 @@
// Verify that PLTCall optimization works. // Verify that PLTCall optimization works.
-RUN: %clang %cflags %p/../Inputs/plt-tailcall.c \+RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+RUN: %clang %cflags %p/../Inputs/plt-tailcall.c %t.so \
RUN: -o %t -Wl,-q RUN: -o %t -Wl,-q
RUN: llvm-bolt %t -o %t.bolt --plt=all --print-plt --print-only=foo | FileCheck %s RUN: llvm-bolt %t -o %t.bolt --plt=all --print-plt --print-only=foo | FileCheck %s
bolt/test/runtime/exceptions-plt.cpp
@@ -2,7 +2,9 @@
// REQUIRES: system-linux // REQUIRES: system-linux
-// RUN: %clangxx %cxxflags -O1 -Wl,-q,-znow %s -o %t.exe+// RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
+// Link against a DSO to ensure PLT entries.
+// RUN: %clangxx %cxxflags -O1 -Wl,-q,-znow %s %t.so -o %t.exe
// RUN: llvm-bolt %t.exe -o %t.bolt.exe --plt=all // RUN: llvm-bolt %t.exe -o %t.bolt.exe --plt=all
// RUN: %t.bolt.exe // RUN: %t.bolt.exe
bolt/test/runtime/plt-lld.test
@@ -1,14 +1,15 @@
// This test checks that the pointers to PLT are properly updated. // This test checks that the pointers to PLT are properly updated.
-// The test is using lld linker.+// The test uses lld and links against a DSO to ensure PLT entries.
+RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so
// Non-PIE: // Non-PIE:
-RUN: %clang %cflags -no-pie %p/../Inputs/plt.c -fuse-ld=lld \+RUN: %clang %cflags -no-pie %p/../Inputs/plt.c %t.so -fuse-ld=lld \
RUN: -o %t.lld.exe -Wl,-q RUN: -o %t.lld.exe -Wl,-q
RUN: llvm-bolt %t.lld.exe -o %t.lld.bolt.exe --use-old-text=0 --lite=0 RUN: llvm-bolt %t.lld.exe -o %t.lld.bolt.exe --use-old-text=0 --lite=0
RUN: %t.lld.bolt.exe | FileCheck %s RUN: %t.lld.bolt.exe | FileCheck %s
// PIE: // PIE:
-RUN: %clang %cflags -fPIC -pie %p/../Inputs/plt.c -fuse-ld=lld \+RUN: %clang %cflags -fPIC -pie %p/../Inputs/plt.c %t.so -fuse-ld=lld \
RUN: -o %t.lld.pie.exe -Wl,-q RUN: -o %t.lld.pie.exe -Wl,-q
RUN: llvm-bolt %t.lld.pie.exe -o %t.lld.bolt.pie.exe --use-old-text=0 --lite=0 RUN: llvm-bolt %t.lld.pie.exe -o %t.lld.bolt.pie.exe --use-old-text=0 --lite=0
RUN: %t.lld.bolt.pie.exe | FileCheck %s RUN: %t.lld.bolt.pie.exe | FileCheck %s
clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -494,18 +494,31 @@ genReferencesBlock(const std::vector<Reference> &References,
static std::unique_ptr<TagNode> static std::unique_ptr<TagNode>
writeFileDefinition(const Location &L, writeFileDefinition(const Location &L,
std::optional<StringRef> RepositoryUrl = std::nullopt) { std::optional<StringRef> RepositoryUrl = std::nullopt) {
- if (!L.IsFileInRootDir || !RepositoryUrl)+ if (!L.IsFileInRootDir && !RepositoryUrl)
return std::make_unique<TagNode>( return std::make_unique<TagNode>(
HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) + HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) +
" of file " + L.Filename); " of file " + L.Filename);
SmallString<128> FileURL(*RepositoryUrl); SmallString<128> FileURL(*RepositoryUrl);
- llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename);+ llvm::sys::path::append(
+ FileURL, llvm::sys::path::Style::posix,
+ // If we're on Windows, the file name will be in the wrong format, and
+ // append won't convert the full path being appended to the correct
+ // format, so we need to do that here.
+ llvm::sys::path::convert_to_slash(
+ L.Filename,
+ // The style here is the current style of the path, not the one we're
+ // targeting. If the string is already in the posix style, it will do
+ // nothing.
+ llvm::sys::path::Style::windows));
auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P); auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P);
Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line ")); Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line "));
auto LocNumberNode = auto LocNumberNode =
std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber)); std::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber));
// The links to a specific line in the source code use the github / // The links to a specific line in the source code use the github /
// googlesource notation so it won't work for all hosting pages. // googlesource notation so it won't work for all hosting pages.
+ // FIXME: we probably should have a configuration setting for line number
+ // rendering in the HTML. For example, GitHub uses #L22, while googlesource
+ // uses #22 for line numbers.
LocNumberNode->Attributes.emplace_back( LocNumberNode->Attributes.emplace_back(
"href", (FileURL + "#" + std::to_string(L.LineNumber)).str()); "href", (FileURL + "#" + std::to_string(L.LineNumber)).str());
Node->Children.emplace_back(std::move(LocNumberNode)); Node->Children.emplace_back(std::move(LocNumberNode));
@@ -964,7 +977,7 @@ HTMLGenerator::generateDocs(StringRef RootDir,
for (const auto &Group : FileToInfos) { for (const auto &Group : FileToInfos) {
std::error_code FileErr; std::error_code FileErr;
llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr, llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr,
- llvm::sys::fs::OF_None);+ llvm::sys::fs::OF_Text);
if (FileErr) { if (FileErr) {
return llvm::createStringError(FileErr, "Error opening file '%s'", return llvm::createStringError(FileErr, "Error opening file '%s'",
Group.getKey().str().c_str()); Group.getKey().str().c_str());
@@ -1047,7 +1060,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
llvm::SmallString<128> FilePath; llvm::SmallString<128> FilePath;
llvm::sys::path::native(CDCtx.OutDirectory, FilePath); llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
llvm::sys::path::append(FilePath, "index_json.js"); llvm::sys::path::append(FilePath, "index_json.js");
- llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);+ llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr != OK) { if (FileErr != OK) {
return llvm::createStringError(llvm::inconvertibleErrorCode(), return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating index file: " + "error creating index file: " +
@@ -1108,7 +1121,7 @@ static llvm::Error genIndex(const ClangDocContext &CDCtx) {
llvm::SmallString<128> IndexPath; llvm::SmallString<128> IndexPath;
llvm::sys::path::native(CDCtx.OutDirectory, IndexPath); llvm::sys::path::native(CDCtx.OutDirectory, IndexPath);
llvm::sys::path::append(IndexPath, "index.html"); llvm::sys::path::append(IndexPath, "index.html");
- llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_None);+ llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr != OK) { if (FileErr != OK) {
return llvm::createStringError(llvm::inconvertibleErrorCode(), return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating main index: " + "error creating main index: " +
clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -300,7 +300,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
llvm::SmallString<128> FilePath; llvm::SmallString<128> FilePath;
llvm::sys::path::native(CDCtx.OutDirectory, FilePath); llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
llvm::sys::path::append(FilePath, "all_files.md"); llvm::sys::path::append(FilePath, "all_files.md");
- llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);+ llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr) if (FileErr)
return llvm::createStringError(llvm::inconvertibleErrorCode(), return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating index file: " + "error creating index file: " +
@@ -323,7 +323,7 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
llvm::SmallString<128> FilePath; llvm::SmallString<128> FilePath;
llvm::sys::path::native(CDCtx.OutDirectory, FilePath); llvm::sys::path::native(CDCtx.OutDirectory, FilePath);
llvm::sys::path::append(FilePath, "index.md"); llvm::sys::path::append(FilePath, "index.md");
- llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None);+ llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
if (FileErr) if (FileErr)
return llvm::createStringError(llvm::inconvertibleErrorCode(), return llvm::createStringError(llvm::inconvertibleErrorCode(),
"error creating index file: " + "error creating index file: " +
@@ -407,7 +407,7 @@ MDGenerator::generateDocs(StringRef RootDir,
for (const auto &Group : FileToInfos) { for (const auto &Group : FileToInfos) {
std::error_code FileErr; std::error_code FileErr;
llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr, llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr,
- llvm::sys::fs::OF_None);+ llvm::sys::fs::OF_Text);
if (FileErr) { if (FileErr) {
return llvm::createStringError(FileErr, "Error opening file '%s'", return llvm::createStringError(FileErr, "Error opening file '%s'",
Group.getKey().str().c_str()); Group.getKey().str().c_str());
clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -347,7 +347,7 @@ YAMLGenerator::generateDocs(StringRef RootDir,
} }
std::error_code FileErr; std::error_code FileErr;
- llvm::raw_fd_ostream InfoOS(Path, FileErr, llvm::sys::fs::OF_None);+ llvm::raw_fd_ostream InfoOS(Path, FileErr, llvm::sys::fs::OF_Text);
if (FileErr) { if (FileErr) {
return llvm::createStringError(FileErr, "Error opening file '%s'", return llvm::createStringError(FileErr, "Error opening file '%s'",
Path.c_str()); Path.c_str());
clang-tools-extra/clang-include-fixer/FuzzySymbolIndex.cpp
@@ -131,7 +131,7 @@ FuzzySymbolIndex::queryRegexp(const std::vector<std::string> &Tokens) {
llvm::Expected<std::unique_ptr<FuzzySymbolIndex>> llvm::Expected<std::unique_ptr<FuzzySymbolIndex>>
FuzzySymbolIndex::createFromYAML(StringRef FilePath) { FuzzySymbolIndex::createFromYAML(StringRef FilePath) {
- auto Buffer = llvm::MemoryBuffer::getFile(FilePath);+ auto Buffer = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
if (!Buffer) if (!Buffer)
return llvm::errorCodeToError(Buffer.getError()); return llvm::errorCodeToError(Buffer.getError());
return std::make_unique<MemSymbolIndex>( return std::make_unique<MemSymbolIndex>(
clang-tools-extra/clang-include-fixer/YamlSymbolIndex.cpp
@@ -22,7 +22,7 @@ namespace include_fixer {
llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>> llvm::ErrorOr<std::unique_ptr<YamlSymbolIndex>>
YamlSymbolIndex::createFromFile(llvm::StringRef FilePath) { YamlSymbolIndex::createFromFile(llvm::StringRef FilePath) {
- auto Buffer = llvm::MemoryBuffer::getFile(FilePath);+ auto Buffer = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
if (!Buffer) if (!Buffer)
return Buffer.getError(); return Buffer.getError();
clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -95,7 +95,7 @@ bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
// Parse YAML files in parallel. // Parse YAML files in parallel.
Pool.async( Pool.async(
[&AddSymbols](std::string Path) { [&AddSymbols](std::string Path) {
- auto Buffer = llvm::MemoryBuffer::getFile(Path);+ auto Buffer = llvm::MemoryBuffer::getFile(Path, /*IsText=*/true);
if (!Buffer) { if (!Buffer) {
llvm::errs() << "Can't open " << Path << "\n"; llvm::errs() << "Can't open " << Path << "\n";
return; return;
@@ -114,7 +114,7 @@ bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) {
} }
} }
- llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_None);+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_Text);
if (EC) { if (EC) {
llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message() llvm::errs() << "Can't open '" << OutputFile << "': " << EC.message()
<< '\n'; << '\n';
clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
@@ -415,7 +415,7 @@ int includeFixerMain(int argc, const char **argv) {
llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n"; llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n";
return 1; return 1;
} }
- auto Buffer = llvm::MemoryBuffer::getFile(FilePath);+ auto Buffer = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
if (!Buffer) { if (!Buffer) {
errs() << "Couldn't open file: " + FilePath.str() + ": " errs() << "Couldn't open file: " + FilePath.str() + ": "
<< Buffer.getError().message() + "\n"; << Buffer.getError().message() + "\n";
clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp
@@ -82,7 +82,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher( Finder->addMatcher(
cxxConstructExpr( cxxConstructExpr(
hasDeclaration(cxxMethodDecl(hasName("basic_string"))), hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
- hasArgument(0, hasType(qualType(isInteger()))),+ argumentCountIs(2), hasArgument(0, hasType(qualType(isInteger()))),
hasArgument(1, hasType(qualType(isInteger()))), hasArgument(1, hasType(qualType(isInteger()))),
anyOf( anyOf(
// Detect the expression: string('x', 40); // Detect the expression: string('x', 40);
@@ -102,7 +102,7 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
cxxConstructExpr( cxxConstructExpr(
hasDeclaration(cxxConstructorDecl(ofClass( hasDeclaration(cxxConstructorDecl(ofClass(
cxxRecordDecl(hasAnyName(removeNamespaces(StringNames)))))), cxxRecordDecl(hasAnyName(removeNamespaces(StringNames)))))),
- hasArgument(0, hasType(CharPtrType)),+ argumentCountIs(2), hasArgument(0, hasType(CharPtrType)),
hasArgument(1, hasType(isInteger())), hasArgument(1, hasType(isInteger())),
anyOf( anyOf(
// Detect the expression: string("...", 0); // Detect the expression: string("...", 0);
@@ -114,7 +114,34 @@ void StringConstructorCheck::registerMatchers(MatchFinder *Finder) {
// Detect the expression: string("lit", 5) // Detect the expression: string("lit", 5)
allOf(hasArgument(0, ConstStrLiteral.bind("literal-with-length")), allOf(hasArgument(0, ConstStrLiteral.bind("literal-with-length")),
hasArgument(1, ignoringParenImpCasts( hasArgument(1, ignoringParenImpCasts(
- integerLiteral().bind("int"))))))+ integerLiteral().bind("length"))))))
+ .bind("constructor"),
+ this);
+
+ // Check the literal string constructor with char pointer, start position and
+ // length parameters. [i.e. string (const char* s, size_t pos, size_t count);]
+ Finder->addMatcher(
+ cxxConstructExpr(
+ hasDeclaration(cxxConstructorDecl(ofClass(
+ cxxRecordDecl(hasAnyName(removeNamespaces(StringNames)))))),
+ argumentCountIs(3), hasArgument(0, hasType(CharPtrType)),
+ hasArgument(1, hasType(qualType(isInteger()))),
+ hasArgument(2, hasType(qualType(isInteger()))),
+ anyOf(
+ // Detect the expression: string("...", 1, 0);
+ hasArgument(2, ZeroExpr.bind("empty-string")),
+ // Detect the expression: string("...", -4, 1);
+ hasArgument(1, NegativeExpr.bind("negative-pos")),
+ // Detect the expression: string("...", 0, -4);
+ hasArgument(2, NegativeExpr.bind("negative-length")),
+ // Detect the expression: string("lit", 0, 0x1234567);
+ hasArgument(2, LargeLengthExpr.bind("large-length")),
+ // Detect the expression: string("lit", 1, 5)
+ allOf(hasArgument(0, ConstStrLiteral.bind("literal-with-length")),
+ hasArgument(
+ 1, ignoringParenImpCasts(integerLiteral().bind("pos"))),
+ hasArgument(2, ignoringParenImpCasts(
+ integerLiteral().bind("length"))))))
.bind("constructor"), .bind("constructor"),
this); this);
@@ -155,14 +182,27 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
diag(Loc, "constructor creating an empty string"); diag(Loc, "constructor creating an empty string");
} else if (Result.Nodes.getNodeAs<Expr>("negative-length")) { } else if (Result.Nodes.getNodeAs<Expr>("negative-length")) {
diag(Loc, "negative value used as length parameter"); diag(Loc, "negative value used as length parameter");
+ } else if (Result.Nodes.getNodeAs<Expr>("negative-pos")) {
+ diag(Loc, "negative value used as position of the "
+ "first character parameter");
} else if (Result.Nodes.getNodeAs<Expr>("large-length")) { } else if (Result.Nodes.getNodeAs<Expr>("large-length")) {
if (WarnOnLargeLength) if (WarnOnLargeLength)
diag(Loc, "suspicious large length parameter"); diag(Loc, "suspicious large length parameter");
} else if (Result.Nodes.getNodeAs<Expr>("literal-with-length")) { } else if (Result.Nodes.getNodeAs<Expr>("literal-with-length")) {
const auto *Str = Result.Nodes.getNodeAs<StringLiteral>("str"); const auto *Str = Result.Nodes.getNodeAs<StringLiteral>("str");
- const auto *Lit = Result.Nodes.getNodeAs<IntegerLiteral>("int");+ const auto *Length = Result.Nodes.getNodeAs<IntegerLiteral>("length");
- if (Lit->getValue().ugt(Str->getLength())) {+ if (Length->getValue().ugt(Str->getLength())) {
diag(Loc, "length is bigger than string literal size"); diag(Loc, "length is bigger than string literal size");
+ return;
+ }
+ if (const auto *Pos = Result.Nodes.getNodeAs<IntegerLiteral>("pos")) {
+ if (Pos->getValue().uge(Str->getLength())) {
+ diag(Loc, "position of the first character parameter is bigger than "
+ "string literal character range");
+ } else if (Length->getValue().ugt(
+ (Str->getLength() - Pos->getValue()).getZExtValue())) {
+ diag(Loc, "length is bigger than remaining string literal size");
+ }
} }
} else if (const auto *Ptr = Result.Nodes.getNodeAs<Expr>("from-ptr")) { } else if (const auto *Ptr = Result.Nodes.getNodeAs<Expr>("from-ptr")) {
Expr::EvalResult ConstPtr; Expr::EvalResult ConstPtr;
clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
return cast<BinaryOperator>(Left)->getOpcode() == return cast<BinaryOperator>(Left)->getOpcode() ==
cast<BinaryOperator>(Right)->getOpcode(); cast<BinaryOperator>(Right)->getOpcode();
case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::UnaryExprOrTypeTraitExprClass:
- const auto *LeftUnaryExpr =+ const auto *LeftUnaryExpr = cast<UnaryExprOrTypeTraitExpr>(Left);
- cast<UnaryExprOrTypeTraitExpr>(Left);+ const auto *RightUnaryExpr = cast<UnaryExprOrTypeTraitExpr>(Right);
- const auto *RightUnaryExpr =
- cast<UnaryExprOrTypeTraitExpr>(Right);
if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType()) if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType())
return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() && return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() &&
LeftUnaryExpr->getArgumentType() == LeftUnaryExpr->getArgumentType() ==
@@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr(
Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0); Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0);
OperandExpr = OverloadedOperatorExpr; OperandExpr = OverloadedOperatorExpr;
- Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator());+ Opcode = BinaryOperator::getOverloadedOpcode(
+ OverloadedOperatorExpr->getOperator());
if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr)) if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr))
return false; return false;
@@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr(
} }
// Checks for expressions like (X == 4) && (Y != 9) // Checks for expressions like (X == 4) && (Y != 9)
-static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) {+static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp,
+ const ASTContext *AstCtx) {
const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS()); const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS());
const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS()); const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS());
@@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A
return false; return false;
} }
+static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant(
+ const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
+ if (areSidesBinaryConstExpressions(BinOp, AstCtx))
+ return true;
+
+ const Expr *Lhs = BinOp->getLHS();
+ const Expr *Rhs = BinOp->getRHS();
+
+ if (!Lhs || !Rhs)
+ return false;
+
+ auto IsDefineExpr = [AstCtx](const Expr *E) {
+ const SourceRange Lsr = E->getSourceRange();
+ if (!Lsr.getBegin().isMacroID() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(*AstCtx))
+ return false;
+ return true;
+ };
+
+ return IsDefineExpr(Lhs) || IsDefineExpr(Rhs);
+}
+
// Retrieves integer constant subexpressions from binary operator expressions // Retrieves integer constant subexpressions from binary operator expressions
// that have two equivalent sides. // that have two equivalent sides.
// E.g.: from (X == 5) && (X == 5) retrieves 5 and 5. // E.g.: from (X == 5) && (X == 5) retrieves 5 and 5.
@@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp,
} }
static bool isSameRawIdentifierToken(const Token &T1, const Token &T2, static bool isSameRawIdentifierToken(const Token &T1, const Token &T2,
- const SourceManager &SM) {+ const SourceManager &SM) {
if (T1.getKind() != T2.getKind()) if (T1.getKind() != T2.getKind())
return false; return false;
if (T1.isNot(tok::raw_identifier)) if (T1.isNot(tok::raw_identifier))
@@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr,
const ASTContext *AstCtx) { const ASTContext *AstCtx) {
if (!LhsExpr || !RhsExpr) if (!LhsExpr || !RhsExpr)
return false; return false;
- SourceRange Lsr = LhsExpr->getSourceRange();+ const SourceRange Lsr = LhsExpr->getSourceRange();
- SourceRange Rsr = RhsExpr->getSourceRange();+ const SourceRange Rsr = RhsExpr->getSourceRange();
if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID()) if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID())
return false; return false;
@@ -847,11 +869,83 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr,
if (!LhsExpr || !RhsExpr) if (!LhsExpr || !RhsExpr)
return false; return false;
- SourceLocation LhsLoc = LhsExpr->getExprLoc();+ const SourceLocation LhsLoc = LhsExpr->getExprLoc();
- SourceLocation RhsLoc = RhsExpr->getExprLoc();+ const SourceLocation RhsLoc = RhsExpr->getExprLoc();
return LhsLoc.isMacroID() != RhsLoc.isMacroID(); return LhsLoc.isMacroID() != RhsLoc.isMacroID();
} }
+
+static bool areStringsSameIgnoreSpaces(const llvm::StringRef Left,
+ const llvm::StringRef Right) {
+ if (Left == Right)
+ return true;
+
+ // Do running comparison ignoring spaces
+ llvm::StringRef L = Left.trim();
+ llvm::StringRef R = Right.trim();
+ while (!L.empty() && !R.empty()) {
+ L = L.ltrim();
+ R = R.ltrim();
+ if (L.empty() && R.empty())
+ return true;
+ // If symbol compared are different ==> strings are not the same
+ if (L.front() != R.front())
+ return false;
+ L = L.drop_front();
+ R = R.drop_front();
+ }
+ return L.empty() && R.empty();
+}
+
+static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp,
+ const ASTContext *Context) {
+
+ if (!BinOp)
+ return false;
+
+ const Expr *Lhs = BinOp->getLHS();
+ const Expr *Rhs = BinOp->getRHS();
+ const SourceManager &SM = Context->getSourceManager();
+
+ const SourceRange Lsr = Lhs->getSourceRange();
+ const SourceRange Rsr = Rhs->getSourceRange();
+ if (Lsr.getBegin().isMacroID()) {
+ // Left is macro so right macro too
+ if (Rsr.getBegin().isMacroID()) {
+ // Both sides are macros so they are same macro or literal
+ const llvm::StringRef L = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Lsr), SM, Context->getLangOpts(), 0);
+ const llvm::StringRef R = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Rsr), SM, Context->getLangOpts(), 0);
+ return areStringsSameIgnoreSpaces(L, R);
+ }
+ // Left is macro but right is not so they are not same macro or literal
+ return false;
+ }
+ const auto *Lil = dyn_cast<IntegerLiteral>(Lhs);
+ const auto *Ril = dyn_cast<IntegerLiteral>(Rhs);
+ if (Lil && Ril)
+ return Lil->getValue() == Ril->getValue();
+
+ const auto *LStrl = dyn_cast<StringLiteral>(Lhs);
+ const auto *RStrl = dyn_cast<StringLiteral>(Rhs);
+ if (Lil && Ril) {
+ const llvm::StringRef L = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(LStrl->getBeginLoc()), SM,
+ Context->getLangOpts(), 0);
+ const llvm::StringRef R = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(RStrl->getBeginLoc()), SM,
+ Context->getLangOpts(), 0);
+ return L.compare(R) == 0;
+ }
+
+ const auto *Lbl = dyn_cast<CXXBoolLiteralExpr>(Lhs);
+ const auto *Rbl = dyn_cast<CXXBoolLiteralExpr>(Rhs);
+ if (Lbl && Rbl)
+ return Lbl->getValue() == Rbl->getValue();
+
+ return false;
+}
} // namespace } // namespace
void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -1089,7 +1183,6 @@ static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0); ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0);
} }
-
void RedundantExpressionCheck::checkBitwiseExpr( void RedundantExpressionCheck::checkBitwiseExpr(
const MatchFinder::MatchResult &Result) { const MatchFinder::MatchResult &Result) {
if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>( if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
@@ -1134,8 +1227,8 @@ void RedundantExpressionCheck::checkBitwiseExpr(
ConstExpr)) ConstExpr))
return; return;
- if((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())+ if ((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
- return;+ return;
SourceLocation Loc = IneffectiveOperator->getOperatorLoc(); SourceLocation Loc = IneffectiveOperator->getOperatorLoc();
@@ -1276,19 +1369,23 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
return; return;
} }
- if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {+ if (areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant(
+ BinOp, Result.Context)) {
const Expr *LhsConst = nullptr, *RhsConst = nullptr; const Expr *LhsConst = nullptr, *RhsConst = nullptr;
BinaryOperatorKind MainOpcode{}, SideOpcode{}; BinaryOperatorKind MainOpcode{}, SideOpcode{};
-+ if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {
- if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,+ if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,
- LhsConst, RhsConst, Result.Context))+ LhsConst, RhsConst, Result.Context))
- return;+ return;
-+
- if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||+ if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
- areExprsMacroAndNonMacro(LhsConst, RhsConst))+ areExprsMacroAndNonMacro(LhsConst, RhsConst))
- return;+ return;
+ } else {
+ if (!areExprsSameMacroOrLiteral(BinOp, Result.Context))
+ return;
+ }
} }
-
diag(BinOp->getOperatorLoc(), "both sides of operator are equivalent"); diag(BinOp->getOperatorLoc(), "both sides of operator are equivalent");
} }
clang-tools-extra/docs/ReleaseNotes.rst
@@ -97,10 +97,19 @@ New check aliases
Changes in existing checks Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
+- Improved :doc:`bugprone-string-constructor
+ <clang-tidy/checks/bugprone/string-constructor>` check to find suspicious
+ calls of ``std::string`` constructor with char pointer, start position and
+ length parameters.
+
- Improved :doc:`bugprone-unsafe-functions - Improved :doc:`bugprone-unsafe-functions
<clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying <clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying
additional C++ member functions to match. additional C++ member functions to match.
+- Improved :doc:`misc-redundant-expression
+ <clang-tidy/checks/misc/redundant-expression>` check by providing additional
+ examples and fixing some macro related false positives.
+
Removed checks Removed checks
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
clang-tools-extra/docs/clang-tidy/checks/bugprone/string-constructor.rst
@@ -21,6 +21,7 @@ Examples:
.. code-block:: c++ .. code-block:: c++
std::string("test", 200); // Will include random characters after "test". std::string("test", 200); // Will include random characters after "test".
+ std::string("test", 2, 5); // Will include random characters after "st".
std::string_view("test", 200); std::string_view("test", 200);
Creating an empty string from constructors with parameters is considered Creating an empty string from constructors with parameters is considered
@@ -31,8 +32,19 @@ Examples:
.. code-block:: c++ .. code-block:: c++
std::string("test", 0); // Creation of an empty string. std::string("test", 0); // Creation of an empty string.
+ std::string("test", 1, 0);
std::string_view("test", 0); std::string_view("test", 0);
+Passing an invalid first character position parameter to constructor will
+cause ``std::out_of_range`` exception at runtime.
+
+Examples:
+
+.. code-block:: c++
+
+ std::string("test", -1, 10); // Negative first character position.
+ std::string("test", 10, 10); // First character position is bigger than string literal character range".
+
Options Options
------- -------
clang-tools-extra/docs/clang-tidy/checks/misc/redundant-expression.rst
@@ -19,12 +19,14 @@ Examples:
.. code-block:: c++ .. code-block:: c++
- ((x+1) | (x+1)) // (x+1) is redundant+ ((x+1) | (x+1)) // (x+1) is redundant
- (p->x == p->x) // always true+ (p->x == p->x) // always true
- (p->x < p->x) // always false+ (p->x < p->x) // always false
- (speed - speed + 1 == 12) // speed - speed is always zero+ (speed - speed + 1 == 12) // speed - speed is always zero
- int b = a | 4 | a // identical expr on both sides+ int b = a | 4 | a // identical expr on both sides
- ((x=1) | (x=1)) // expression is identical+ ((x=1) | (x=1)) // expression is identical
+ (DEFINE_1 | DEFINE_1) // same macro on the both sides
+ ((DEF_1 + DEF_2) | (DEF_1+DEF_2)) // expressions differ in spaces only
Floats are handled except in the case that NaNs are checked like so: Floats are handled except in the case that NaNs are checked like so:
clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Circle.cpp
@@ -8,4 +8,5 @@ double Circle::area() const {
double Circle::perimeter() const { double Circle::perimeter() const {
return 3.141 * radius_; return 3.141 * radius_;
-}
clang-tools-extra/test/clang-doc/basic-project.test
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t/docs %t/build // RUN: rm -rf %t && mkdir -p %t/docs %t/build
// RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json // RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json
-// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json+// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json --repository=https://repository.com
// RUN: FileCheck %s -input-file=%t/docs/index_json.js -check-prefix=JSON-INDEX // RUN: FileCheck %s -input-file=%t/docs/index_json.js -check-prefix=JSON-INDEX
// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE // RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE
// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefix=HTML-CALC // RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefix=HTML-CALC
@@ -54,130 +54,183 @@
// JSON-INDEX-NEXT: }; // JSON-INDEX-NEXT: };
// JSON-INDEX-NEXT: } // JSON-INDEX-NEXT: }
-// HTML-SHAPE: <h1>class Shape</h1>+// HTML-SHAPE: <h1>class Shape</h1>
-// HTML-SHAPE: <p>Defined at line 8 of file {{.*}}Shape.h</p>+// HTML-SHAPE-NEXT: <p>
-// HTML-SHAPE: <div>brief</div>+// HTML-SHAPE-NEXT: Defined at line
-// HTML-SHAPE: <p> Abstract base class for shapes.</p>+// HTML-SHAPE-NEXT: <a href="https://repository.com/./include/Shape.h#8">8</a>
-// HTML-SHAPE: <p> Provides a common interface for different types of shapes.</p>+// HTML-SHAPE-NEXT: of file
-// HTML-SHAPE: <h2 id="Functions">Functions</h2>+// HTML-SHAPE-NEXT: <a href="https://repository.com/./include/Shape.h">Shape.h</a>
-// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">area</h3>+// HTML-SHAPE-NEXT: </p>
-// HTML-SHAPE: <p>public double area()</p>+// HTML-SHAPE: <div>brief</div>
-// HTML-SHAPE: <div>brief</div>+// HTML-SHAPE: <p> Abstract base class for shapes.</p>
-// HTML-SHAPE: <p> Calculates the area of the shape.</p>+// HTML-SHAPE: <p> Provides a common interface for different types of shapes.</p>
-// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3>+// HTML-SHAPE: <h2 id="Functions">Functions</h2>
-// HTML-SHAPE: <p>public double perimeter()</p>+// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">area</h3>
-// HTML-SHAPE: <div>brief</div>+// HTML-SHAPE: <p>public double area()</p>
-// HTML-SHAPE: <p> Calculates the perimeter of the shape.</p>+// HTML-SHAPE: <div>brief</div>
-// HTML-SHAPE: <div>return</div>+// HTML-SHAPE: <p> Calculates the area of the shape.</p>
-// HTML-SHAPE: <p> double The perimeter of the shape.</p>+// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3>
-// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">~Shape</h3>+// HTML-SHAPE: <p>public double perimeter()</p>
-// HTML-SHAPE: <p>public void ~Shape()</p>+// HTML-SHAPE: <div>brief</div>
-// HTML-SHAPE: <p>Defined at line 13 of file {{.*}}Shape.h</p>+// HTML-SHAPE: <p> Calculates the perimeter of the shape.</p>
-// HTML-SHAPE: <div>brief</div>+// HTML-SHAPE: <div>return</div>
-// HTML-SHAPE: <p> Virtual destructor.</p>+// HTML-SHAPE: <p> double The perimeter of the shape.</p>
+// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">~Shape</h3>
+// HTML-SHAPE: <p>public void ~Shape()</p>
+// HTML-SHAPE: Defined at line
+// HTML-SHAPE-NEXT: <a href="https://repository.com/./include/Shape.h#13">13</a>
+// HTML-SHAPE-NEXT: of file
+// HTML-SHAPE-NEXT: <a href="https://repository.com/./include/Shape.h">Shape.h</a>
+// HTML-SHAPE: <div>brief</div>
+// HTML-SHAPE: <p> Virtual destructor.</p>
-// HTML-CALC: <h1>class Calculator</h1>+// HTML-CALC: <h1>class Calculator</h1>
-// HTML-CALC: <p>Defined at line 8 of file {{.*}}Calculator.h</p>+// HTML-CALC-NEXT: <p>
-// HTML-CALC: <div>brief</div>+// HTML-CALC-NEXT: Defined at line
-// HTML-CALC: <p> A simple calculator class.</p>+// HTML-CALC-NEXT: <a href="https://repository.com/./include/Calculator.h#8">8</a>
-// HTML-CALC: <p> Provides basic arithmetic operations.</p>+// HTML-CALC-NEXT: of file
-// HTML-CALC: <h2 id="Functions">Functions</h2>+// HTML-CALC-NEXT: <a href="https://repository.com/./include/Calculator.h">Calculator.h</a>
-// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">add</h3>+// HTML-CALC-NEXT: </p>
-// HTML-CALC: <p>public int add(int a, int b)</p>+// HTML-CALC: <div>brief</div>
-// HTML-CALC: <p>Defined at line 3 of file {{.*}}Calculator.cpp</p>+// HTML-CALC: <p> A simple calculator class.</p>
-// HTML-CALC: <div>brief</div>+// HTML-CALC: <p> Provides basic arithmetic operations.</p>
-// HTML-CALC: <p> Adds two integers.</p>+// HTML-CALC: <h2 id="Functions">Functions</h2>
-// HTML-CALC: <div>return</div>+// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">add</h3>
-// HTML-CALC: <p> int The sum of a and b.</p>+// HTML-CALC: <p>public int add(int a, int b)</p>
-// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">subtract</h3>+// HTML-CALC: Defined at line
-// HTML-CALC: <p>public int subtract(int a, int b)</p>+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp#3">3</a>
-// HTML-CALC: <p>Defined at line 7 of file {{.*}}Calculator.cpp</p>+// HTML-CALC-NEXT: of file
-// HTML-CALC: <div>brief</div>+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a>
-// HTML-CALC: <p> Subtracts the second integer from the first.</p>+// HTML-CALC: <div>brief</div>
-// HTML-CALC: <div>return</div>+// HTML-CALC: <p> Adds two integers.</p>
-// HTML-CALC: <p> int The result of a - b.</p>+// HTML-CALC: <div>return</div>
-// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">multiply</h3>+// HTML-CALC: <p> int The sum of a and b.</p>
-// HTML-CALC: <p>public int multiply(int a, int b)</p>+// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">subtract</h3>
-// HTML-CALC: <p>Defined at line 11 of file {{.*}}Calculator.cpp</p>+// HTML-CALC: <p>public int subtract(int a, int b)</p>
-// HTML-CALC: <div>brief</div>+// HTML-CALC: Defined at line
-// HTML-CALC: <p> Multiplies two integers.</p>+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp#7">7</a>
-// HTML-CALC: <div>return</div>+// HTML-CALC-NEXT: of file
-// HTML-CALC: <p> int The product of a and b.</p>+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a>
-// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">divide</h3>+// HTML-CALC: <div>brief</div>
-// HTML-CALC: <p>public double divide(int a, int b)</p>+// HTML-CALC: <p> Subtracts the second integer from the first.</p>
-// HTML-CALC: <p>Defined at line 15 of file {{.*}}Calculator.cpp</p>+// HTML-CALC: <div>return</div>
-// HTML-CALC: <div>brief</div>+// HTML-CALC: <p> int The result of a - b.</p>
-// HTML-CALC: <p> Divides the first integer by the second.</p>+// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">multiply</h3>
-// HTML-CALC: <div>return</div>+// HTML-CALC: <p>public int multiply(int a, int b)</p>
-// HTML-CALC: <p> double The result of a / b.</p>+// HTML-CALC: Defined at line
-// HTML-CALC: <div>throw</div>+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp#11">11</a>
-// HTML-CALC: <p>if b is zero.</p>+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a>
+// HTML-CALC: <div>brief</div>
+// HTML-CALC: <p> Multiplies two integers.</p>
+// HTML-CALC: <div>return</div>
+// HTML-CALC: <p> int The product of a and b.</p>
+// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">divide</h3>
+// HTML-CALC: <p>public double divide(int a, int b)</p>
+// HTML-CALC: Defined at line
+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp#15">15</a>
+// HTML-CALC-NEXT: of file
+// HTML-CALC-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a>
+// HTML-CALC: <div>brief</div>
+// HTML-CALC: <p> Divides the first integer by the second.</p>
+// HTML-CALC: <div>return</div>
+// HTML-CALC: <p> double The result of a / b.</p>
+// HTML-CALC: <div>throw</div>
+// HTML-CALC: <p>if b is zero.</p>
-// HTML-RECTANGLE: <h1>class Rectangle</h1>+// HTML-RECTANGLE: <h1>class Rectangle</h1>
-// HTML-RECTANGLE: <p>Defined at line 10 of file {{.*}}Rectangle.h</p>+// HTML-RECTANGLE-NEXT: <p>
-// HTML-RECTANGLE: <p> Represents a rectangle with a given width and height.</p+// HTML-RECTANGLE-NEXT: Defined at line
-// HTML-RECTANGLE: <p>+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./include/Rectangle.h#10">10</a>
-// HTML-RECTANGLE: Inherits from+// HTML-RECTANGLE-NEXT: of file
-// HTML-RECTANGLE: <a href="Shape.html">Shape</a>+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./include/Rectangle.h">Rectangle.h</a>
-// HTML-RECTANGLE: </p>+// HTML-RECTANGLE-NEXT: </p>
-// HTML-RECTANGLE: <h2 id="Members">Members</h2>+// HTML-RECTANGLE: <p> Represents a rectangle with a given width and height.</p>
-// HTML-RECTANGLE: <p> Width of the rectangle.</p>+// HTML-RECTANGLE: <p>
-// HTML-RECTANGLE: <div>private double width_</div>+// HTML-RECTANGLE: Inherits from
-// HTML-RECTANGLE: <p> Height of the rectangle.</p>+// HTML-RECTANGLE: <a href="Shape.html">Shape</a>
-// HTML-RECTANGLE: <div>private double height_</div>+// HTML-RECTANGLE: </p>
-// HTML-RECTANGLE: <h2 id="Functions">Functions</h2>+// HTML-RECTANGLE: <h2 id="Members">Members</h2>
-// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">Rectangle</h3>+// HTML-RECTANGLE: <p> Width of the rectangle.</p>
-// HTML-RECTANGLE: <p>public void Rectangle(double width, double height)</p>+// HTML-RECTANGLE: <div>private double width_</div>
-// HTML-RECTANGLE: <p>Defined at line 3 of file {{.*}}Rectangle.cpp</p>+// HTML-RECTANGLE: <p> Height of the rectangle.</p>
-// HTML-RECTANGLE: <div>brief</div>+// HTML-RECTANGLE: <div>private double height_</div>
-// HTML-RECTANGLE: <p> Constructs a new Rectangle object.</p>+// HTML-RECTANGLE: <h2 id="Functions">Functions</h2>
-// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">area</h3>+// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">Rectangle</h3>
-// HTML-RECTANGLE: <p>public double area()</p>+// HTML-RECTANGLE: <p>public void Rectangle(double width, double height)</p>
-// HTML-RECTANGLE: <p>Defined at line 6 of file {{.*}}Rectangle.cpp</p>+// HTML-RECTANGLE: Defined at line
-// HTML-RECTANGLE: <div>brief</div>+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./src/Rectangle.cpp#3">3</a>
-// HTML-RECTANGLE: <p> Calculates the area of the rectangle.</p>+// HTML-RECTANGLE-NEXT: of file
-// HTML-RECTANGLE: <div>return</div>+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./src/Rectangle.cpp">Rectangle.cpp</a>
-// HTML-RECTANGLE: <p> double The area of the rectangle.</p>+// HTML-RECTANGLE: <div>brief</div>
-// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3>+// HTML-RECTANGLE: <p> Constructs a new Rectangle object.</p>
-// HTML-RECTANGLE: <p>public double perimeter()</p>+// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">area</h3>
-// HTML-RECTANGLE: <p>Defined at line 10 of file {{.*}}Rectangle.cpp</p>+// HTML-RECTANGLE: <p>public double area()</p>
-// HTML-RECTANGLE: <div>brief</div>+// HTML-RECTANGLE: Defined at line
-// HTML-RECTANGLE: <p> Calculates the perimeter of the rectangle.</p>+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./src/Rectangle.cpp#6">6</a>
-// HTML-RECTANGLE: <div>return</div>+// HTML-RECTANGLE-NEXT: of file
-// HTML-RECTANGLE: <p> double The perimeter of the rectangle.</p>+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./src/Rectangle.cpp">Rectangle.cpp</a>
+// HTML-RECTANGLE: <div>brief</div>
+// HTML-RECTANGLE: <p> Calculates the area of the rectangle.</p>
+// HTML-RECTANGLE: <div>return</div>
+// HTML-RECTANGLE: <p> double The area of the rectangle.</p>
+// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3>
+// HTML-RECTANGLE: <p>public double perimeter()</p>
+// HTML-RECTANGLE: Defined at line
+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./src/Rectangle.cpp#10">10</a>
+// HTML-RECTANGLE-NEXT: of file
+// HTML-RECTANGLE-NEXT: <a href="https://repository.com/./src/Rectangle.cpp">Rectangle.cpp</a>
+// HTML-RECTANGLE: <div>brief</div>
+// HTML-RECTANGLE: <p> Calculates the perimeter of the rectangle.</p>
+// HTML-RECTANGLE: <div>return</div>
+// HTML-RECTANGLE: <p> double The perimeter of the rectangle.</p>
-// HTML-CIRCLE: <h1>class Circle</h1>+// HTML-CIRCLE: <h1>class Circle</h1>
-// HTML-CIRCLE: <p>Defined at line 10 of file {{.*}}Circle.h</p>+// HTML-CIRCLE-NEXT: <p>
-// HTML-CIRCLE: <div>brief</div>+// HTML-CIRCLE-NEXT: Defined at line
-// HTML-CIRCLE: <p> Circle class derived from Shape.</p>+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./include/Circle.h#10">10</a>
-// HTML-CIRCLE: <p> Represents a circle with a given radius.</p>+// HTML-CIRCLE-NEXT: of file
-// HTML-CIRCLE: <p>+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./include/Circle.h">Circle.h</a>
-// HTML-CIRCLE: Inherits from+// HTML-CIRCLE-NEXT: </p>
-// HTML-CIRCLE: <a href="Shape.html">Shape</a>+// HTML-CIRCLE: <div>brief</div>
-// HTML-CIRCLE: </p>+// HTML-CIRCLE: <p> Circle class derived from Shape.</p>
-// HTML-CIRCLE: <h2 id="Members">Members</h2>+// HTML-CIRCLE: <p> Represents a circle with a given radius.</p>
-// HTML-CIRCLE: <p> Radius of the circle.</p>+// HTML-CIRCLE: <p>
-// HTML-CIRCLE: <div>private double radius_</div>+// HTML-CIRCLE: Inherits from
-// HTML-CIRCLE: <h2 id="Functions">Functions</h2>+// HTML-CIRCLE: <a href="Shape.html">Shape</a>
-// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">Circle</h3>+// HTML-CIRCLE: </p>
-// HTML-CIRCLE: <p>public void Circle(double radius)</p>+// HTML-CIRCLE: <h2 id="Members">Members</h2>
-// HTML-CIRCLE: <p>Defined at line 3 of file {{.*}}Circle.cpp</p>+// HTML-CIRCLE: <p> Radius of the circle.</p>
-// HTML-CIRCLE: <div>brief</div>+// HTML-CIRCLE: <div>private double radius_</div>
-// HTML-CIRCLE: <p> Constructs a new Circle object.</p>+// HTML-CIRCLE: <h2 id="Functions">Functions</h2>
-// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">area</h3>+// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">Circle</h3>
-// HTML-CIRCLE: <p>public double area()</p>+// HTML-CIRCLE: <p>public void Circle(double radius)</p>
-// HTML-CIRCLE: <p>Defined at line 5 of file {{.*}}Circle.cpp</p>+// HTML-CIRCLE: Defined at line
-// HTML-CIRCLE: <div>brief</div>+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./src/Circle.cpp#3">3</a>
-// HTML-CIRCLE: <p> Calculates the area of the circle.</p>+// HTML-CIRCLE-NEXT: of file
-// HTML-CIRCLE: <div>return</div>+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./src/Circle.cpp">Circle.cpp</a>
-// HTML-CIRCLE: <p> double The area of the circle.</p>+// HTML-CIRCLE: <div>brief</div>
-// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3>+// HTML-CIRCLE: <p> Constructs a new Circle object.</p>
-// HTML-CIRCLE: <p>public double perimeter()</p>+// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">area</h3>
-// HTML-CIRCLE: <p>Defined at line 9 of file {{.*}}Circle.cpp</p>+// HTML-CIRCLE: <p>public double area()</p>
-// HTML-CIRCLE: <div>brief</div>+// HTML-CIRCLE: Defined at line
-// HTML-CIRCLE: <p> Calculates the perimeter of the circle.</p>+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./src/Circle.cpp#5">5</a>
-// HTML-CIRCLE: <div>return</div>+// HTML-CIRCLE-NEXT: of file
-// HTML-CIRCLE: <p> double The perimeter of the circle.</p>+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./src/Circle.cpp">Circle.cpp</a>
+// HTML-CIRCLE: <div>brief</div>
+// HTML-CIRCLE: <p> Calculates the area of the circle.</p>
+// HTML-CIRCLE: <div>return</div>
+// HTML-CIRCLE: <p> double The area of the circle.</p>
+// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3>
+// HTML-CIRCLE: <p>public double perimeter()</p>
+// HTML-CIRCLE: Defined at line
+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./src/Circle.cpp#9">9</a>
+// HTML-CIRCLE-NEXT: of file
+// HTML-CIRCLE-NEXT: <a href="https://repository.com/./src/Circle.cpp">Circle.cpp</a>
+// HTML-CIRCLE: <div>brief</div>
+// HTML-CIRCLE: <p> Calculates the perimeter of the circle.</p>
+// HTML-CIRCLE: <div>return</div>
+// HTML-CIRCLE: <p> double The perimeter of the circle.</p>
// MD-CALC: # class Calculator // MD-CALC: # class Calculator
// MD-CALC: *Defined at .{{[\/]}}include{{[\/]}}Calculator.h#8* // MD-CALC: *Defined at .{{[\/]}}include{{[\/]}}Calculator.h#8*
@@ -286,4 +339,4 @@
// MD-ALL-FILES: ## [GlobalNamespace](GlobalNamespace{{[\/]}}index.md) // MD-ALL-FILES: ## [GlobalNamespace](GlobalNamespace{{[\/]}}index.md)
// MD-INDEX: # C/C++ Reference // MD-INDEX: # C/C++ Reference
-// MD-INDEX: * Namespace: [GlobalNamespace](GlobalNamespace)
clang-tools-extra/test/clang-tidy/checkers/bugprone/string-constructor.cpp
@@ -11,6 +11,7 @@ struct basic_string {
basic_string(const C*, unsigned int size); basic_string(const C*, unsigned int size);
basic_string(const C *, const A &allocator = A()); basic_string(const C *, const A &allocator = A());
basic_string(unsigned int size, C c); basic_string(unsigned int size, C c);
+ basic_string(const C*, unsigned int pos, unsigned int size);
}; };
typedef basic_string<char> string; typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring; typedef basic_string<wchar_t> wstring;
@@ -61,6 +62,21 @@ void Test() {
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructing string from nullptr is undefined behaviour // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructing string from nullptr is undefined behaviour
std::string q7 = 0; std::string q7 = 0;
// CHECK-MESSAGES: [[@LINE-1]]:20: warning: constructing string from nullptr is undefined behaviour // CHECK-MESSAGES: [[@LINE-1]]:20: warning: constructing string from nullptr is undefined behaviour
+
+ std::string r1("test", 1, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+ std::string r2("test", 0, -4);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as length parameter
+ std::string r3("test", -4, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: negative value used as position of the first character parameter
+ std::string r4("test", 0, 0x1000000);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+ std::string r5("test", 0, 5);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than string literal size
+ std::string r6("test", 3, 2);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than remaining string literal size
+ std::string r7("test", 4, 1);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: position of the first character parameter is bigger than string literal character range
} }
void TestView() { void TestView() {
@@ -82,6 +98,17 @@ void TestView() {
// CHECK-MESSAGES: [[@LINE-1]]:25: warning: constructing string from nullptr is undefined behaviour // CHECK-MESSAGES: [[@LINE-1]]:25: warning: constructing string from nullptr is undefined behaviour
} }
+void TestUnsignedArguments() {
+ std::string s0("test", 0u);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string
+ std::string s1(0x1000000ull, 'x');
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+ std::string s2("test", 3ull, 2u);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than remaining string literal size
+ std::string s3("test", 0u, 5ll);
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger than string literal size
+}
+
std::string StringFromZero() { std::string StringFromZero() {
return 0; return 0;
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: constructing string from nullptr is undefined behaviour // CHECK-MESSAGES: [[@LINE-1]]:10: warning: constructing string from nullptr is undefined behaviour
@@ -101,6 +128,9 @@ void Valid() {
std::string s3("test"); std::string s3("test");
std::string s4("test\000", 5); std::string s4("test\000", 5);
std::string s6("te" "st", 4); std::string s6("te" "st", 4);
+ std::string s7("test", 0, 4);
+ std::string s8("test", 3, 1);
+ std::string s9("te" "st", 1, 2);
std::string_view emptyv(); std::string_view emptyv();
std::string_view sv1("test", 4); std::string_view sv1("test", 4);
clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
@@ -1,4 +1,5 @@
// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26 // RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26
+// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26 -DTEST_MACRO
typedef __INT64_TYPE__ I64; typedef __INT64_TYPE__ I64;
@@ -91,6 +92,223 @@ int TestSimpleEquivalent(int X, int Y) {
return 0; return 0;
} }
+#ifndef TEST_MACRO
+#define VAL_1 2
+#define VAL_3 3
+#else
+#define VAL_1 3
+#define VAL_3 2
+#endif
+
+#define VAL_2 2
+
+#ifndef TEST_MACRO
+#define VAL_4 2 + 1
+#define VAL_6 3 + 1
+#else
+#define VAL_4 3 + 1
+#define VAL_6 2 + 1
+#endif
+
+#define VAL_5 2 + 1
+
+struct TestStruct
+{
+ int mA;
+ int mB;
+ int mC[10];
+};
+
+int TestDefineEquivalent() {
+
+ int int_val1 = 3;
+ int int_val2 = 4;
+ int int_val = 0;
+ const int cint_val2 = 4;
+
+ // Cases which should not be reported
+ if (VAL_1 != VAL_2) return 0;
+ if (VAL_3 != VAL_2) return 0;
+ if (VAL_1 == VAL_2) return 0;
+ if (VAL_3 == VAL_2) return 0;
+ if (VAL_1 >= VAL_2) return 0;
+ if (VAL_3 >= VAL_2) return 0;
+ if (VAL_1 <= VAL_2) return 0;
+ if (VAL_3 <= VAL_2) return 0;
+ if (VAL_1 < VAL_2) return 0;
+ if (VAL_3 < VAL_2) return 0;
+ if (VAL_1 > VAL_2) return 0;
+ if (VAL_3 > VAL_2) return 0;
+
+ if (VAL_4 != VAL_5) return 0;
+ if (VAL_6 != VAL_5) return 0;
+ if (VAL_6 == VAL_5) return 0;
+ if (VAL_4 >= VAL_5) return 0;
+ if (VAL_6 >= VAL_5) return 0;
+ if (VAL_4 <= VAL_5) return 0;
+ if (VAL_6 <= VAL_5) return 0;
+ if (VAL_4 > VAL_5) return 0;
+ if (VAL_6 > VAL_5) return 0;
+ if (VAL_4 < VAL_5) return 0;
+ if (VAL_6 < VAL_5) return 0;
+
+ if (VAL_1 != 2) return 0;
+ if (VAL_3 == 3) return 0;
+
+ if (VAL_1 >= VAL_1) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_2 <= VAL_2) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_3 > VAL_3) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_4 < VAL_4) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_6 == VAL_6) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+ if (VAL_5 != VAL_5) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: both sides of operator are equivalent
+
+ // Test prefixes
+ if (+VAL_6 == +VAL_6) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+ if (-VAL_6 == -VAL_6) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: both sides of operator are equivalent
+ if ((+VAL_6) == (+VAL_6)) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: both sides of operator are equivalent
+ if ((-VAL_6) == (-VAL_6)) return 2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: both sides of operator are equivalent
+
+ if (1 >= 1) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: both sides of operator are equivalent
+ if (0xFF <= 0xFF) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: both sides of operator are equivalent
+ if (042 > 042) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: both sides of operator are equivalent
+
+ int_val = (VAL_6 == VAL_6)?int_val1: int_val2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: both sides of operator are equivalent
+ int_val = (042 > 042)?int_val1: int_val2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: both sides of operator are equivalent
+
+
+ // Ternary operator cases which should not be reported
+ int_val = (VAL_4 == VAL_5)? int_val1: int_val2;
+ int_val = (VAL_3 != VAL_2)? int_val1: int_val2;
+ int_val = (VAL_6 != 10)? int_val1: int_val2;
+ int_val = (VAL_6 != 3)? int_val1: int_val2;
+ int_val = (VAL_6 != 4)? int_val1: int_val2;
+ int_val = (VAL_6 == 3)? int_val1: int_val2;
+ int_val = (VAL_6 == 4)? int_val1: int_val2;
+
+ TestStruct tsVar1 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... VAL_2 - 2] = int_val + 1,
+ };
+
+ TestStruct tsVar2 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... cint_val2 - 2] = int_val + 1,
+ };
+
+ TestStruct tsVar3 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... VAL_3 - VAL_3] = int_val + 1,
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: both sides of operator are equivalent
+ };
+
+ TestStruct tsVar4 = {
+ .mA = 3,
+ .mB = int_val,
+ .mC[0 ... 5 - 5] = int_val + 1,
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: both sides of operator are equivalent
+ };
+
+ return 1 + int_val + sizeof(tsVar1) + sizeof(tsVar2) +
+ sizeof(tsVar3) + sizeof(tsVar4);
+}
+
+#define LOOP_DEFINE 1
+
+unsigned int testLoops(const unsigned int arr1[LOOP_DEFINE])
+{
+ unsigned int localIndex;
+ for (localIndex = LOOP_DEFINE - 1; localIndex > 0; localIndex--)
+ {
+ }
+ for (localIndex = LOOP_DEFINE - 1; 10 > 10; localIndex--)
+ // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: both sides of operator are equivalent
+ {
+ }
+
+ for (localIndex = LOOP_DEFINE - 1; LOOP_DEFINE > LOOP_DEFINE; localIndex--)
+ // CHECK-MESSAGES: :[[@LINE-1]]:50: warning: both sides of operator are equivalent
+ {
+ }
+
+ return localIndex;
+}
+
+#define getValue(a) a
+#define getValueM(a) a
+
+int TestParamDefine() {
+ int ret = 0;
+
+ // Negative cases
+ ret += getValue(VAL_6) == getValue(2);
+ ret += getValue(VAL_6) == getValue(3);
+ ret += getValue(VAL_5) == getValue(2);
+ ret += getValue(VAL_5) == getValue(3);
+ ret += getValue(1) > getValue( 2);
+ ret += getValue(VAL_1) == getValue(VAL_2);
+ ret += getValue(VAL_1) != getValue(VAL_2);
+ ret += getValue(VAL_1) == getValueM(VAL_1);
+ ret += getValue(VAL_1 + VAL_2) == getValueM(VAL_1 + VAL_2);
+ ret += getValue(1) == getValueM(1);
+ ret += getValue(false) == getValueM(false);
+ ret += -getValue(1) > +getValue( 1);
+
+ // Positive cases
+ ret += (+getValue(1)) > (+getValue( 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent
+ ret += (-getValue(1)) > (-getValue( 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent
+
+ ret += +getValue(1) > +getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
+ ret += -getValue(1) > -getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: both sides of operator are equivalent
+
+ ret += getValue(1) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent
+ ret += getValue(1) > getValue( 1 );
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent
+ ret += getValue(1) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: both sides of operator are equivalent
+ ret += getValue( 1) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: both sides of operator are equivalent
+ ret += getValue( 1 ) > getValue( 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: both sides of operator are equivalent
+ ret += getValue( VAL_5 ) > getValue(VAL_5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue( VAL_5 ) > getValue( VAL_5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue( VAL_5 ) > getValue( VAL_5 ) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue(VAL_5) > getValue( VAL_5 ) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: both sides of operator are equivalent
+ ret += getValue(VAL_1+VAL_2) > getValue(VAL_1 + VAL_2) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: both sides of operator are equivalent
+ ret += getValue(VAL_1)+getValue(VAL_2) > getValue(VAL_1) + getValue( VAL_2) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: both sides of operator are equivalent
+ ret += (getValue(VAL_1)+getValue(VAL_2)) > (getValue(VAL_1) + getValue( VAL_2) ) ;
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: both sides of operator are equivalent
+ return ret;
+}
+
template <int DX> template <int DX>
int TestSimpleEquivalentDependent() { int TestSimpleEquivalentDependent() {
if (DX > 0 && DX > 0) return 1; if (DX > 0 && DX > 0) return 1;
clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
@@ -319,7 +319,12 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) {
<a href="path/to/int.html">int</a> <a href="path/to/int.html">int</a>
P) P)
</p> </p>
- <p>Defined at line 10 of file dir/test.cpp</p>+ <p>
+ Defined at line
+ <a href="https://www.repository.com/dir/test.cpp#10">10</a>
+ of file
+ <a href="https://www.repository.com/dir/test.cpp">test.cpp</a>
+ </p>
</div> </div>
<div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div> <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
</main> </main>
clang/cmake/caches/Fuchsia-stage2.cmake
@@ -190,8 +190,8 @@ foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unkn
set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "") set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
# Enable FatLTO for Linux and baremetal runtimes # Enable FatLTO for Linux and baremetal runtimes
- set(RUNTIMES_${target}_LLVM_ENABLE_LTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
- set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
# Use .build-id link. # Use .build-id link.
list(APPEND RUNTIME_BUILD_ID_LINK "${target}") list(APPEND RUNTIME_BUILD_ID_LINK "${target}")
@@ -276,8 +276,8 @@ if(FUCHSIA_SDK)
set(RUNTIMES_${target}+asan+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") set(RUNTIMES_${target}+asan+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
# Enable FatLTO for Fuchsia runtimes # Enable FatLTO for Fuchsia runtimes
- set(RUNTIMES_${target}_LLVM_ENABLE_LTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
- set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
# Use .build-id link. # Use .build-id link.
list(APPEND RUNTIME_BUILD_ID_LINK "${target}") list(APPEND RUNTIME_BUILD_ID_LINK "${target}")
@@ -378,8 +378,8 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv7em-none-eabi;armv8m.main-n
set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc;libcxx" CACHE STRING "") set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc;libcxx" CACHE STRING "")
# Enable FatLTO for baremetal runtimes # Enable FatLTO for baremetal runtimes
- set(RUNTIMES_${target}_LLVM_ENABLE_LTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
- set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
endforeach() endforeach()
foreach(target riscv32-unknown-elf) foreach(target riscv32-unknown-elf)
@@ -433,8 +433,8 @@ foreach(target riscv32-unknown-elf)
set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc;libcxx" CACHE STRING "") set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc;libcxx" CACHE STRING "")
# Enable FatLTO for baremetal runtimes # Enable FatLTO for baremetal runtimes
- set(RUNTIMES_${target}_LLVM_ENABLE_LTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_LTO OFF CACHE BOOL "")
- set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO ON CACHE BOOL "")+ set(RUNTIMES_${target}_LLVM_ENABLE_FATLTO OFF CACHE BOOL "")
endforeach() endforeach()
set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "") set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "")
clang/docs/BoundsSafety.rst
@@ -777,13 +777,13 @@ the transformed pseudo code of function ``alloc_buf()`` in the example below.
size_t count; size_t count;
} sized_buf_t; } sized_buf_t;
- void alloc_buf(sized_buf_t *sbuf, sized_t nelems) {+ void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
sbuf->buf = (int *)malloc(sizeof(int) * nelems); sbuf->buf = (int *)malloc(sizeof(int) * nelems);
sbuf->count = nelems; sbuf->count = nelems;
} }
// Transformed pseudo code: // Transformed pseudo code:
- void alloc_buf(sized_buf_t *sbuf, sized_t nelems) {+ void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
// Materialize RHS values: // Materialize RHS values:
int *tmp_ptr = (int *)malloc(sizeof(int) * nelems); int *tmp_ptr = (int *)malloc(sizeof(int) * nelems);
int tmp_count = nelems; int tmp_count = nelems;
@@ -959,7 +959,8 @@ that has the define.
#if defined(__has_feature) && __has_feature(bounds_safety) #if defined(__has_feature) && __has_feature(bounds_safety)
#define __counted_by(T) __attribute__((__counted_by__(T))) #define __counted_by(T) __attribute__((__counted_by__(T)))
// ... other bounds annotations // ... other bounds annotations
- #else #define __counted_by(T) // defined as nothing+ #else
+ #define __counted_by(T) // defined as nothing
// ... other bounds annotations // ... other bounds annotations
#endif #endif
@@ -987,7 +988,7 @@ and it does not guarantee other types of memory safety properties. Consequently,
it may not prevent some of the secondary bounds safety violations caused by it may not prevent some of the secondary bounds safety violations caused by
other types of safety violations such as type confusion. For instance, other types of safety violations such as type confusion. For instance,
``-fbounds-safety`` does not perform type-safety checks on conversions between ``-fbounds-safety`` does not perform type-safety checks on conversions between
-`__single`` pointers of different pointee types (e.g., ``char *__single`` →+``__single`` pointers of different pointee types (e.g., ``char *__single`` →
``void *__single`` → ``int *__single``) beyond what the foundation languages ``void *__single`` → ``int *__single``) beyond what the foundation languages
(C/C++) already offer. (C/C++) already offer.
@@ -1003,4 +1004,4 @@ Try it out
Your feedback on the programming model is valuable. You may want to follow the Your feedback on the programming model is valuable. You may want to follow the
instruction in :doc:`BoundsSafetyAdoptionGuide` to play with ``-fbounds-safety`` instruction in :doc:`BoundsSafetyAdoptionGuide` to play with ``-fbounds-safety``
-and please send your feedback to `Yeoul Na <mailto:yeoul_na@apple.com>`_.
clang/docs/BoundsSafetyImplPlans.rst
@@ -134,7 +134,7 @@ same basic block and without side effect in between.
int *__counted_by(count) buf; size_t count; int *__counted_by(count) buf; size_t count;
} sized_buf_t; } sized_buf_t;
- void alloc_buf(sized_buf_t *sbuf, sized_t nelems) {+ void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
sbuf->buf = (int *)malloc(sizeof(int) * nelems); sbuf->buf = (int *)malloc(sizeof(int) * nelems);
sbuf->count = nelems; sbuf->count = nelems;
} }
clang/docs/ClangFormatStyleOptions.rst
@@ -2182,6 +2182,24 @@ the configuration (without a prefix: ``Auto``).
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
} }
+.. _BinPackLongBracedList:
+
+**BinPackLongBracedList** (``Boolean``) :versionbadge:`clang-format 21` :ref:`¶ <BinPackLongBracedList>`
+ If ``BinPackLongBracedList`` is ``true`` it overrides
+ ``BinPackArguments`` if there are 20 or more items in a braced
+ initializer list.
+
+ .. code-block:: c++
+
+ BinPackLongBracedList: false vs. BinPackLongBracedList: true
+ vector<int> x{ vector<int> x{1, 2, ...,
+ 20, 21};
+ 1,
+ 2,
+ ...,
+ 20,
+ 21};
+
.. _BinPackParameters: .. _BinPackParameters:
**BinPackParameters** (``BinPackParametersStyle``) :versionbadge:`clang-format 3.7` :ref:`¶ <BinPackParameters>` **BinPackParameters** (``BinPackParametersStyle``) :versionbadge:`clang-format 3.7` :ref:`¶ <BinPackParameters>`
@@ -3421,6 +3439,35 @@ the configuration (without a prefix: ``Auto``).
+.. _BreakBeforeTemplateCloser:
+
+**BreakBeforeTemplateCloser** (``Boolean``) :versionbadge:`clang-format 21` :ref:`¶ <BreakBeforeTemplateCloser>`
+ If ``true``, break before a template closing bracket (``>``) when there is
+ a line break after the matching opening bracket (``<``).
+
+ .. code-block:: c++
+
+ true:
+ template <typename Foo, typename Bar>
+
+ template <typename Foo,
+ typename Bar>
+
+ template <
+ typename Foo,
+ typename Bar
+ >
+
+ false:
+ template <typename Foo, typename Bar>
+
+ template <typename Foo,
+ typename Bar>
+
+ template <
+ typename Foo,
+ typename Bar>
+
.. _BreakBeforeTernaryOperators: .. _BreakBeforeTernaryOperators:
**BreakBeforeTernaryOperators** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <BreakBeforeTernaryOperators>` **BreakBeforeTernaryOperators** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <BreakBeforeTernaryOperators>`
clang/docs/ControlFlowIntegrity.rst
@@ -336,6 +336,15 @@ cross-DSO function address equality. These properties make KCFI easier to
adopt in low-level software. KCFI is limited to checking only function adopt in low-level software. KCFI is limited to checking only function
pointers, and isn't compatible with executable-only memory. pointers, and isn't compatible with executable-only memory.
+``-fsanitize-kcfi-arity``
+-----------------------------
+
+For supported targets, this feature extends kCFI by telling the compiler to
+record information about each indirect-callable function's arity (i.e., the
+number of arguments passed in registers) into the binary. Some kernel CFI
+techniques, such as FineIBT, may be able to use this information to provide
+enhanced security.
+
Member Function Pointer Call Checking Member Function Pointer Call Checking
===================================== =====================================
clang/docs/LanguageExtensions.rst
@@ -1803,10 +1803,6 @@ The following type trait primitives are supported by Clang. Those traits marked
* ``__is_pointer_interconvertible_base_of`` (C++, GNU, Microsoft) * ``__is_pointer_interconvertible_base_of`` (C++, GNU, Microsoft)
* ``__is_polymorphic`` (C++, GNU, Microsoft, Embarcadero) * ``__is_polymorphic`` (C++, GNU, Microsoft, Embarcadero)
* ``__is_reference`` (C++, Embarcadero) * ``__is_reference`` (C++, Embarcadero)
-* ``__is_referenceable`` (C++, GNU, Microsoft, Embarcadero):
- Returns true if a type is referenceable, and false otherwise. A referenceable
- type is a type that's either an object type, a reference type, or an unqualified
- function type. This trait is deprecated and will be removed in Clang 21.
* ``__is_rvalue_reference`` (C++, Embarcadero) * ``__is_rvalue_reference`` (C++, Embarcadero)
* ``__is_same`` (C++, Embarcadero) * ``__is_same`` (C++, Embarcadero)
* ``__is_same_as`` (GCC): Synonym for ``__is_same``. * ``__is_same_as`` (GCC): Synonym for ``__is_same``.
clang/docs/OpenMPSupport.rst
@@ -364,6 +364,8 @@ implementation.
+=============================================================+===========================+===========================+==========================================================================+ +=============================================================+===========================+===========================+==========================================================================+
| free-agent threads | :none:`unclaimed` | :none:`unclaimed` | | | free-agent threads | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| threadset clause | :`worked on` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Recording of task graphs | :none:`unclaimed` | :none:`unclaimed` | | | Recording of task graphs | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Parallel inductions | :none:`unclaimed` | :none:`unclaimed` | | | Parallel inductions | :none:`unclaimed` | :none:`unclaimed` | |
@@ -410,13 +412,13 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Extensions to interop construct | :none:`unclaimed` | :none:`unclaimed` | | | Extensions to interop construct | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| no_openmp_constructs | :none:`unclaimed` | :none:`unclaimed` | |+| no_openmp_constructs | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125933 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| safe_sync and progress with identifier and API | :none:`unclaimed` | :none:`unclaimed` | | | safe_sync and progress with identifier and API | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| OpenMP directives in concurrent loop regions | :none:`unclaimed` | :none:`unclaimed` | |+| OpenMP directives in concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| atomics constructs on concurrent loop regions | :none:`unclaimed` | :none:`unclaimed` | |+| atomics constructs on concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Loop construct with DO CONCURRENT | :none:`unclaimed` | :none:`unclaimed` | | | Loop construct with DO CONCURRENT | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
@@ -454,9 +456,7 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| map-type modifiers in arbitrary position | :none:`unclaimed` | :none:`unclaimed` | | | map-type modifiers in arbitrary position | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| atomic constructs in loop region | :none:`unclaimed` | :none:`unclaimed` | |+| Lift nesting restriction on concurrent loop | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
-+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| Lift nesting restriction on concurrent loop | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| priority clause for target constructs | :none:`unclaimed` | :none:`unclaimed` | | | priority clause for target constructs | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
clang/docs/ReleaseNotes.rst
@@ -42,9 +42,15 @@ C/C++ Language Potentially Breaking Changes
C++ Specific Potentially Breaking Changes C++ Specific Potentially Breaking Changes
----------------------------------------- -----------------------------------------
+- The type trait builtin ``__is_referenceable`` has been removed, since it has
+ very few users and all the type traits that could benefit from it in the
+ standard library already have their own bespoke builtins.
+
ABI Changes in This Version ABI Changes in This Version
--------------------------- ---------------------------
+- Return larger CXX records in memory instead of using AVX registers. Code compiled with older clang will be incompatible with newer version of the clang unless -fclang-abi-compat=20 is provided. (#GH120670)
+
AST Dumping Potentially Breaking Changes AST Dumping Potentially Breaking Changes
---------------------------------------- ----------------------------------------
@@ -98,6 +104,10 @@ Non-comprehensive list of changes in this release
New Compiler Flags New Compiler Flags
------------------ ------------------
+- New option ``-fprofile-continuous`` added to enable continuous profile syncing to file (#GH124353, `docs <https://clang.llvm.org/docs/UsersManual.html#cmdoption-fprofile-continuous>`_).
+ The feature has `existed <https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program>`_)
+ for a while and this is just a user facing option.
+
Deprecated Compiler Flags Deprecated Compiler Flags
------------------------- -------------------------
@@ -110,9 +120,22 @@ Removed Compiler Flags
Attribute Changes in Clang Attribute Changes in Clang
-------------------------- --------------------------
+- The ``no_sanitize`` attribute now accepts both ``gnu`` and ``clang`` names.
+- Clang now diagnoses use of declaration attributes on void parameters. (#GH108819)
+
Improvements to Clang's diagnostics Improvements to Clang's diagnostics
----------------------------------- -----------------------------------
+- Improve the diagnostics for deleted default constructor errors for C++ class
+ initializer lists that don't explicitly list a class member and thus attempt
+ to implicitly default construct that member.
+- The ``-Wunique-object-duplication`` warning has been added to warn about objects
+ which are supposed to only exist once per program, but may get duplicated when
+ built into a shared library.
+- Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
+- A statement attribute applied to a ``case`` label no longer suppresses
+ 'bypassing variable initialization' diagnostics (#84072).
+
Improvements to Clang's time-trace Improvements to Clang's time-trace
---------------------------------- ----------------------------------
@@ -129,16 +152,23 @@ Bug Fixes to Compiler Builtins
Bug Fixes to Attribute Support Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ - Fixed crash when a parameter to the ``clang::annotate`` attribute evaluates to ``void``. See #GH119125
Bug Fixes to C++ Support Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
+- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
+- The initialization kind of elements of structured bindings
+ direct-list-initialized from an array is corrected to direct-initialization.
+
Bug Fixes to AST Handling Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
Miscellaneous Bug Fixes Miscellaneous Bug Fixes
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
+- HTML tags in comments that span multiple lines are now parsed correctly by Clang's comment parser. (#GH120843)
+
Miscellaneous Clang Crashes Fixed Miscellaneous Clang Crashes Fixed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,6 +184,11 @@ AMDGPU Support
NVPTX Support NVPTX Support
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
+Hexagon Support
+^^^^^^^^^^^^^^^
+
+- The default compilation target has been changed from V60 to V68.
+
X86 Support X86 Support
^^^^^^^^^^^ ^^^^^^^^^^^
@@ -210,6 +245,10 @@ AST Matchers
clang-format clang-format
------------ ------------
+- Adds ``BreakBeforeTemplateCloser`` option.
+- Adds ``BinPackLongBracedList`` option to override bin packing options in
+ long (20 item or more) braced list initializer lists.
+
libclang libclang
-------- --------
@@ -219,13 +258,14 @@ Code Completion
Static Analyzer Static Analyzer
--------------- ---------------
-- Clang currently support extending lifetime of object bound to
- reference members of aggregates in CFG and ExprEngine, that are
- created from default member initializer.
-
New features New features
^^^^^^^^^^^^ ^^^^^^^^^^^^
+A new flag - `-static-libclosure` was introduced to support statically linking
+the runtime for the Blocks extension on Windows. This flag currently only
+changes the code generation, and even then, only on Windows. This does not
+impact the linker behaviour like the other `-static-*` flags.
+
Crash and bug fixes Crash and bug fixes
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
@@ -235,6 +275,11 @@ Improvements
Moved checkers Moved checkers
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
+- After lots of improvements, the checker ``alpha.security.ArrayBoundV2`` is
+ renamed to ``security.ArrayBound``. As this checker is stable now, the old
+ checker ``alpha.security.ArrayBound`` (which was searching for the same kind
+ of bugs with an different, simpler and less accurate algorithm) is removed.
+
.. _release-notes-sanitizers: .. _release-notes-sanitizers:
Sanitizers Sanitizers
@@ -245,6 +290,7 @@ Python Binding Changes
OpenMP Support OpenMP Support
-------------- --------------
+- Added support 'no_openmp_constructs' assumption clause.
Improvements Improvements
^^^^^^^^^^^^ ^^^^^^^^^^^^
clang/docs/SourceBasedCodeCoverage.rst
@@ -94,6 +94,11 @@ directory structure will be created. Additionally, the following special
not specified (i.e the pattern is "%m"), it's assumed that ``N = 1``. The not specified (i.e the pattern is "%m"), it's assumed that ``N = 1``. The
merge pool specifier can only occur once per filename pattern. merge pool specifier can only occur once per filename pattern.
+* "%b" expands out to the binary ID (build ID). It can be used with "%Nm" to
+ avoid binary signature collisions. To use it, the program should be compiled
+ with the build ID linker option (``--build-id`` for GNU ld or LLD,
+ ``/build-id`` for lld-link on Windows). Linux, Windows and AIX are supported.
+
* "%c" expands out to nothing, but enables a mode in which profile counter * "%c" expands out to nothing, but enables a mode in which profile counter
updates are continuously synced to a file. This means that if the updates are continuously synced to a file. This means that if the
instrumented program crashes, or is killed by a signal, perfect coverage instrumented program crashes, or is killed by a signal, perfect coverage
clang/docs/TypeSanitizer.rst
@@ -27,7 +27,7 @@ reduce these impacts.
The TypeSanitizer Algorithm The TypeSanitizer Algorithm
=========================== ===========================
For each TBAA type-access descriptor, encoded in LLVM IR using TBAA Metadata, the instrumentation For each TBAA type-access descriptor, encoded in LLVM IR using TBAA Metadata, the instrumentation
-pass generates descriptor tales. Thus there is a unique pointer to each type (and access descriptor).+pass generates descriptor tables. Thus there is a unique pointer to each type (and access descriptor).
These tables are comdat (except for anonymous-namespace types), so the pointer values are unique These tables are comdat (except for anonymous-namespace types), so the pointer values are unique
across the program. across the program.
clang/docs/UsersManual.rst
@@ -2223,6 +2223,12 @@ are listed below.
This option is currently experimental. This option is currently experimental.
+.. option:: -fsanitize-kcfi-arity
+
+ Extends kernel indirect call forward-edge control flow integrity with
+ additional function arity information (for supported targets). See
+ :doc:`ControlFlowIntegrity` for more details.
+
.. option:: -fstrict-vtable-pointers .. option:: -fstrict-vtable-pointers
Enable optimizations based on the strict rules for overwriting polymorphic Enable optimizations based on the strict rules for overwriting polymorphic
@@ -2959,7 +2965,8 @@ instrumentation:
environment variable to specify an alternate file. If non-default file name environment variable to specify an alternate file. If non-default file name
is specified by both the environment variable and the command line option, is specified by both the environment variable and the command line option,
the environment variable takes precedence. The file name pattern specified the environment variable takes precedence. The file name pattern specified
- can include different modifiers: ``%p``, ``%h``, ``%m``, ``%t``, and ``%c``.+ can include different modifiers: ``%p``, ``%h``, ``%m``, ``%b``, ``%t``, and
+ ``%c``.
Any instance of ``%p`` in that file name will be replaced by the process Any instance of ``%p`` in that file name will be replaced by the process
ID, so that you can easily distinguish the profile output from multiple ID, so that you can easily distinguish the profile output from multiple
@@ -2981,11 +2988,11 @@ instrumentation:
``%p`` is that the storage requirement for raw profile data files is greatly ``%p`` is that the storage requirement for raw profile data files is greatly
increased. To avoid issues like this, the ``%m`` specifier can used in the profile increased. To avoid issues like this, the ``%m`` specifier can used in the profile
name. When this specifier is used, the profiler runtime will substitute ``%m`` name. When this specifier is used, the profiler runtime will substitute ``%m``
- with a unique integer identifier associated with the instrumented binary. Additionally,+ with an integer identifier associated with the instrumented binary. Additionally,
multiple raw profiles dumped from different processes that share a file system (can be multiple raw profiles dumped from different processes that share a file system (can be
on different hosts) will be automatically merged by the profiler runtime during the on different hosts) will be automatically merged by the profiler runtime during the
dumping. If the program links in multiple instrumented shared libraries, each library dumping. If the program links in multiple instrumented shared libraries, each library
- will dump the profile data into its own profile data file (with its unique integer+ will dump the profile data into its own profile data file (with its integer
id embedded in the profile name). Note that the merging enabled by ``%m`` is for raw id embedded in the profile name). Note that the merging enabled by ``%m`` is for raw
profile data generated by profiler runtime. The resulting merged "raw" profile data profile data generated by profiler runtime. The resulting merged "raw" profile data
file still needs to be converted to a different format expected by the compiler ( file still needs to be converted to a different format expected by the compiler (
@@ -2995,6 +3002,12 @@ instrumentation:
$ LLVM_PROFILE_FILE="code-%m.profraw" ./code $ LLVM_PROFILE_FILE="code-%m.profraw" ./code
+ Although rare, binary signatures used by the ``%m`` specifier can have
+ collisions. In this case, the ``%b`` specifier, which expands to the binary
+ ID (build ID in ELF and COFF), can be added. To use it, the program should be
+ compiled with the build ID linker option (``--build-id`` for GNU ld or LLD,
+ ``/build-id`` for lld-link on Windows). Linux, Windows and AIX are supported.
+
See `this <SourceBasedCodeCoverage.html#running-the-instrumented-program>`_ section See `this <SourceBasedCodeCoverage.html#running-the-instrumented-program>`_ section
about the ``%t``, and ``%c`` modifiers. about the ``%t``, and ``%c`` modifiers.
@@ -3112,6 +3125,24 @@ indexed format, regardeless whether it is produced by frontend or the IR pass.
overhead. ``prefer-atomic`` will be transformed to ``atomic`` when supported overhead. ``prefer-atomic`` will be transformed to ``atomic`` when supported
by the target, or ``single`` otherwise. by the target, or ``single`` otherwise.
+.. option:: -fprofile-continuous
+
+ Enables the continuous instrumentation profiling where profile counter updates
+ are continuously synced to a file. This option sets any neccessary modifiers
+ (currently ``%c``) in the default profile filename and passes any necessary
+ flags to the middle-end to support this mode. Value profiling is not supported
+ in continuous mode.
+
+ .. code-block:: console
+
+ $ clang++ -O2 -fprofile-generate -fprofile-continuous code.cc -o code
+
+ Running ``./code`` will collect the profile and write it to the
+ ``default_xxxx.profraw`` file. However, if ``./code`` abruptly terminates or
+ does not call ``exit()``, in continuous mode the profile collected up to the
+ point of termination will be available in ``default_xxxx.profraw`` while in
+ the non-continuous mode, no profile file is generated.
+
.. option:: -ftemporal-profile .. option:: -ftemporal-profile
Enables the temporal profiling extension for IRPGO to improve startup time by Enables the temporal profiling extension for IRPGO to improve startup time by
clang/docs/analyzer/checkers.rst
@@ -1332,10 +1332,69 @@ security
Security related checkers. Security related checkers.
+.. _security-ArrayBound:
+
+security.ArrayBound (C, C++)
+""""""""""""""""""""""""""""
+Report out of bounds access to memory that is before the start or after the end
+of the accessed region (array, heap-allocated region, string literal etc.).
+This usually means incorrect indexing, but the checker also detects access via
+the operators ``*`` and ``->``.
+
+.. code-block:: c
+
+ void test_underflow(int x) {
+ int buf[100][100];
+ if (x < 0)
+ buf[0][x] = 1; // warn
+ }
+
+ void test_overflow() {
+ int buf[100];
+ int *p = buf + 100;
+ *p = 1; // warn
+ }
+
+If checkers like :ref:`unix-Malloc` or :ref:`cplusplus-NewDelete` are enabled
+to model the behavior of ``malloc()``, ``operator new`` and similar
+allocators), then this checker can also reports out of bounds access to
+dynamically allocated memory:
+
+.. code-block:: cpp
+
+ int *test_dynamic() {
+ int *mem = new int[100];
+ mem[-1] = 42; // warn
+ return mem;
+ }
+
+In uncertain situations (when the checker can neither prove nor disprove that
+overflow occurs), the checker assumes that the the index (more precisely, the
+memory offeset) is within bounds.
+
+However, if :ref:`optin-taint-GenericTaint` is enabled and the index/offset is
+tainted (i.e. it is influenced by an untrusted souce), then this checker
+reports the potential out of bounds access:
+
+.. code-block:: c
+
+ void test_with_tainted_index() {
+ char s[] = "abc";
+ int x = getchar();
+ char c = s[x]; // warn: potential out of bounds access with tainted index
+ }
+
+.. note::
+
+ This checker is an improved and renamed version of the checker that was
+ previously known as ``alpha.security.ArrayBoundV2``. The old checker
+ ``alpha.security.ArrayBound`` was removed when the (previously
+ "experimental") V2 variant became stable enough for regular use.
+
.. _security-cert-env-InvalidPtr: .. _security-cert-env-InvalidPtr:
security.cert.env.InvalidPtr security.cert.env.InvalidPtr
-""""""""""""""""""""""""""""""""""+""""""""""""""""""""""""""""
Corresponds to SEI CERT Rules `ENV31-C <https://wiki.sei.cmu.edu/confluence/display/c/ENV31-C.+Do+not+rely+on+an+environment+pointer+following+an+operation+that+may+invalidate+it>`_ and `ENV34-C <https://wiki.sei.cmu.edu/confluence/display/c/ENV34-C.+Do+not+store+pointers+returned+by+certain+functions>`_. Corresponds to SEI CERT Rules `ENV31-C <https://wiki.sei.cmu.edu/confluence/display/c/ENV31-C.+Do+not+rely+on+an+environment+pointer+following+an+operation+that+may+invalidate+it>`_ and `ENV34-C <https://wiki.sei.cmu.edu/confluence/display/c/ENV34-C.+Do+not+store+pointers+returned+by+certain+functions>`_.
@@ -3216,78 +3275,6 @@ Warns against using one vs. many plural pattern in code when generating localize
alpha.security alpha.security
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
-.. _alpha-security-ArrayBound:
-
-alpha.security.ArrayBound (C)
-"""""""""""""""""""""""""""""
-Warn about buffer overflows (older checker).
-
-.. code-block:: c
-
- void test() {
- char *s = "";
- char c = s[1]; // warn
- }
-
- struct seven_words {
- int c[7];
- };
-
- void test() {
- struct seven_words a, *p;
- p = &a;
- p[0] = a;
- p[1] = a;
- p[2] = a; // warn
- }
-
- // note: requires unix.Malloc or
- // alpha.unix.MallocWithAnnotations checks enabled.
- void test() {
- int *p = malloc(12);
- p[3] = 4; // warn
- }
-
- void test() {
- char a[2];
- int *b = (int*)a;
- b[1] = 3; // warn
- }
-
-.. _alpha-security-ArrayBoundV2:
-
-alpha.security.ArrayBoundV2 (C)
-"""""""""""""""""""""""""""""""
-Warn about buffer overflows (newer checker).
-
-.. code-block:: c
-
- void test() {
- char *s = "";
- char c = s[1]; // warn
- }
-
- void test() {
- int buf[100];
- int *p = buf;
- p = p + 99;
- p[1] = 1; // warn
- }
-
- // note: compiler has internal check for this.
- // Use -Wno-array-bounds to suppress compiler warning.
- void test() {
- int buf[100][100];
- buf[0][-1] = 1; // warn
- }
-
- // note: requires optin.taint check turned on.
- void test() {
- char s[] = "abc";
- int x = getchar();
- char c = s[x]; // warn: index is tainted
- }
-
.. _alpha-security-ReturnPtrRange: .. _alpha-security-ReturnPtrRange:
alpha.security.ReturnPtrRange (C) alpha.security.ReturnPtrRange (C)
clang/docs/analyzer/developer-docs.rst
@@ -11,3 +11,4 @@ Contents:
developer-docs/InitializerLists developer-docs/InitializerLists
developer-docs/nullability developer-docs/nullability
developer-docs/RegionStore developer-docs/RegionStore
+ developer-docs/PerformanceInvestigation
clang/docs/analyzer/developer-docs/PerformanceInvestigation.rst
@@ -0,0 +1,137 @@
+=========================
+Performance Investigation
+=========================
+
+Multiple factors contribute to the time it takes to analyze a file with Clang Static Analyzer.
+A translation unit contains multiple entry points, each of which take multiple steps to analyze.
+
+Performance analysis using ``-ftime-trace``
+===========================================
+
+You can add the ``-ftime-trace=file.json`` option to break down the analysis time into individual entry points and steps within each entry point.
+You can explore the generated JSON file in a Chromium browser using the ``chrome://tracing`` URL,
+or using `speedscope <https://speedscope.app>`_.
+Once you narrow down to specific analysis steps you are interested in, you can more effectively employ heavier profilers,
+such as `Perf <https://perfwiki.github.io/main/>`_ and `Callgrind <https://valgrind.org/docs/manual/cl-manual.html>`_.
+
+Each analysis step has a time scope in the trace, corresponds to processing of an exploded node, and is designated with a ``ProgramPoint``.
+If the ``ProgramPoint`` is associated with a location, you can see it on the scope metadata label.
+
+Here is an example of a time trace produced with
+
+.. code-block:: bash
+ :caption: Clang Static Analyzer invocation to generate a time trace of string.c analysis.
+
+ clang -cc1 -analyze -verify clang/test/Analysis/string.c \
+ -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection \
+ -ftime-trace=trace.json -ftime-trace-granularity=1
+
+.. image:: ../images/speedscope.png
+
+On the speedscope screenshot above, under the first time ruler is the bird's-eye view of the entire trace that spans a little over 60 milliseconds.
+Under the second ruler (focused on the 18.09-18.13ms time point) you can see a narrowed-down portion.
+The second box ("HandleCode memset...") that spans entire screen (and actually extends beyond it) corresponds to the analysis of ``memset16_region_cast()`` entry point that is defined in the "string.c" test file on line 1627.
+Below it, you can find multiple sub-scopes each corresponding to processing of a single exploded node.
+
+- First: a ``PostStmt`` for some statement on line 1634. This scope has a selected subscope "CheckerManager::runCheckersForCallEvent (Pre)" that takes 5 microseconds.
+- Four other nodes, too small to be discernible at this zoom level
+- Last on this screenshot: another ``PostStmt`` for a statement on line 1635.
+
+In addition to the ``-ftime-trace`` option, you can use ``-ftime-trace-granularity`` to fine-tune the time trace.
+
+- ``-ftime-trace-granularity=NN`` dumps only time scopes that are longer than NN microseconds.
+- ``-ftime-trace-verbose`` enables some additional dumps in the frontend related to template instantiations.
+ At the moment, it has no effect on the traces from the static analyzer.
+
+Note: Both Chrome-tracing and speedscope tools might struggle with time traces above 100 MB in size.
+Luckily, in most cases the default max-steps boundary of 225 000 produces the traces of approximately that size
+for a single entry point.
+You can use ``-analyze-function=get_global_options`` together with ``-ftime-trace`` to narrow down analysis to a specific entry point.
+
+
+Performance analysis using ``perf``
+===================================
+
+`Perf <https://perfwiki.github.io/main/>`_ is a tool for conducting sampling-based profiling.
+It's easy to start profiling, you only have 2 prerequisites.
+Build with ``-fno-omit-frame-pointer`` and debug info (``-g``).
+You can use release builds, but probably the easiest is to set the ``CMAKE_BUILD_TYPE=RelWithDebInfo``
+along with ``CMAKE_CXX_FLAGS="-fno-omit-frame-pointer"`` when configuring ``llvm``.
+Here is how to `get started <https://llvm.org/docs/CMake.html#quick-start>`_ if you are in trouble.
+
+.. code-block:: bash
+ :caption: Running the Clang Static Analyzer through ``perf`` to gather samples of the execution.
+
+ # -F: Sampling frequency, use `-F max` for maximal frequency
+ # -g: Enable call-graph recording for both kernel and user space
+ perf record -F 99 -g -- clang -cc1 -analyze -verify clang/test/Analysis/string.c \
+ -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection
+
+Once you have the profile data, you can use it to produce a Flame graph.
+A Flame graph is a visual representation of the stack frames of the samples.
+Common stack frame prefixes are squashed together, making up a wider bar.
+The wider the bar, the more time was spent under that particular stack frame,
+giving a sense of how the overall execution time was spent.
+
+Clone the `FlameGraph <https://github.com/brendangregg/FlameGraph>`_ git repository,
+as we will use some scripts from there to convert the ``perf`` samples into a Flame graph.
+It's also useful to check out Brendan Gregg's (the author of FlameGraph)
+`homepage <https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html>`_.
+
+
+.. code-block:: bash
+ :caption: Converting the ``perf`` profile into a Flamegraph, then opening it in Firefox.
+
+ perf script | /path/to/FlameGraph/stackcollapse-perf.pl > perf.folded
+ /path/to/FlameGraph/flamegraph.pl perf.folded > perf.svg
+ firefox perf.svg
+
+.. image:: ../images/flamegraph.png
+
+
+Performance analysis using ``uftrace``
+======================================
+
+`uftrace <https://github.com/namhyung/uftrace/wiki/Tutorial#getting-started>`_ is a great tool to generate rich profile data
+that you can use to focus and drill down into the timeline of your application.
+We will use it to generate Chromium trace JSON.
+In contrast to ``perf``, this approach statically instruments every function, so it should be more precise and thorough than the sampling-based approaches like ``perf``.
+In contrast to using ``-ftime-trace``, functions don't need to opt-in to be profiled using ``llvm::TimeTraceScope``.
+All functions are profiled due to automatic static instrumentation.
+
+There is only one prerequisite to use this tool.
+You need to build the binary you are about to instrument using ``-pg`` or ``-finstrument-functions``.
+This will make it run substantially slower but allows rich instrumentation.
+It will also consume many gigabites of storage for a single trace unless filter flags are used during recording.
+
+.. code-block:: bash
+ :caption: Recording with ``uftrace``, then dumping the result as a Chrome trace JSON.
+
+ uftrace record clang -cc1 -analyze -verify clang/test/Analysis/string.c \
+ -analyzer-checker=core,unix,alpha.unix.cstring,debug.ExprInspection
+ uftrace dump --filter=".*::AnalysisConsumer::HandleTranslationUnit" --time-filter=300 --chrome > trace.json
+
+.. image:: ../images/uftrace_detailed.png
+
+In this picture, you can see the functions below the Static Analyzer's entry point, which takes at least 300 nanoseconds to run, visualized by Chrome's ``about:tracing`` page
+You can also see how deep function calls we may have due to AST visitors.
+
+Using different filters can reduce the number of functions to record.
+For the common options, refer to the ``uftrace`` `documentation <https://github.com/namhyung/uftrace/blob/master/doc/uftrace-record.md#common-options>`_.
+
+Similar filters can be applied for dumping too. That way you can reuse the same (detailed)
+recording to selectively focus on some special part using a refinement of the filter flags.
+Remember, the trace JSON needs to fit into Chrome's ``about:tracing`` or `speedscope <https://speedscope.app>`_,
+thus it needs to be of a limited size.
+If you do not apply filters on recording, you will collect a large trace and every dump operation
+would need to sieve through the much larger recording which may be annoying if done repeatedly.
+
+If the trace JSON is still too large to load, have a look at the dump as plain text and look for frequent entries that refer to non-interesting parts.
+Once you have some of those, add them as ``--hide`` flags to the ``uftrace dump`` call.
+To see what functions appear frequently in the trace, use this command:
+
+.. code-block:: bash
+
+ cat trace.json | grep -Po '"name":"(.+)"' | sort | uniq -c | sort -nr | head -n 50
+
+``uftrace`` can also dump the report as a Flame graph using ``uftrace dump --framegraph``.
clang/include/clang-c/Index.h
@@ -2206,7 +2206,11 @@ enum CXCursorKind {
*/ */
CXCursor_OpenACCUpdateConstruct = 331, CXCursor_OpenACCUpdateConstruct = 331,
- CXCursor_LastStmt = CXCursor_OpenACCUpdateConstruct,+ /** OpenACC atomic Construct.
+ */
+ CXCursor_OpenACCAtomicConstruct = 332,
+
+ CXCursor_LastStmt = CXCursor_OpenACCAtomicConstruct,
/** /**
* Cursor that represents the translation unit itself. * Cursor that represents the translation unit itself.
clang/include/clang/AST/ASTContext.h
@@ -1733,6 +1733,47 @@ public:
unsigned NumPositiveBits, QualType &BestType, unsigned NumPositiveBits, QualType &BestType,
QualType &BestPromotionType); QualType &BestPromotionType);
+ /// Determine whether the given integral value is representable within
+ /// the given type T.
+ bool isRepresentableIntegerValue(llvm::APSInt &Value, QualType T);
+
+ /// Compute NumNegativeBits and NumPositiveBits for an enum based on
+ /// the constant values of its enumerators.
+ template <typename RangeT>
+ bool computeEnumBits(RangeT EnumConstants, unsigned &NumNegativeBits,
+ unsigned &NumPositiveBits) {
+ NumNegativeBits = 0;
+ NumPositiveBits = 0;
+ bool MembersRepresentableByInt = true;
+ for (auto *Elem : EnumConstants) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elem);
+ if (!ECD)
+ continue; // Already issued a diagnostic.
+
+ llvm::APSInt InitVal = ECD->getInitVal();
+ if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
+ // If the enumerator is zero that should still be counted as a positive
+ // bit since we need a bit to store the value zero.
+ unsigned ActiveBits = InitVal.getActiveBits();
+ NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
+ } else {
+ NumNegativeBits =
+ std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
+ }
+
+ MembersRepresentableByInt &= isRepresentableIntegerValue(InitVal, IntTy);
+ }
+
+ // If we have an empty set of enumerators we still need one bit.
+ // From [dcl.enum]p8
+ // If the enumerator-list is empty, the values of the enumeration are as if
+ // the enumeration had a single enumerator with value 0
+ if (!NumPositiveBits && !NumNegativeBits)
+ NumPositiveBits = 1;
+
+ return MembersRepresentableByInt;
+ }
+
QualType QualType
getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const; getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const;
clang/include/clang/AST/Decl.h
@@ -2298,6 +2298,13 @@ public:
FunctionDeclBits.IsLateTemplateParsed = ILT; FunctionDeclBits.IsLateTemplateParsed = ILT;
} }
+ bool isInstantiatedFromMemberTemplate() const {
+ return FunctionDeclBits.IsInstantiatedFromMemberTemplate;
+ }
+ void setInstantiatedFromMemberTemplate(bool Val = true) {
+ FunctionDeclBits.IsInstantiatedFromMemberTemplate = Val;
+ }
+
/// Whether this function is "trivial" in some specialized C++ senses. /// Whether this function is "trivial" in some specialized C++ senses.
/// Can only be true for default constructors, copy constructors, /// Can only be true for default constructors, copy constructors,
/// copy assignment operators, and destructors. Not meaningful until /// copy assignment operators, and destructors. Not meaningful until
clang/include/clang/AST/DeclBase.h
@@ -1257,8 +1257,11 @@ public:
int64_t getID() const; int64_t getID() const;
/// Looks through the Decl's underlying type to extract a FunctionType /// Looks through the Decl's underlying type to extract a FunctionType
- /// when possible. Will return null if the type underlying the Decl does not+ /// when possible. This includes direct FunctionDecls, along with various
- /// have a FunctionType.+ /// function types and typedefs. This includes function pointers/references,
+ /// member function pointers, and optionally if \p BlocksToo is set
+ /// Objective-C block pointers. Returns nullptr if the type underlying the
+ /// Decl does not have a FunctionType.
const FunctionType *getFunctionType(bool BlocksToo = true) const; const FunctionType *getFunctionType(bool BlocksToo = true) const;
// Looks through the Decl's underlying type to determine if it's a // Looks through the Decl's underlying type to determine if it's a
@@ -1777,6 +1780,8 @@ protected:
uint64_t HasImplicitReturnZero : 1; uint64_t HasImplicitReturnZero : 1;
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
uint64_t IsLateTemplateParsed : 1; uint64_t IsLateTemplateParsed : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ uint64_t IsInstantiatedFromMemberTemplate : 1;
/// Kind of contexpr specifier as defined by ConstexprSpecKind. /// Kind of contexpr specifier as defined by ConstexprSpecKind.
LLVM_PREFERRED_TYPE(ConstexprSpecKind) LLVM_PREFERRED_TYPE(ConstexprSpecKind)
@@ -1827,7 +1832,7 @@ protected:
}; };
/// Number of inherited and non-inherited bits in FunctionDeclBitfields. /// Number of inherited and non-inherited bits in FunctionDeclBitfields.
- enum { NumFunctionDeclBits = NumDeclContextBits + 31 };+ enum { NumFunctionDeclBits = NumDeclContextBits + 32 };
/// Stores the bits used by CXXConstructorDecl. If modified /// Stores the bits used by CXXConstructorDecl. If modified
/// NumCXXConstructorDeclBits and the accessor /// NumCXXConstructorDeclBits and the accessor
@@ -1838,12 +1843,12 @@ protected:
LLVM_PREFERRED_TYPE(FunctionDeclBitfields) LLVM_PREFERRED_TYPE(FunctionDeclBitfields)
uint64_t : NumFunctionDeclBits; uint64_t : NumFunctionDeclBits;
- /// 20 bits to fit in the remaining available space.+ /// 19 bits to fit in the remaining available space.
/// Note that this makes CXXConstructorDeclBitfields take /// Note that this makes CXXConstructorDeclBitfields take
/// exactly 64 bits and thus the width of NumCtorInitializers /// exactly 64 bits and thus the width of NumCtorInitializers
/// will need to be shrunk if some bit is added to NumDeclContextBitfields, /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields. /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
- uint64_t NumCtorInitializers : 17;+ uint64_t NumCtorInitializers : 16;
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
uint64_t IsInheritingConstructor : 1; uint64_t IsInheritingConstructor : 1;
@@ -1857,7 +1862,7 @@ protected:
}; };
/// Number of inherited and non-inherited bits in CXXConstructorDeclBitfields. /// Number of inherited and non-inherited bits in CXXConstructorDeclBitfields.
- enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 20 };+ enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 19 };
/// Stores the bits used by ObjCMethodDecl. /// Stores the bits used by ObjCMethodDecl.
/// If modified NumObjCMethodDeclBits and the accessor /// If modified NumObjCMethodDeclBits and the accessor
clang/include/clang/AST/DeclTemplate.h
@@ -1011,6 +1011,26 @@ public:
return getTemplatedDecl()->isThisDeclarationADefinition(); return getTemplatedDecl()->isThisDeclarationADefinition();
} }
+ bool isCompatibleWithDefinition() const {
+ return getTemplatedDecl()->isInstantiatedFromMemberTemplate() ||
+ isThisDeclarationADefinition();
+ }
+
+ // This bit closely tracks 'RedeclarableTemplateDecl::InstantiatedFromMember',
+ // except this is per declaration, while the redeclarable field is
+ // per chain. This indicates a template redeclaration which
+ // is compatible with the definition, in the non-trivial case
+ // where this is not already a definition.
+ // This is only really needed for instantiating the definition of friend
+ // function templates, which can have redeclarations in different template
+ // contexts.
+ // The bit is actually stored in the FunctionDecl for space efficiency
+ // reasons.
+ void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *D) {
+ getTemplatedDecl()->setInstantiatedFromMemberTemplate();
+ RedeclarableTemplateDecl::setInstantiatedFromMemberTemplate(D);
+ }
+
/// Return the specialization with the provided arguments if it exists, /// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point. /// otherwise return the insertion point.
FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args, FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args,
@@ -1841,15 +1861,23 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
LLVM_PREFERRED_TYPE(TemplateSpecializationKind) LLVM_PREFERRED_TYPE(TemplateSpecializationKind)
unsigned SpecializationKind : 3; unsigned SpecializationKind : 3;
+ /// Indicate that we have matched a parameter pack with a non pack
+ /// argument, when the opposite match is also allowed.
+ /// This needs to be cached as deduction is performed during declaration,
+ /// and we need the information to be preserved so that it is consistent
+ /// during instantiation.
+ bool StrictPackMatch : 1;
+
protected: protected:
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
DeclContext *DC, SourceLocation StartLoc, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate, ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args, ArrayRef<TemplateArgument> Args,
+ bool StrictPackMatch,
ClassTemplateSpecializationDecl *PrevDecl); ClassTemplateSpecializationDecl *PrevDecl);
- explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);+ ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
public: public:
friend class ASTDeclReader; friend class ASTDeclReader;
@@ -1859,7 +1887,7 @@ public:
Create(ASTContext &Context, TagKind TK, DeclContext *DC, Create(ASTContext &Context, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc, SourceLocation StartLoc, SourceLocation IdLoc,
ClassTemplateDecl *SpecializedTemplate, ClassTemplateDecl *SpecializedTemplate,
- ArrayRef<TemplateArgument> Args,+ ArrayRef<TemplateArgument> Args, bool StrictPackMatch,
ClassTemplateSpecializationDecl *PrevDecl); ClassTemplateSpecializationDecl *PrevDecl);
static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID); GlobalDeclID ID);
@@ -1930,6 +1958,10 @@ public:
SpecializationKind = TSK; SpecializationKind = TSK;
} }
+ bool hasStrictPackMatch() const { return StrictPackMatch; }
+
+ void setStrictPackMatch(bool Val) { StrictPackMatch = Val; }
+
/// Get the point of instantiation (if any), or null if none. /// Get the point of instantiation (if any), or null if none.
SourceLocation getPointOfInstantiation() const { SourceLocation getPointOfInstantiation() const {
return PointOfInstantiation; return PointOfInstantiation;
clang/include/clang/AST/Expr.h
@@ -6678,7 +6678,6 @@ public:
class AtomicExpr : public Expr { class AtomicExpr : public Expr {
public: public:
enum AtomicOp { enum AtomicOp {
-#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID, #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID,
#include "clang/Basic/Builtins.inc" #include "clang/Basic/Builtins.inc"
// Avoid trailing comma // Avoid trailing comma
@@ -6742,7 +6741,6 @@ public:
AtomicOp getOp() const { return Op; } AtomicOp getOp() const { return Op; }
StringRef getOpAsString() const { StringRef getOpAsString() const {
switch (Op) { switch (Op) {
-#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
case AO##ID: \ case AO##ID: \
return #ID; return #ID;
clang/include/clang/AST/ExprCXX.h
@@ -5040,7 +5040,7 @@ public:
} }
const FieldDecl *getInitializedFieldInUnion() const { const FieldDecl *getInitializedFieldInUnion() const {
- return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();+ return dyn_cast_if_present<FieldDecl *>(ArrayFillerOrUnionFieldInit);
} }
child_range children() { child_range children() {
clang/include/clang/AST/OpenMPClause.h
@@ -2423,6 +2423,28 @@ public:
OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {} OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {}
}; };
+/// This represents the 'no_openmp_constructs' clause in the
+//// '#pragma omp assume' directive.
+///
+/// \code
+/// #pragma omp assume no_openmp_constructs
+/// \endcode
+/// In this example directive '#pragma omp assume' has a 'no_openmp_constructs'
+/// clause.
+class OMPNoOpenMPConstructsClause final
+ : public OMPNoChildClause<llvm::omp::OMPC_no_openmp_constructs> {
+public:
+ /// Build 'no_openmp_constructs' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPNoOpenMPConstructsClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPNoChildClause(StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPNoOpenMPConstructsClause() : OMPNoChildClause() {}
+};
+
/// This represents the 'no_parallelism' clause in the '#pragma omp assume' /// This represents the 'no_parallelism' clause in the '#pragma omp assume'
/// directive. /// directive.
/// ///
@@ -9451,7 +9473,8 @@ struct TargetOMPContext final : public llvm::omp::OMPContext {
TargetOMPContext(ASTContext &ASTCtx, TargetOMPContext(ASTContext &ASTCtx,
std::function<void(StringRef)> &&DiagUnknownTrait, std::function<void(StringRef)> &&DiagUnknownTrait,
const FunctionDecl *CurrentFunctionDecl, const FunctionDecl *CurrentFunctionDecl,
- ArrayRef<llvm::omp::TraitProperty> ConstructTraits);+ ArrayRef<llvm::omp::TraitProperty> ConstructTraits,
+ int DeviceNum);
virtual ~TargetOMPContext() = default; virtual ~TargetOMPContext() = default;
clang/include/clang/AST/OperationKinds.def
@@ -367,6 +367,9 @@ CAST_OPERATION(HLSLVectorTruncation)
// Non-decaying array RValue cast (HLSL only). // Non-decaying array RValue cast (HLSL only).
CAST_OPERATION(HLSLArrayRValue) CAST_OPERATION(HLSLArrayRValue)
+// Aggregate by Value cast (HLSL only).
+CAST_OPERATION(HLSLElementwiseCast)
+
//===- Binary Operations -------------------------------------------------===// //===- Binary Operations -------------------------------------------------===//
// Operators listed in order of precedence. // Operators listed in order of precedence.
// Note that additions to this should also update the StmtVisitor class, // Note that additions to this should also update the StmtVisitor class,
clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3544,6 +3544,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPRoutinesClause(
return true; return true;
} }
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPConstructsClause(
+ OMPNoOpenMPConstructsClause *) {
+ return true;
+}
+
template <typename Derived> template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPNoParallelismClause( bool RecursiveASTVisitor<Derived>::VisitOMPNoParallelismClause(
OMPNoParallelismClause *) { OMPNoParallelismClause *) {
@@ -4099,6 +4105,8 @@ DEF_TRAVERSE_STMT(OpenACCSetConstruct,
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); }) { TRY_TO(VisitOpenACCClauseList(S->clauses())); })
DEF_TRAVERSE_STMT(OpenACCUpdateConstruct, DEF_TRAVERSE_STMT(OpenACCUpdateConstruct,
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); }) { TRY_TO(VisitOpenACCClauseList(S->clauses())); })
+DEF_TRAVERSE_STMT(OpenACCAtomicConstruct,
+ { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
// Traverse HLSL: Out argument expression // Traverse HLSL: Out argument expression
DEF_TRAVERSE_STMT(HLSLOutArgExpr, {}) DEF_TRAVERSE_STMT(HLSLOutArgExpr, {})
clang/include/clang/AST/StmtOpenACC.h
@@ -751,5 +751,50 @@ public:
Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
}; };
+
+// This class represents the 'atomic' construct, which has an associated
+// statement, but no clauses.
+class OpenACCAtomicConstruct final : public OpenACCAssociatedStmtConstruct {
+
+ friend class ASTStmtReader;
+ OpenACCAtomicKind AtomicKind = OpenACCAtomicKind::None;
+
+ OpenACCAtomicConstruct(EmptyShell)
+ : OpenACCAssociatedStmtConstruct(
+ OpenACCAtomicConstructClass, OpenACCDirectiveKind::Atomic,
+ SourceLocation{}, SourceLocation{}, SourceLocation{},
+ /*AssociatedStmt=*/nullptr) {}
+
+ OpenACCAtomicConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
+ OpenACCAtomicKind AtKind, SourceLocation End,
+ Stmt *AssociatedStmt)
+ : OpenACCAssociatedStmtConstruct(OpenACCAtomicConstructClass,
+ OpenACCDirectiveKind::Atomic, Start,
+ DirectiveLoc, End, AssociatedStmt),
+ AtomicKind(AtKind) {}
+
+ void setAssociatedStmt(Stmt *S) {
+ OpenACCAssociatedStmtConstruct::setAssociatedStmt(S);
+ }
+
+public:
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OpenACCAtomicConstructClass;
+ }
+
+ static OpenACCAtomicConstruct *CreateEmpty(const ASTContext &C);
+ static OpenACCAtomicConstruct *
+ Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
+ OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt);
+
+ OpenACCAtomicKind getAtomicKind() const { return AtomicKind; }
+ const Stmt *getAssociatedStmt() const {
+ return OpenACCAssociatedStmtConstruct::getAssociatedStmt();
+ }
+ Stmt *getAssociatedStmt() {
+ return OpenACCAssociatedStmtConstruct::getAssociatedStmt();
+ }
+};
+
} // namespace clang } // namespace clang
#endif // LLVM_CLANG_AST_STMTOPENACC_H #endif // LLVM_CLANG_AST_STMTOPENACC_H
clang/include/clang/AST/TextNodeDumper.h
@@ -420,6 +420,7 @@ public:
void VisitOpenACCSetConstruct(const OpenACCSetConstruct *S); void VisitOpenACCSetConstruct(const OpenACCSetConstruct *S);
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S); void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S);
void VisitOpenACCUpdateConstruct(const OpenACCUpdateConstruct *S); void VisitOpenACCUpdateConstruct(const OpenACCUpdateConstruct *S);
+ void VisitOpenACCAtomicConstruct(const OpenACCAtomicConstruct *S);
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S); void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
void VisitEmbedExpr(const EmbedExpr *S); void VisitEmbedExpr(const EmbedExpr *S);
void VisitAtomicExpr(const AtomicExpr *AE); void VisitAtomicExpr(const AtomicExpr *AE);
clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2489,7 +2489,28 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral>
imaginaryLiteral; imaginaryLiteral;
-/// Matches fixed point literals+/// Matches fixed-point literals eg.
+/// 0.5r, 0.5hr, 0.5lr, 0.5uhr, 0.5ur, 0.5ulr
+/// 1.0k, 1.0hk, 1.0lk, 1.0uhk, 1.0uk, 1.0ulk
+/// Exponents 1.0e10k
+/// Hexadecimal numbers 0x0.2p2r
+///
+/// Does not match implicit conversions such as first two lines:
+/// \code
+/// short _Accum sa = 2;
+/// _Accum a = 12.5;
+/// _Accum b = 1.25hk;
+/// _Fract c = 0.25hr;
+/// _Fract v = 0.35uhr;
+/// _Accum g = 1.45uhk;
+/// _Accum decexp1 = 1.575e1k;
+/// \endcode
+/// \compile_args{-ffixed-point;-std=c99}
+///
+/// The matcher \matcher{fixedPointLiteral()} matches
+/// \match{1.25hk}, \match{0.25hr}, \match{0.35uhr},
+/// \match{1.45uhk}, \match{1.575e1k}, but does not
+/// match \nomatch{12.5} and \nomatch{2} from the code block.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, FixedPointLiteral> extern const internal::VariadicDynCastAllOfMatcher<Stmt, FixedPointLiteral>
fixedPointLiteral; fixedPointLiteral;
clang/include/clang/Analysis/ProgramPoint.h
@@ -85,6 +85,9 @@ public:
LoopExitKind, LoopExitKind,
EpsilonKind}; EpsilonKind};
+ static StringRef getProgramPointKindName(Kind K);
+ std::optional<SourceLocation> getSourceLocation() const;
+
private: private:
const void *Data1; const void *Data1;
llvm::PointerIntPair<const void *, 2, unsigned> Data2; llvm::PointerIntPair<const void *, 2, unsigned> Data2;
clang/include/clang/Basic/Attr.td
@@ -198,7 +198,7 @@ def OpenCLKernelFunction
// inclusive nature of subject testing). // inclusive nature of subject testing).
def HasFunctionProto : SubsetSubject<DeclBase, def HasFunctionProto : SubsetSubject<DeclBase,
[{(S->getFunctionType(true) != nullptr && [{(S->getFunctionType(true) != nullptr &&
- isa<FunctionProtoType>(S->getFunctionType())) ||+ isa<FunctionProtoType>(S->getFunctionType())) ||
isa<ObjCMethodDecl>(S) || isa<ObjCMethodDecl>(S) ||
isa<BlockDecl>(S)}], isa<BlockDecl>(S)}],
"non-K&R-style functions">; "non-K&R-style functions">;
@@ -380,6 +380,13 @@ class Clang<string name, bit allowInC = 1, int version = 1>
bit AllowInC = allowInC; bit AllowInC = allowInC;
} }
+// This spelling combines the spellings of GCC and Clang for cases where the
+// spellings are equivalent for compile compatibility.
+class ClangGCC<string name, bit allowInC = 1, int version = 1>
+ : Spelling<name, "ClangGCC", version> {
+ bit AllowInC = allowInC;
+}
+
// HLSL Annotation spellings // HLSL Annotation spellings
class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation">; class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation">;
@@ -3677,7 +3684,7 @@ def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86>
} }
def NoSanitize : InheritableAttr { def NoSanitize : InheritableAttr {
- let Spellings = [Clang<"no_sanitize">];+ let Spellings = [ClangGCC<"no_sanitize">];
let Args = [VariadicStringArgument<"Sanitizers">]; let Args = [VariadicStringArgument<"Sanitizers">];
let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag>; let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag>;
let Documentation = [NoSanitizeDocs]; let Documentation = [NoSanitizeDocs];
clang/include/clang/Basic/AttrDocs.td
@@ -5274,6 +5274,7 @@ optimization passes are aware of the following assumptions:
"omp_no_openmp" "omp_no_openmp"
"omp_no_openmp_routines" "omp_no_openmp_routines"
"omp_no_parallelism" "omp_no_parallelism"
+ "omp_no_openmp_constructs"
The OpenMP standard defines the meaning of OpenMP assumptions ("omp_XYZ" is The OpenMP standard defines the meaning of OpenMP assumptions ("omp_XYZ" is
spelled "XYZ" in the `OpenMP 5.1 Standard`_). spelled "XYZ" in the `OpenMP 5.1 Standard`_).
clang/include/clang/Basic/Builtins.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringTable.h"
#include <cstring> #include <cstring>
// VC++ defines 'alloca' as an object-like macro, which interferes with our // VC++ defines 'alloca' as an object-like macro, which interferes with our
@@ -55,6 +56,7 @@ struct HeaderDesc {
#undef HEADER #undef HEADER
} ID; } ID;
+ constexpr HeaderDesc() : ID() {}
constexpr HeaderDesc(HeaderID ID) : ID(ID) {} constexpr HeaderDesc(HeaderID ID) : ID(ID) {}
const char *getName() const; const char *getName() const;
@@ -62,20 +64,160 @@ struct HeaderDesc {
namespace Builtin { namespace Builtin {
enum ID { enum ID {
- NotBuiltin = 0, // This is not a builtin function.+ NotBuiltin = 0, // This is not a builtin function.
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/Builtins.inc" #include "clang/Basic/Builtins.inc"
+#undef GET_BUILTIN_ENUMERATORS
FirstTSBuiltin FirstTSBuiltin
}; };
+struct InfosShard;
+
+/// The info used to represent each builtin.
struct Info { struct Info {
- llvm::StringLiteral Name;+ // Rather than store pointers to the string literals describing these four
- const char *Type, *Attributes;+ // aspects of builtins, we store offsets into a common string table.
- const char *Features;+ struct StrOffsets {
- HeaderDesc Header;+ llvm::StringTable::Offset Name = {};
- LanguageID Langs;+ llvm::StringTable::Offset Type = {};
+ llvm::StringTable::Offset Attributes = {};
+
+ // Defaults to the empty string offset.
+ llvm::StringTable::Offset Features = {};
+ } Offsets;
+
+ HeaderDesc Header = HeaderDesc::NO_HEADER;
+ LanguageID Langs = ALL_LANGUAGES;
+
+ /// Get the name for the builtin represented by this `Info` object.
+ ///
+ /// Must be provided the `Shard` for this `Info` object.
+ std::string getName(const InfosShard &Shard) const;
}; };
+/// A constexpr function to construct an infos array from X-macros.
+///
+/// The input array uses the same data structure, but the offsets are actually
+/// _lengths_ when input. This is all we can compute from the X-macro approach
+/// to builtins. This function will convert these lengths into actual offsets to
+/// a string table built up through sequentially appending strings with the
+/// given lengths.
+template <size_t N>
+static constexpr std::array<Info, N> MakeInfos(std::array<Info, N> Infos) {
+ // Translate lengths to offsets. We start past the initial empty string at
+ // offset zero.
+ unsigned Offset = 1;
+ for (Info &I : Infos) {
+ Info::StrOffsets NewOffsets = {};
+ NewOffsets.Name = Offset;
+ Offset += I.Offsets.Name.value();
+ NewOffsets.Type = Offset;
+ Offset += I.Offsets.Type.value();
+ NewOffsets.Attributes = Offset;
+ Offset += I.Offsets.Attributes.value();
+ NewOffsets.Features = Offset;
+ Offset += I.Offsets.Features.value();
+ I.Offsets = NewOffsets;
+ }
+ return Infos;
+}
+
+/// A shard of a target's builtins string table and info.
+///
+/// Target builtins are sharded across multiple tables due to different
+/// structures, origins, and also to improve the overall scaling by avoiding a
+/// single table across all builtins.
+struct InfosShard {
+ const llvm::StringTable *Strings;
+ llvm::ArrayRef<Info> Infos;
+
+ llvm::StringLiteral NamePrefix = "";
+};
+
+// A detail macro used below to emit a string literal that, after string literal
+// concatenation, ends up triggering the `-Woverlength-strings` warning. While
+// the warning is useful in general to catch accidentally excessive strings,
+// here we are creating them intentionally.
+//
+// This relies on a subtle aspect of `_Pragma`: that the *diagnostic* ones don't
+// turn into actual tokens that would disrupt string literal concatenation.
+#ifdef __clang__
+#define CLANG_BUILTIN_DETAIL_STR_TABLE(S) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Woverlength-strings\"") \
+ S _Pragma("clang diagnostic pop")
+#else
+#define CLANG_BUILTIN_DETAIL_STR_TABLE(S) S
+#endif
+
+// We require string tables to start with an empty string so that a `0` offset
+// can always be used to refer to an empty string. To satisfy that when building
+// string tables with X-macros, we use this start macro prior to expanding the
+// X-macros.
+#define CLANG_BUILTIN_STR_TABLE_START CLANG_BUILTIN_DETAIL_STR_TABLE("\0")
+
+// A macro that can be used with `Builtins.def` and similar files as an X-macro
+// to add the string arguments to a builtin string table. This is typically the
+// target for the `BUILTIN`, `LANGBUILTIN`, or `LIBBUILTIN` macros in those
+// files.
+#define CLANG_BUILTIN_STR_TABLE(ID, TYPE, ATTRS) \
+ CLANG_BUILTIN_DETAIL_STR_TABLE(#ID "\0" TYPE "\0" ATTRS "\0" /*FEATURE*/ "\0")
+
+// A macro that can be used with target builtin `.def` and `.inc` files as an
+// X-macro to add the string arguments to a builtin string table. this is
+// typically the target for the `TARGET_BUILTIN` macro.
+#define CLANG_TARGET_BUILTIN_STR_TABLE(ID, TYPE, ATTRS, FEATURE) \
+ CLANG_BUILTIN_DETAIL_STR_TABLE(#ID "\0" TYPE "\0" ATTRS "\0" FEATURE "\0")
+
+// A macro that can be used with target builtin `.def` and `.inc` files as an
+// X-macro to add the string arguments to a builtin string table. this is
+// typically the target for the `TARGET_HEADER_BUILTIN` macro. We can't delegate
+// to `TARGET_BUILTIN` because the `FEATURE` string changes position.
+#define CLANG_TARGET_HEADER_BUILTIN_STR_TABLE(ID, TYPE, ATTRS, HEADER, LANGS, \
+ FEATURE) \
+ CLANG_BUILTIN_DETAIL_STR_TABLE(#ID "\0" TYPE "\0" ATTRS "\0" FEATURE "\0")
+
+// A detail macro used internally to compute the desired string table
+// `StrOffsets` struct for arguments to `MakeInfos`.
+#define CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS) \
+ Builtin::Info::StrOffsets { \
+ sizeof(#ID), sizeof(TYPE), sizeof(ATTRS), sizeof("") \
+ }
+
+// A detail macro used internally to compute the desired string table
+// `StrOffsets` struct for arguments to `Storage::Make`.
+#define CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS, FEATURE) \
+ Builtin::Info::StrOffsets { \
+ sizeof(#ID), sizeof(TYPE), sizeof(ATTRS), sizeof(FEATURE) \
+ }
+
+// A set of macros that can be used with builtin `.def' files as an X-macro to
+// create an `Info` struct for a particular builtin. It both computes the
+// `StrOffsets` value for the string table (the lengths here, translated to
+// offsets by the `MakeInfos` function), and the other metadata for each
+// builtin.
+//
+// There is a corresponding macro for each of `BUILTIN`, `LANGBUILTIN`,
+// `LIBBUILTIN`, `TARGET_BUILTIN`, and `TARGET_HEADER_BUILTIN`.
+#define CLANG_BUILTIN_ENTRY(ID, TYPE, ATTRS) \
+ Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS), \
+ HeaderDesc::NO_HEADER, ALL_LANGUAGES},
+#define CLANG_LANGBUILTIN_ENTRY(ID, TYPE, ATTRS, LANG) \
+ Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS), \
+ HeaderDesc::NO_HEADER, LANG},
+#define CLANG_LIBBUILTIN_ENTRY(ID, TYPE, ATTRS, HEADER, LANG) \
+ Builtin::Info{CLANG_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS), \
+ HeaderDesc::HEADER, LANG},
+#define CLANG_TARGET_BUILTIN_ENTRY(ID, TYPE, ATTRS, FEATURE) \
+ Builtin::Info{ \
+ CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS, FEATURE), \
+ HeaderDesc::NO_HEADER, ALL_LANGUAGES},
+#define CLANG_TARGET_HEADER_BUILTIN_ENTRY(ID, TYPE, ATTRS, HEADER, LANG, \
+ FEATURE) \
+ Builtin::Info{ \
+ CLANG_TARGET_BUILTIN_DETAIL_STR_OFFSETS(ID, TYPE, ATTRS, FEATURE), \
+ HeaderDesc::HEADER, LANG},
+
/// Holds information about both target-independent and /// Holds information about both target-independent and
/// target-specific builtins, allowing easy queries by clients. /// target-specific builtins, allowing easy queries by clients.
/// ///
@@ -83,11 +225,16 @@ struct Info {
/// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to /// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
/// be translated back with getAuxBuiltinID() before use. /// be translated back with getAuxBuiltinID() before use.
class Context { class Context {
- llvm::ArrayRef<Info> TSRecords;+ llvm::SmallVector<InfosShard> BuiltinShards;
- llvm::ArrayRef<Info> AuxTSRecords;+
+ llvm::SmallVector<InfosShard> TargetShards;
+ llvm::SmallVector<InfosShard> AuxTargetShards;
+
+ unsigned NumTargetBuiltins = 0;
+ unsigned NumAuxTargetBuiltins = 0;
public: public:
- Context() = default;+ Context();
/// Perform target-specific initialization /// Perform target-specific initialization
/// \param AuxTarget Target info to incorporate builtins from. May be nullptr. /// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
@@ -100,13 +247,17 @@ public:
/// Return the identifier name for the specified builtin, /// Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs". /// e.g. "__builtin_abs".
- llvm::StringRef getName(unsigned ID) const { return getRecord(ID).Name; }+ std::string getName(unsigned ID) const;
- /// Return a quoted name for the specified builtin for use in diagnostics.+ /// Return the identifier name for the specified builtin inside single quotes
+ /// for a diagnostic, e.g. "'__builtin_abs'".
std::string getQuotedName(unsigned ID) const; std::string getQuotedName(unsigned ID) const;
/// Get the type descriptor string for the specified builtin. /// Get the type descriptor string for the specified builtin.
- const char *getTypeString(unsigned ID) const { return getRecord(ID).Type; }+ const char *getTypeString(unsigned ID) const;
+
+ /// Get the attributes descriptor string for the specified builtin.
+ const char *getAttributesString(unsigned ID) const;
/// Return true if this function is a target-specific builtin. /// Return true if this function is a target-specific builtin.
bool isTSBuiltin(unsigned ID) const { bool isTSBuiltin(unsigned ID) const {
@@ -115,40 +266,40 @@ public:
/// Return true if this function has no side effects. /// Return true if this function has no side effects.
bool isPure(unsigned ID) const { bool isPure(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'U') != nullptr;+ return strchr(getAttributesString(ID), 'U') != nullptr;
} }
/// Return true if this function has no side effects and doesn't /// Return true if this function has no side effects and doesn't
/// read memory. /// read memory.
bool isConst(unsigned ID) const { bool isConst(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'c') != nullptr;+ return strchr(getAttributesString(ID), 'c') != nullptr;
} }
/// Return true if we know this builtin never throws an exception. /// Return true if we know this builtin never throws an exception.
bool isNoThrow(unsigned ID) const { bool isNoThrow(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'n') != nullptr;+ return strchr(getAttributesString(ID), 'n') != nullptr;
} }
/// Return true if we know this builtin never returns. /// Return true if we know this builtin never returns.
bool isNoReturn(unsigned ID) const { bool isNoReturn(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'r') != nullptr;+ return strchr(getAttributesString(ID), 'r') != nullptr;
} }
/// Return true if we know this builtin can return twice. /// Return true if we know this builtin can return twice.
bool isReturnsTwice(unsigned ID) const { bool isReturnsTwice(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'j') != nullptr;+ return strchr(getAttributesString(ID), 'j') != nullptr;
} }
/// Returns true if this builtin does not perform the side-effects /// Returns true if this builtin does not perform the side-effects
/// of its arguments. /// of its arguments.
bool isUnevaluated(unsigned ID) const { bool isUnevaluated(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'u') != nullptr;+ return strchr(getAttributesString(ID), 'u') != nullptr;
} }
/// Return true if this is a builtin for a libc/libm function, /// Return true if this is a builtin for a libc/libm function,
/// with a "__builtin_" prefix (e.g. __builtin_abs). /// with a "__builtin_" prefix (e.g. __builtin_abs).
bool isLibFunction(unsigned ID) const { bool isLibFunction(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'F') != nullptr;+ return strchr(getAttributesString(ID), 'F') != nullptr;
} }
/// Determines whether this builtin is a predefined libc/libm /// Determines whether this builtin is a predefined libc/libm
@@ -159,21 +310,21 @@ public:
/// they do not, but they are recognized as builtins once we see /// they do not, but they are recognized as builtins once we see
/// a declaration. /// a declaration.
bool isPredefinedLibFunction(unsigned ID) const { bool isPredefinedLibFunction(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'f') != nullptr;+ return strchr(getAttributesString(ID), 'f') != nullptr;
} }
/// Returns true if this builtin requires appropriate header in other /// Returns true if this builtin requires appropriate header in other
/// compilers. In Clang it will work even without including it, but we can emit /// compilers. In Clang it will work even without including it, but we can emit
/// a warning about missing header. /// a warning about missing header.
bool isHeaderDependentFunction(unsigned ID) const { bool isHeaderDependentFunction(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'h') != nullptr;+ return strchr(getAttributesString(ID), 'h') != nullptr;
} }
/// Determines whether this builtin is a predefined compiler-rt/libgcc /// Determines whether this builtin is a predefined compiler-rt/libgcc
/// function, such as "__clear_cache", where we know the signature a /// function, such as "__clear_cache", where we know the signature a
/// priori. /// priori.
bool isPredefinedRuntimeFunction(unsigned ID) const { bool isPredefinedRuntimeFunction(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'i') != nullptr;+ return strchr(getAttributesString(ID), 'i') != nullptr;
} }
/// Determines whether this builtin is a C++ standard library function /// Determines whether this builtin is a C++ standard library function
@@ -181,7 +332,7 @@ public:
/// specialization, where the signature is determined by the standard library /// specialization, where the signature is determined by the standard library
/// declaration. /// declaration.
bool isInStdNamespace(unsigned ID) const { bool isInStdNamespace(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'z') != nullptr;+ return strchr(getAttributesString(ID), 'z') != nullptr;
} }
/// Determines whether this builtin can have its address taken with no /// Determines whether this builtin can have its address taken with no
@@ -195,33 +346,33 @@ public:
/// Determines whether this builtin has custom typechecking. /// Determines whether this builtin has custom typechecking.
bool hasCustomTypechecking(unsigned ID) const { bool hasCustomTypechecking(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 't') != nullptr;+ return strchr(getAttributesString(ID), 't') != nullptr;
} }
/// Determines whether a declaration of this builtin should be recognized /// Determines whether a declaration of this builtin should be recognized
/// even if the type doesn't match the specified signature. /// even if the type doesn't match the specified signature.
bool allowTypeMismatch(unsigned ID) const { bool allowTypeMismatch(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'T') != nullptr ||+ return strchr(getAttributesString(ID), 'T') != nullptr ||
hasCustomTypechecking(ID); hasCustomTypechecking(ID);
} }
/// Determines whether this builtin has a result or any arguments which /// Determines whether this builtin has a result or any arguments which
/// are pointer types. /// are pointer types.
bool hasPtrArgsOrResult(unsigned ID) const { bool hasPtrArgsOrResult(unsigned ID) const {
- return strchr(getRecord(ID).Type, '*') != nullptr;+ return strchr(getTypeString(ID), '*') != nullptr;
} }
/// Return true if this builtin has a result or any arguments which are /// Return true if this builtin has a result or any arguments which are
/// reference types. /// reference types.
bool hasReferenceArgsOrResult(unsigned ID) const { bool hasReferenceArgsOrResult(unsigned ID) const {
- return strchr(getRecord(ID).Type, '&') != nullptr ||+ return strchr(getTypeString(ID), '&') != nullptr ||
- strchr(getRecord(ID).Type, 'A') != nullptr;+ strchr(getTypeString(ID), 'A') != nullptr;
} }
/// If this is a library function that comes from a specific /// If this is a library function that comes from a specific
/// header, retrieve that header name. /// header, retrieve that header name.
const char *getHeaderName(unsigned ID) const { const char *getHeaderName(unsigned ID) const {
- return getRecord(ID).Header.getName();+ return getInfo(ID).Header.getName();
} }
/// Determine whether this builtin is like printf in its /// Determine whether this builtin is like printf in its
@@ -246,27 +397,25 @@ public:
/// Such functions can be const when the MathErrno lang option and FP /// Such functions can be const when the MathErrno lang option and FP
/// exceptions are disabled. /// exceptions are disabled.
bool isConstWithoutErrnoAndExceptions(unsigned ID) const { bool isConstWithoutErrnoAndExceptions(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'e') != nullptr;+ return strchr(getAttributesString(ID), 'e') != nullptr;
} }
bool isConstWithoutExceptions(unsigned ID) const { bool isConstWithoutExceptions(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'g') != nullptr;+ return strchr(getAttributesString(ID), 'g') != nullptr;
} }
- const char *getRequiredFeatures(unsigned ID) const {+ const char *getRequiredFeatures(unsigned ID) const;
- return getRecord(ID).Features;
- }
unsigned getRequiredVectorWidth(unsigned ID) const; unsigned getRequiredVectorWidth(unsigned ID) const;
/// Return true if builtin ID belongs to AuxTarget. /// Return true if builtin ID belongs to AuxTarget.
bool isAuxBuiltinID(unsigned ID) const { bool isAuxBuiltinID(unsigned ID) const {
- return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());+ return ID >= (Builtin::FirstTSBuiltin + NumTargetBuiltins);
} }
/// Return real builtin ID (i.e. ID it would have during compilation /// Return real builtin ID (i.e. ID it would have during compilation
/// for AuxTarget). /// for AuxTarget).
- unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }+ unsigned getAuxBuiltinID(unsigned ID) const { return ID - NumTargetBuiltins; }
/// Returns true if this is a libc/libm function without the '__builtin_' /// Returns true if this is a libc/libm function without the '__builtin_'
/// prefix. /// prefix.
@@ -278,16 +427,19 @@ public:
/// Return true if this function can be constant evaluated by Clang frontend. /// Return true if this function can be constant evaluated by Clang frontend.
bool isConstantEvaluated(unsigned ID) const { bool isConstantEvaluated(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'E') != nullptr;+ return strchr(getAttributesString(ID), 'E') != nullptr;
} }
/// Returns true if this is an immediate (consteval) function /// Returns true if this is an immediate (consteval) function
bool isImmediate(unsigned ID) const { bool isImmediate(unsigned ID) const {
- return strchr(getRecord(ID).Attributes, 'G') != nullptr;+ return strchr(getAttributesString(ID), 'G') != nullptr;
} }
private: private:
- const Info &getRecord(unsigned ID) const;+ std::pair<const InfosShard &, const Info &>
+ getShardAndInfo(unsigned ID) const;
+
+ const Info &getInfo(unsigned ID) const { return getShardAndInfo(ID).second; }
/// Helper function for isPrintfLike and isScanfLike. /// Helper function for isPrintfLike and isScanfLike.
bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
clang/include/clang/Basic/BuiltinsARM.def
@@ -206,13 +206,6 @@ BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
// Misc // Misc
BUILTIN(__builtin_sponentry, "v*", "c") BUILTIN(__builtin_sponentry, "v*", "c")
-// Builtins for implementing ACLE MVE intrinsics. (Unlike NEON, these
-// don't need to live in a separate BuiltinsMVE.def, because they
-// aren't included from both here and BuiltinsAArch64.def.)
-#include "clang/Basic/arm_mve_builtins.inc"
-
-#include "clang/Basic/arm_cde_builtins.inc"
-
// MSVC // MSVC
LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES) LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
clang/include/clang/Basic/BuiltinsBase.td
@@ -86,6 +86,13 @@ def Consteval : Attribute<"EG">;
// indicated by the remaining indices. // indicated by the remaining indices.
class Callback<list<int> ArgIndices> : MultiIndexAttribute<"C", ArgIndices>; class Callback<list<int> ArgIndices> : MultiIndexAttribute<"C", ArgIndices>;
+// Prefixes
+// ========
+
+class NamePrefix<string spelling> {
+ string Spelling = spelling;
+}
+
// Builtin kinds // Builtin kinds
// ============= // =============
@@ -99,6 +106,9 @@ class Builtin {
bit RequiresUndef = 0; bit RequiresUndef = 0;
// Enables builtins to generate `long long` outside of OpenCL and `long` inside. // Enables builtins to generate `long long` outside of OpenCL and `long` inside.
bit EnableOpenCLLong = 0; bit EnableOpenCLLong = 0;
+ // Requires a common prefix to be prepended. Each generated set of builtins
+ // can optionally extract one common prefix that is handled separately.
+ NamePrefix RequiredNamePrefix;
} }
class AtomicBuiltin : Builtin; class AtomicBuiltin : Builtin;
clang/include/clang/Basic/BuiltinsHexagon.td
@@ -56,10 +56,13 @@ def HVXV65 : HVXV<"65", HVXV66>;
def HVXV62 : HVXV<"62", HVXV65>; def HVXV62 : HVXV<"62", HVXV65>;
def HVXV60 : HVXV<"60", HVXV62>; def HVXV60 : HVXV<"60", HVXV62>;
+def HexagonPrefix : NamePrefix<"__builtin_HEXAGON_">;
+
class HexagonBuiltin<string prototype> : TargetBuiltin { class HexagonBuiltin<string prototype> : TargetBuiltin {
- let Spellings = ["__builtin_HEXAGON_" # NAME];+ let Spellings = [NAME];
let Prototype = prototype; let Prototype = prototype;
let Features = V5.Features; let Features = V5.Features;
+ let RequiredNamePrefix = HexagonPrefix; // Adds a prefix to the name.
} }
class HexagonBuiltinNoPrefix<string prototype> : TargetBuiltin { class HexagonBuiltinNoPrefix<string prototype> : TargetBuiltin {
clang/include/clang/Basic/BuiltinsLoongArch.def→/dev/null
@@ -1,28 +0,0 @@
-//==- BuiltinsLoongArch.def - LoongArch Builtin function database -- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LoongArch-specific builtin function database. Users of
-// this file must define the BUILTIN macro to make use of this information.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
-# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
-#endif
-
-// Definition of LoongArch basic builtins.
-#include "clang/Basic/BuiltinsLoongArchBase.def"
-
-// Definition of LSX builtins.
-#include "clang/Basic/BuiltinsLoongArchLSX.def"
-
-// Definition of LASX builtins.
-#include "clang/Basic/BuiltinsLoongArchLASX.def"
-
-#undef BUILTIN
-#undef TARGET_BUILTIN
clang/include/clang/Basic/BuiltinsNEON.def→/dev/null
@@ -1,22 +0,0 @@
-//===--- BuiltinsNEON.def - NEON Builtin function database ------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the NEON-specific builtin function database. Users of
-// this file must define the BUILTIN macro to make use of this information.
-//
-//===----------------------------------------------------------------------===//
-
-// The format of this database matches clang/Basic/Builtins.def.
-
-#define GET_NEON_BUILTINS
-#include "clang/Basic/arm_neon.inc"
-#include "clang/Basic/arm_fp16.inc"
-#undef GET_NEON_BUILTINS
-
-#undef BUILTIN
-#undef TARGET_BUILTIN
clang/include/clang/Basic/BuiltinsPPC.def
@@ -1138,5 +1138,6 @@ UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2nn, "vW512*VVi15i15i3", true,
// FIXME: Obviously incomplete. // FIXME: Obviously incomplete.
#undef BUILTIN #undef BUILTIN
+#undef TARGET_BUILTIN
#undef CUSTOM_BUILTIN #undef CUSTOM_BUILTIN
#undef UNALIASED_CUSTOM_BUILTIN #undef UNALIASED_CUSTOM_BUILTIN
clang/include/clang/Basic/BuiltinsRISCVVector.def→/dev/null
@@ -1,22 +0,0 @@
-//==- BuiltinsRISCVVector.def - RISC-V Vector Builtin Database ---*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the RISC-V-specific builtin function database. Users of
-// this file must define the BUILTIN macro to make use of this information.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
-# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
-#endif
-
-#include "clang/Basic/riscv_vector_builtins.inc"
-#include "clang/Basic/riscv_sifive_vector_builtins.inc"
-
-#undef BUILTIN
-#undef TARGET_BUILTIN
clang/include/clang/Basic/BuiltinsSME.def→/dev/null
@@ -1,21 +0,0 @@
-//===--- BuiltinsSME.def - SME Builtin function database --------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the SME-specific builtin function database. Users of
-// this file must define the BUILTIN macro to make use of this information.
-//
-//===----------------------------------------------------------------------===//
-
-// The format of this database matches clang/Basic/Builtins.def.
-
-#define GET_SME_BUILTINS
-#include "clang/Basic/arm_sme_builtins.inc"
-#undef GET_SME_BUILTINS
-
-#undef BUILTIN
-#undef TARGET_BUILTIN
clang/include/clang/Basic/BuiltinsSVE.def→/dev/null
@@ -1,22 +0,0 @@
-//===--- BuiltinsSVE.def - SVE Builtin function database --------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the SVE-specific builtin function database. Users of
-// this file must define the BUILTIN macro to make use of this information.
-//
-//===----------------------------------------------------------------------===//
-
-// The format of this database matches clang/Basic/Builtins.def.
-
-#define GET_SVE_BUILTINS
-#include "clang/Basic/arm_sve_builtins.inc"
-#include "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
-#undef GET_SVE_BUILTINS
-
-#undef BUILTIN
-#undef TARGET_BUILTIN
clang/include/clang/Basic/BuiltinsX86Base.td
@@ -12,10 +12,13 @@
include "clang/Basic/BuiltinsBase.td" include "clang/Basic/BuiltinsBase.td"
+def X86Prefix : NamePrefix<"__builtin_ia32_">;
+
class X86Builtin<string prototype> : TargetBuiltin { class X86Builtin<string prototype> : TargetBuiltin {
- let Spellings = ["__builtin_ia32_" # NAME];+ let Spellings = [NAME];
let Prototype = prototype; let Prototype = prototype;
let EnableOpenCLLong = 1; let EnableOpenCLLong = 1;
+ let RequiredNamePrefix = X86Prefix; // Adds a prefix to the name.
} }
class X86NoPrefixBuiltin<string prototype> : TargetBuiltin { class X86NoPrefixBuiltin<string prototype> : TargetBuiltin {
clang/include/clang/Basic/CodeGenOptions.def
@@ -221,6 +221,7 @@ AFFECTING_VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option spec
AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic
+CODEGENOPT(ContinuousProfileSync, 1, 0) ///< Enable continuous instrumentation profiling
/// Choose profile instrumenation kind or no instrumentation. /// Choose profile instrumenation kind or no instrumentation.
ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone) ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone)
/// Choose profile kind for PGO use compilation. /// Choose profile kind for PGO use compilation.
@@ -277,6 +278,7 @@ CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types
///< CFI icall function signatures ///< CFI icall function signatures
CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
///< instead of creating a local jump table. ///< instead of creating a local jump table.
+CODEGENOPT(SanitizeKcfiArity, 1, 0) ///< Embed arity in KCFI patchable function prefix
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation. ///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
@@ -319,6 +321,7 @@ CODEGENOPT(TimePassesPerRun , 1, 0) ///< Set when -ftime-report=per-pass-run is
CODEGENOPT(TimeTrace , 1, 0) ///< Set when -ftime-trace is enabled. CODEGENOPT(TimeTrace , 1, 0) ///< Set when -ftime-trace is enabled.
VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (in microseconds), VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (in microseconds),
///< traced by time profiler ///< traced by time profiler
+CODEGENOPT(InterchangeLoops , 1, 0) ///< Run loop-interchange.
CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled. CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled. CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled. CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
@@ -469,6 +472,10 @@ CODEGENOPT(CtorDtorReturnThis, 1, 0)
/// by the Windows kernel to enable import call optimization. /// by the Windows kernel to enable import call optimization.
CODEGENOPT(ImportCallOptimization, 1, 0) CODEGENOPT(ImportCallOptimization, 1, 0)
+/// Controls whether we generate code for static linking of libclosure
+/// (BlocksRuntime) on Windows.
+CODEGENOPT(StaticClosure, 1, 0)
+
/// FIXME: Make DebugOptions its own top-level .def file. /// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def" #include "DebugOptions.def"
clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -209,6 +209,8 @@ def err_drv_cannot_open_randomize_layout_seed_file : Error<
"cannot read randomize layout seed file '%0'">; "cannot read randomize layout seed file '%0'">;
def err_drv_invalid_version_number : Error< def err_drv_invalid_version_number : Error<
"invalid version number in '%0'">; "invalid version number in '%0'">;
+def err_drv_kcfi_arity_unsupported_target : Error<
+ "target '%0' is unsupported by -fsanitize-kcfi-arity">;
def err_drv_no_linker_llvm_support : Error< def err_drv_no_linker_llvm_support : Error<
"'%0': unable to pass LLVM bit-code files to linker">; "'%0': unable to pass LLVM bit-code files to linker">;
def err_drv_no_ast_support : Error< def err_drv_no_ast_support : Error<
clang/include/clang/Basic/DiagnosticGroups.td
@@ -694,6 +694,36 @@ def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess",
NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>; NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>;
def StaticInInline : DiagGroup<"static-in-inline">; def StaticInInline : DiagGroup<"static-in-inline">;
def StaticLocalInInline : DiagGroup<"static-local-in-inline">; def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
+def UniqueObjectDuplication : DiagGroup<"unique-object-duplication"> {
+ code Documentation = [{
+Warns when objects which are supposed to be globally unique might get duplicated
+when built into a shared library.
+
+If an object with hidden visibility is built into a shared library, each instance
+of the library will get its own copy. This can cause very subtle bugs if there was
+only supposed to be one copy of the object in question: singletons aren't single,
+changes to one object won't affect the others, the object's initializer will run
+once per copy, etc.
+
+Specifically, this warning fires when it detects an object which:
+ 1. Appears in a header file (so it might get compiled into multiple libaries), and
+ 2. Has external linkage (otherwise it's supposed to be duplicated), and
+ 3. Has hidden visibility.
+
+As well as one of the following:
+ 1. The object is mutable, or
+ 2. The object's initializer definitely has side effects.
+
+The warning is best resolved by making the object ``const`` (if possible), or by explicitly
+giving the object non-hidden visibility, e.g. using ``__attribute((visibility("default")))``.
+Note that all levels of a pointer variable must be constant; ``const int*`` will
+trigger the warning because the pointer itself is mutable.
+
+This warning is currently disabled on Windows since it uses import/export rules
+instead of visibility.
+}];
+}
+
def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>; def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
// Allow differentiation between GNU statement expressions in a macro versus // Allow differentiation between GNU statement expressions in a macro versus
clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -350,10 +350,11 @@ def warn_arm_interrupt_vfp_clobber : Warning<
InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>; InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>;
def err_arm_interrupt_called : Error< def err_arm_interrupt_called : Error<
"interrupt service routine cannot be called directly">; "interrupt service routine cannot be called directly">;
-def warn_interrupt_attribute_invalid : Warning<+def warn_interrupt_signal_attribute_invalid : Warning<
- "%select{MIPS|MSP430|RISC-V}0 'interrupt' attribute only applies to "+ "%select{MIPS|MSP430|RISC-V|AVR}0 '%select{interrupt|signal}1' "
- "functions that have %select{no parameters|a 'void' return type}1">,+ "attribute only applies to functions that have "
- InGroup<IgnoredAttributes>;+ "%select{no parameters|a 'void' return type}2">,
+ InGroup<IgnoredAttributes>;
def warn_riscv_repeated_interrupt_attribute : Warning< def warn_riscv_repeated_interrupt_attribute : Warning<
"repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>; "repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>;
def note_riscv_repeated_interrupt_attribute : Note< def note_riscv_repeated_interrupt_attribute : Note<
@@ -490,7 +491,7 @@ def warn_qual_return_type : Warning<
"'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">, "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">,
InGroup<IgnoredQualifiers>, DefaultIgnore; InGroup<IgnoredQualifiers>, DefaultIgnore;
def warn_qual_base_type : Warning< def warn_qual_base_type : Warning<
- "'%0' qualifier%s1 on base class type %2 have no effect">,+ "'%0' qualifier%s1 on base class type %2 %plural{1:has|:have}1 no effect">,
InGroup<IgnoredQualifiers>, DefaultIgnore; InGroup<IgnoredQualifiers>, DefaultIgnore;
def warn_deprecated_redundant_constexpr_static_def : Warning< def warn_deprecated_redundant_constexpr_static_def : Warning<
@@ -3832,6 +3833,9 @@ def warn_type_attribute_wrong_type : Warning<
"'%0' only applies to %select{function|pointer|" "'%0' only applies to %select{function|pointer|"
"Objective-C object or block pointer}1 types; type here is %2">, "Objective-C object or block pointer}1 types; type here is %2">,
InGroup<IgnoredAttributes>; InGroup<IgnoredAttributes>;
+def warn_attribute_on_void_param: Warning<
+ "attribute %0 cannot be applied to a 'void' parameter">,
+ InGroup<IgnoredAttributes>;
def err_type_attribute_wrong_type : Error< def err_type_attribute_wrong_type : Error<
warn_type_attribute_wrong_type.Summary>; warn_type_attribute_wrong_type.Summary>;
def warn_incomplete_encoded_type : Warning< def warn_incomplete_encoded_type : Warning<
@@ -6113,6 +6117,8 @@ def note_deleted_special_member_class_subobject : Note<
"destructor}5" "destructor}5"
"%select{||s||}4" "%select{||s||}4"
"|is an ObjC pointer}6">; "|is an ObjC pointer}6">;
+def note_default_constructed_field
+ : Note<"default constructed field %0 declared here">;
def note_deleted_default_ctor_uninit_field : Note< def note_deleted_default_ctor_uninit_field : Note<
"%select{default constructor of|constructor inherited by}0 " "%select{default constructor of|constructor inherited by}0 "
"%1 is implicitly deleted because field %2 of " "%1 is implicitly deleted because field %2 of "
@@ -6167,6 +6173,15 @@ def warn_static_local_in_extern_inline : Warning<
def note_convert_inline_to_static : Note< def note_convert_inline_to_static : Note<
"use 'static' to give inline function %0 internal linkage">; "use 'static' to give inline function %0 internal linkage">;
+def warn_possible_object_duplication_mutable : Warning<
+ "%0 may be duplicated when built into a shared library: "
+ "it is mutable, has hidden visibility, and external linkage">,
+ InGroup<UniqueObjectDuplication>, DefaultIgnore;
+def warn_possible_object_duplication_init : Warning<
+ "initializeation of %0 may run twice when built into a shared library: "
+ "it has hidden visibility and external linkage">,
+ InGroup<UniqueObjectDuplication>, DefaultIgnore;
+
def ext_redefinition_of_typedef : ExtWarn< def ext_redefinition_of_typedef : ExtWarn<
"redefinition of typedef %0 is a C11 feature">, "redefinition of typedef %0 is a C11 feature">,
InGroup<DiagGroup<"typedef-redefinition"> >; InGroup<DiagGroup<"typedef-redefinition"> >;
@@ -9182,6 +9197,8 @@ def err_cuda_device_exceptions : Error<
def err_dynamic_var_init : Error< def err_dynamic_var_init : Error<
"dynamic initialization is not supported for " "dynamic initialization is not supported for "
"__device__, __constant__, __shared__, and __managed__ variables">; "__device__, __constant__, __shared__, and __managed__ variables">;
+def err_cuda_ctor_dtor_attrs
+ : Error<"CUDA does not support global %0 for __device__ functions">;
def err_shared_var_init : Error< def err_shared_var_init : Error<
"initialization is not supported for __shared__ variables">; "initialization is not supported for __shared__ variables">;
def err_cuda_vla : Error< def err_cuda_vla : Error<
@@ -12903,6 +12920,48 @@ def err_acc_update_as_body
: Error<"OpenACC 'update' construct may not appear in place of the " : Error<"OpenACC 'update' construct may not appear in place of the "
"statement following a%select{n if statement| while statement| do " "statement following a%select{n if statement| while statement| do "
"statement| switch statement| label statement}0">; "statement| switch statement| label statement}0">;
+def err_acc_invalid_atomic
+ : Error<"statement associated with OpenACC 'atomic%select{| "
+ "%1}0' directive is invalid">;
+def note_acc_atomic_expr_must_be
+ : Note<"expected "
+ "%enum_select<OACCAtomicExpr>{%Assign{assignment}|%UnaryCompAssign{"
+ "assignment, compound assignment, increment, or decrement}}0 "
+ "expression">;
+def note_acc_atomic_unsupported_unary_operator
+ : Note<"unary operator not supported, only increment and decrement "
+ "operations permitted">;
+def note_acc_atomic_unsupported_binary_operator
+ : Note<"binary operator not supported, only +, *, -, /, &, ^, |, <<, or >> "
+ "are permitted">;
+def note_acc_atomic_unsupported_compound_binary_operator
+ : Note<"compound binary operator not supported, only +=, *=, -=, /=, &=, "
+ "^=, |=, <<=, or >>= are permitted">;
+
+def note_acc_atomic_operand_lvalue_scalar
+ : Note<"%select{left |right |}0operand to "
+ "%enum_select<OACCAtomicOpKind>{%Assign{assignment}|%CompoundAssign{"
+ "compound assignment}|%Inc{increment}|"
+ "%Dec{decrement}}1 "
+ "expression must be "
+ "%enum_select<OACCLValScalar>{%LVal{an l-value}|%Scalar{of scalar "
+ "type (was %3)}}2">;
+def note_acc_atomic_too_many_stmts
+ : Note<"'atomic capture' with a compound statement only supports two "
+ "statements">;
+def note_acc_atomic_expected_binop : Note<"expected binary operation on right "
+ "hand side of assignment operator">;
+def note_acc_atomic_mismatch_operand
+ : Note<"left hand side of assignment operation('%0') must match one side "
+ "of the sub-operation on the right hand side('%1' and '%2')">;
+def note_acc_atomic_mismatch_compound_operand
+ : Note<"variable %select{|in unary expression|on right hand side of "
+ "assignment|on left hand side of assignment|on left hand side of "
+ "compound assignment|on left hand side of assignment}2('%3') must "
+ "match variable used %select{|in unary expression|on right hand "
+ "side of assignment|<not possible>|on left hand side of compound "
+ "assignment|on left hand side of assignment}0('%1') from the first "
+ "statement">;
// AMDGCN builtins diagnostics // AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">; def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
clang/include/clang/Basic/FPOptions.def
@@ -28,5 +28,5 @@ OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc)
OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod)
OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, Float16ExcessPrecision) OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, Float16ExcessPrecision)
OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision) OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision)
-OPTION(ComplexRange, LangOptions::ComplexRangeKind, 2, MathErrno)+OPTION(ComplexRange, LangOptions::ComplexRangeKind, 3, MathErrno)
#undef OPTION #undef OPTION
clang/include/clang/Basic/Features.def
@@ -254,6 +254,7 @@ FEATURE(is_trivially_constructible, LangOpts.CPlusPlus)
FEATURE(is_trivially_copyable, LangOpts.CPlusPlus) FEATURE(is_trivially_copyable, LangOpts.CPlusPlus)
FEATURE(is_union, LangOpts.CPlusPlus) FEATURE(is_union, LangOpts.CPlusPlus)
FEATURE(kcfi, LangOpts.Sanitize.has(SanitizerKind::KCFI)) FEATURE(kcfi, LangOpts.Sanitize.has(SanitizerKind::KCFI))
+FEATURE(kcfi_arity, LangOpts.Sanitize.has(SanitizerKind::KCFI))
FEATURE(modules, LangOpts.Modules) FEATURE(modules, LangOpts.Modules)
FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack)) FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack))
FEATURE(shadow_call_stack, FEATURE(shadow_call_stack,
clang/include/clang/Basic/IdentifierTable.h
@@ -101,8 +101,9 @@ enum class InterestingIdentifier {
NUM_OBJC_KEYWORDS_AND_NOTABLE_IDENTIFIERS, NUM_OBJC_KEYWORDS_AND_NOTABLE_IDENTIFIERS,
NotBuiltin, NotBuiltin,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/Builtins.inc" #include "clang/Basic/Builtins.inc"
+#undef GET_BUILTIN_ENUMERATORS
FirstTSBuiltin, FirstTSBuiltin,
NotInterestingIdentifier = 65534 NotInterestingIdentifier = 65534
clang/include/clang/Basic/LangOptions.def
@@ -238,7 +238,7 @@ BENIGN_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization wit
BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal") BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal")
BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation") BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation")
-ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 2, CX_None, "Enable use of range reduction for complex arithmetics.")+ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 3, CX_None, "Enable use of range reduction for complex arithmetics.")
BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
clang/include/clang/Basic/LangOptions.h
@@ -250,6 +250,11 @@ public:
/// passing them as if they had a size of 1 byte. /// passing them as if they had a size of 1 byte.
Ver19, Ver19,
+ /// Attempt to be ABI-compatible with code generated by Clang 20.0.x.
+ /// This causes clang to:
+ /// - Incorrectly return C++ records in AVX registers on x86_64.
+ Ver20,
+
/// Conform to the underlying platform's C and C++ ABIs as closely /// Conform to the underlying platform's C and C++ ABIs as closely
/// as we can. /// as we can.
Latest Latest
@@ -643,9 +648,12 @@ public:
// Define accessors/mutators for language options of enumeration type. // Define accessors/mutators for language options of enumeration type.
#define LANGOPT(Name, Bits, Default, Description) #define LANGOPT(Name, Bits, Default, Description)
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
- Type get##Name() const { return static_cast<Type>(Name); } \+ Type get##Name() const { return static_cast<Type>(Name); } \
- void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }+ void set##Name(Type Value) { \
+ assert(static_cast<unsigned>(Value) < (1u << Bits)); \
+ Name = static_cast<unsigned>(Value); \
+ }
#include "clang/Basic/LangOptions.def" #include "clang/Basic/LangOptions.def"
/// Are we compiling a module? /// Are we compiling a module?
@@ -954,11 +962,14 @@ public:
void applyChanges(FPOptionsOverride FPO); void applyChanges(FPOptionsOverride FPO);
// We can define most of the accessors automatically: // We can define most of the accessors automatically:
+ // TODO: consider enforcing the assertion that value fits within bits
+ // statically.
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
TYPE get##NAME() const { \ TYPE get##NAME() const { \
return static_cast<TYPE>((Value & NAME##Mask) >> NAME##Shift); \ return static_cast<TYPE>((Value & NAME##Mask) >> NAME##Shift); \
} \ } \
void set##NAME(TYPE value) { \ void set##NAME(TYPE value) { \
+ assert(storage_type(value) < (1u << WIDTH)); \
Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \ Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \
} }
#include "clang/Basic/FPOptions.def" #include "clang/Basic/FPOptions.def"
clang/include/clang/Basic/OpenACCKinds.h
@@ -171,9 +171,34 @@ enum class OpenACCAtomicKind : uint8_t {
Write, Write,
Update, Update,
Capture, Capture,
- Invalid,+ None,
}; };
+template <typename StreamTy>
+inline StreamTy &printOpenACCAtomicKind(StreamTy &Out, OpenACCAtomicKind AK) {
+ switch (AK) {
+ case OpenACCAtomicKind::Read:
+ return Out << "read";
+ case OpenACCAtomicKind::Write:
+ return Out << "write";
+ case OpenACCAtomicKind::Update:
+ return Out << "update";
+ case OpenACCAtomicKind::Capture:
+ return Out << "capture";
+ case OpenACCAtomicKind::None:
+ return Out << "<none>";
+ }
+ llvm_unreachable("unknown atomic kind");
+}
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
+ OpenACCAtomicKind AK) {
+ return printOpenACCAtomicKind(Out, AK);
+}
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
+ OpenACCAtomicKind AK) {
+ return printOpenACCAtomicKind(Out, AK);
+}
+
/// Represents the kind of an OpenACC clause. /// Represents the kind of an OpenACC clause.
enum class OpenACCClauseKind : uint8_t { enum class OpenACCClauseKind : uint8_t {
/// 'finalize' clause, allowed on 'exit data' directive. /// 'finalize' clause, allowed on 'exit data' directive.
clang/include/clang/Basic/OpenMPKinds.h
@@ -399,6 +399,14 @@ bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind);
/// \return true - if the above condition is met for this directive /// \return true - if the above condition is met for this directive
/// otherwise - false. /// otherwise - false.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind); bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind);
+
+/// Checks if the specified directive is an order concurrent nestable
+/// directive that can be nested within region corresponding to construct
+/// on which order clause was specified with concurrent as ordering argument.
+/// \param DKind Specified directive.
+/// \return true - if the above condition is met for this directive
+/// otherwise - false.
+bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind);
} }
template <> template <>
clang/include/clang/Basic/StmtNodes.td
@@ -319,6 +319,7 @@ def OpenACCInitConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>; def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCSetConstruct : StmtNode<OpenACCConstructStmt>; def OpenACCSetConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCUpdateConstruct : StmtNode<OpenACCConstructStmt>; def OpenACCUpdateConstruct : StmtNode<OpenACCConstructStmt>;
+def OpenACCAtomicConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
// OpenACC Additional Expressions. // OpenACC Additional Expressions.
def OpenACCAsteriskSizeExpr : StmtNode<Expr>; def OpenACCAsteriskSizeExpr : StmtNode<Expr>;
clang/include/clang/Basic/TargetBuiltins.h
@@ -26,30 +26,50 @@ namespace clang {
namespace NEON { namespace NEON {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_NEON_BUILTIN_ENUMERATORS
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID,+#include "clang/Basic/arm_neon.inc"
-#include "clang/Basic/BuiltinsNEON.def"+ FirstFp16Builtin,
+ LastNeonBuiltin = FirstFp16Builtin - 1,
+#include "clang/Basic/arm_fp16.inc"
+#undef GET_NEON_BUILTIN_ENUMERATORS
FirstTSBuiltin FirstTSBuiltin
}; };
} }
/// ARM builtins /// ARM builtins
namespace ARM { namespace ARM {
- enum {+ enum {
- LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
- LastNEONBuiltin = NEON::FirstTSBuiltin - 1,+ LastNEONBuiltin = NEON::FirstTSBuiltin - 1,
+#define GET_MVE_BUILTIN_ENUMERATORS
+#include "clang/Basic/arm_mve_builtins.inc"
+#undef GET_MVE_BUILTIN_ENUMERATORS
+ FirstCDEBuiltin,
+ LastMVEBuiltin = FirstCDEBuiltin - 1,
+#define GET_CDE_BUILTIN_ENUMERATORS
+#include "clang/Basic/arm_cde_builtins.inc"
+#undef GET_CDE_BUILTIN_ENUMERATORS
+ FirstARMBuiltin,
+ LastCDEBuiltin = FirstARMBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID, #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/Basic/BuiltinsARM.def" #include "clang/Basic/BuiltinsARM.def"
- LastTSBuiltin+ LastTSBuiltin
- };+ };
} }
namespace SVE { namespace SVE {
enum { enum {
LastNEONBuiltin = NEON::FirstTSBuiltin - 1, LastNEONBuiltin = NEON::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_SVE_BUILTIN_ENUMERATORS
+#include "clang/Basic/arm_sve_builtins.inc"
+#undef GET_SVE_BUILTIN_ENUMERATORS
+ FirstNeonBridgeBuiltin,
+ LastSveBuiltin = FirstNeonBridgeBuiltin - 1,
+#define GET_SVE_BUILTINS
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID, #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID,
-#include "clang/Basic/BuiltinsSVE.def"+#include "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
+#undef TARGET_BUILTIN
+#undef GET_SVE_BUILTINS
FirstTSBuiltin, FirstTSBuiltin,
}; };
} }
@@ -57,9 +77,9 @@ namespace clang {
namespace SME { namespace SME {
enum { enum {
LastSVEBuiltin = SVE::FirstTSBuiltin - 1, LastSVEBuiltin = SVE::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_SME_BUILTIN_ENUMERATORS
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID,+#include "clang/Basic/arm_sme_builtins.inc"
-#include "clang/Basic/BuiltinsSME.def"+#undef GET_SME_BUILTIN_ENUMERATORS
FirstTSBuiltin, FirstTSBuiltin,
}; };
} }
@@ -83,8 +103,9 @@ namespace clang {
namespace BPF { namespace BPF {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
- #define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
- #include "clang/Basic/BuiltinsBPF.inc"+#include "clang/Basic/BuiltinsBPF.inc"
+#undef GET_BUILTIN_ENUMERATORS
LastTSBuiltin LastTSBuiltin
}; };
} }
@@ -103,8 +124,9 @@ namespace clang {
namespace NVPTX { namespace NVPTX {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/BuiltinsNVPTX.inc" #include "clang/Basic/BuiltinsNVPTX.inc"
+#undef GET_BUILTIN_ENUMERATORS
LastTSBuiltin LastTSBuiltin
}; };
} }
@@ -123,8 +145,9 @@ namespace clang {
namespace SPIRV { namespace SPIRV {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/BuiltinsSPIRV.inc" #include "clang/Basic/BuiltinsSPIRV.inc"
+#undef GET_BUILTIN_ENUMERATORS
LastTSBuiltin LastTSBuiltin
}; };
} // namespace SPIRV } // namespace SPIRV
@@ -133,12 +156,14 @@ namespace clang {
namespace X86 { namespace X86 {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/BuiltinsX86.inc" #include "clang/Basic/BuiltinsX86.inc"
+#undef GET_BUILTIN_ENUMERATORS
FirstX86_64Builtin, FirstX86_64Builtin,
LastX86CommonBuiltin = FirstX86_64Builtin - 1, LastX86CommonBuiltin = FirstX86_64Builtin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/BuiltinsX86_64.inc" #include "clang/Basic/BuiltinsX86_64.inc"
+#undef GET_BUILTIN_ENUMERATORS
LastTSBuiltin LastTSBuiltin
}; };
} }
@@ -156,8 +181,12 @@ namespace clang {
namespace RISCVVector { namespace RISCVVector {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_RISCVV_BUILTIN_ENUMERATORS
-#include "clang/Basic/BuiltinsRISCVVector.def"+#include "clang/Basic/riscv_vector_builtins.inc"
+ FirstSiFiveBuiltin,
+ LastRVVBuiltin = FirstSiFiveBuiltin - 1,
+#include "clang/Basic/riscv_sifive_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_ENUMERATORS
FirstTSBuiltin, FirstTSBuiltin,
}; };
} }
@@ -168,8 +197,9 @@ namespace clang {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
FirstRVVBuiltin = clang::Builtin::FirstTSBuiltin, FirstRVVBuiltin = clang::Builtin::FirstTSBuiltin,
LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1, LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/BuiltinsRISCV.inc" #include "clang/Basic/BuiltinsRISCV.inc"
+#undef GET_BUILTIN_ENUMERATORS
LastTSBuiltin LastTSBuiltin
}; };
} // namespace RISCV } // namespace RISCV
@@ -178,8 +208,16 @@ namespace clang {
namespace LoongArch { namespace LoongArch {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID,
-#include "clang/Basic/BuiltinsLoongArch.def"+#include "clang/Basic/BuiltinsLoongArchBase.def"
+ FirstLSXBuiltin,
+ LastBaseBuiltin = FirstLSXBuiltin - 1,
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID,
+#include "clang/Basic/BuiltinsLoongArchLSX.def"
+ FirstLASXBuiltin,
+ LastLSXBuiltin = FirstLASXBuiltin - 1,
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID,
+#include "clang/Basic/BuiltinsLoongArchLASX.def"
LastTSBuiltin LastTSBuiltin
}; };
} // namespace LoongArch } // namespace LoongArch
@@ -356,8 +394,9 @@ namespace clang {
namespace Hexagon { namespace Hexagon {
enum { enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
-#define BUILTIN(ID, TYPE, ATTRS) BI##ID,+#define GET_BUILTIN_ENUMERATORS
#include "clang/Basic/BuiltinsHexagon.inc" #include "clang/Basic/BuiltinsHexagon.inc"
+#undef GET_BUILTIN_ENUMERATORS
LastTSBuiltin LastTSBuiltin
}; };
} }
clang/include/clang/Basic/TargetInfo.h
@@ -16,6 +16,7 @@
#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/BitmaskEnum.h" #include "clang/Basic/BitmaskEnum.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/CFProtectionOptions.h" #include "clang/Basic/CFProtectionOptions.h"
#include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LLVM.h" #include "clang/Basic/LLVM.h"
@@ -32,6 +33,7 @@
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringTable.h"
#include "llvm/Frontend/OpenMP/OMPGridValues.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h"
#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
@@ -1016,10 +1018,10 @@ public:
virtual void getTargetDefines(const LangOptions &Opts, virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const = 0; MacroBuilder &Builder) const = 0;
- /// Return information about target-specific builtins for+ /// Return information about target-specific builtins for the current primary
- /// the current primary target, and info about which builtins are non-portable+ /// target, and info about which builtins are non-portable across the current
- /// across the current set of primary and secondary targets.+ /// set of primary and secondary targets.
- virtual ArrayRef<Builtin::Info> getTargetBuiltins() const = 0;+ virtual llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const = 0;
/// Returns target-specific min and max values VScale_Range. /// Returns target-specific min and max values VScale_Range.
virtual std::optional<std::pair<unsigned, unsigned>> virtual std::optional<std::pair<unsigned, unsigned>>
@@ -1469,6 +1471,7 @@ public:
/// specification /// specification
virtual bool validateBranchProtection(StringRef Spec, StringRef Arch, virtual bool validateBranchProtection(StringRef Spec, StringRef Arch,
BranchProtectionInfo &BPI, BranchProtectionInfo &BPI,
+ const LangOptions &LO,
StringRef &Err) const { StringRef &Err) const {
Err = ""; Err = "";
return false; return false;
@@ -1659,7 +1662,7 @@ public:
// access target-specific GPU grid values that must be consistent between // access target-specific GPU grid values that must be consistent between
// host RTL (plugin), deviceRTL and clang. // host RTL (plugin), deviceRTL and clang.
virtual const llvm::omp::GV &getGridValue() const { virtual const llvm::omp::GV &getGridValue() const {
- llvm_unreachable("getGridValue not implemented on this target");+ return llvm::omp::SPIRVGridValues;
} }
/// Retrieve the name of the platform as it is used in the /// Retrieve the name of the platform as it is used in the
clang/include/clang/Basic/TokenKinds.def
@@ -546,7 +546,6 @@ TYPE_TRAIT_1(__is_trivially_equality_comparable, IsTriviallyEqualityComparable,
TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX) TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX)
TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX) TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX)
TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX) TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX)
-TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX)
TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX)
TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX)
clang/include/clang/Basic/arm_sme.td
@@ -110,11 +110,11 @@ multiclass ZARead<string n_suffix, string t, string i_prefix, list<ImmCheck> ch>
} }
} }
-defm SVREAD_ZA8 : ZARead<"za8", "cUc", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_0>]>;+defm SVREAD_ZA8 : ZARead<"za8", "cUcm", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_0>]>;
defm SVREAD_ZA16 : ZARead<"za16", "sUshb", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_1>]>; defm SVREAD_ZA16 : ZARead<"za16", "sUshb", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_1>]>;
defm SVREAD_ZA32 : ZARead<"za32", "iUif", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_3>]>; defm SVREAD_ZA32 : ZARead<"za32", "iUif", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_3>]>;
defm SVREAD_ZA64 : ZARead<"za64", "lUld", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_7>]>; defm SVREAD_ZA64 : ZARead<"za64", "lUld", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_7>]>;
-defm SVREAD_ZA128 : ZARead<"za128", "csilUcUsUiUlhbfd", "aarch64_sme_readq", [ImmCheck<2, ImmCheck0_15>]>;+defm SVREAD_ZA128 : ZARead<"za128", "csilUcUsUiUlmhbfd", "aarch64_sme_readq", [ImmCheck<2, ImmCheck0_15>]>;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Write horizontal/vertical ZA slices // Write horizontal/vertical ZA slices
@@ -131,11 +131,11 @@ multiclass ZAWrite<string n_suffix, string t, string i_prefix, list<ImmCheck> ch
} }
} }
-defm SVWRITE_ZA8 : ZAWrite<"za8", "cUc", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_0>]>;+defm SVWRITE_ZA8 : ZAWrite<"za8", "cUcm", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_0>]>;
defm SVWRITE_ZA16 : ZAWrite<"za16", "sUshb", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_1>]>; defm SVWRITE_ZA16 : ZAWrite<"za16", "sUshb", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_1>]>;
defm SVWRITE_ZA32 : ZAWrite<"za32", "iUif", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_3>]>; defm SVWRITE_ZA32 : ZAWrite<"za32", "iUif", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_3>]>;
defm SVWRITE_ZA64 : ZAWrite<"za64", "lUld", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_7>]>; defm SVWRITE_ZA64 : ZAWrite<"za64", "lUld", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_7>]>;
-defm SVWRITE_ZA128 : ZAWrite<"za128", "csilUcUsUiUlhbfd", "aarch64_sme_writeq", [ImmCheck<0, ImmCheck0_15>]>;+defm SVWRITE_ZA128 : ZAWrite<"za128", "csilUcUsUiUlmhbfd", "aarch64_sme_writeq", [ImmCheck<0, ImmCheck0_15>]>;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SME - Zero // SME - Zero
@@ -350,7 +350,7 @@ multiclass ZAWrite_VG<string n, string t, string i, list<ImmCheck> checks> {
} }
let SMETargetGuard = "sme2" in { let SMETargetGuard = "sme2" in {
- defm SVWRITE_ZA8 : ZAWrite_VG<"za8", "cUc", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_0>]>;+ defm SVWRITE_ZA8 : ZAWrite_VG<"za8", "cUcm", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_0>]>;
defm SVWRITE_ZA16 : ZAWrite_VG<"za16", "sUshb", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_1>]>; defm SVWRITE_ZA16 : ZAWrite_VG<"za16", "sUshb", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_1>]>;
defm SVWRITE_ZA32 : ZAWrite_VG<"za32", "iUif", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_3>]>; defm SVWRITE_ZA32 : ZAWrite_VG<"za32", "iUif", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_3>]>;
defm SVWRITE_ZA64 : ZAWrite_VG<"za64", "lUld", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_7>]>; defm SVWRITE_ZA64 : ZAWrite_VG<"za64", "lUld", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_7>]>;
@@ -366,7 +366,7 @@ multiclass ZARead_VG<string n, string t, string i, list<ImmCheck> checks> {
} }
let SMETargetGuard = "sme2" in { let SMETargetGuard = "sme2" in {
- defm SVREAD_ZA8 : ZARead_VG<"za8", "cUc", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_0>]>;+ defm SVREAD_ZA8 : ZARead_VG<"za8", "cUcm", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREAD_ZA16 : ZARead_VG<"za16", "sUshb", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_1>]>; defm SVREAD_ZA16 : ZARead_VG<"za16", "sUshb", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREAD_ZA32 : ZARead_VG<"za32", "iUif", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_3>]>; defm SVREAD_ZA32 : ZARead_VG<"za32", "iUif", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREAD_ZA64 : ZARead_VG<"za64", "lUld", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_7>]>; defm SVREAD_ZA64 : ZARead_VG<"za64", "lUld", "aarch64_sme_read", [ImmCheck<0, ImmCheck0_7>]>;
@@ -722,7 +722,7 @@ def IN_STREAMING_MODE : Inst<"__arm_in_streaming_mode", "sv", "Pc", MergeNone,
// lookup table expand four contiguous registers // lookup table expand four contiguous registers
// //
let SMETargetGuard = "sme2" in { let SMETargetGuard = "sme2" in {
- def SVLUTI2_LANE_ZT_X4 : Inst<"svluti2_lane_zt_{d}_x4", "4.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;+ def SVLUTI2_LANE_ZT_X4 : Inst<"svluti2_lane_zt_{d}_x4", "4.di[i", "cUcsUsiUimbhf", MergeNone, "aarch64_sme_luti2_lane_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;
def SVLUTI4_LANE_ZT_X4 : Inst<"svluti4_lane_zt_{d}_x4", "4.di[i", "sUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_1>]>; def SVLUTI4_LANE_ZT_X4 : Inst<"svluti4_lane_zt_{d}_x4", "4.di[i", "sUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_1>]>;
} }
@@ -730,16 +730,16 @@ let SMETargetGuard = "sme2" in {
// lookup table expand one register // lookup table expand one register
// //
let SMETargetGuard = "sme2" in { let SMETargetGuard = "sme2" in {
- def SVLUTI2_LANE_ZT : Inst<"svluti2_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>;+ def SVLUTI2_LANE_ZT : Inst<"svluti2_lane_zt_{d}", "di[i", "cUcsUsiUimbhf", MergeNone, "aarch64_sme_luti2_lane_zt", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>;
- def SVLUTI4_LANE_ZT : Inst<"svluti4_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;+ def SVLUTI4_LANE_ZT : Inst<"svluti4_lane_zt_{d}", "di[i", "cUcsUsiUimbhf", MergeNone, "aarch64_sme_luti4_lane_zt", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;
} }
// //
// lookup table expand two contiguous registers // lookup table expand two contiguous registers
// //
let SMETargetGuard = "sme2" in { let SMETargetGuard = "sme2" in {
- def SVLUTI2_LANE_ZT_X2 : Inst<"svluti2_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;+ def SVLUTI2_LANE_ZT_X2 : Inst<"svluti2_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUimbhf", MergeNone, "aarch64_sme_luti2_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;
- def SVLUTI4_LANE_ZT_X2 : Inst<"svluti4_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;+ def SVLUTI4_LANE_ZT_X2 : Inst<"svluti4_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUimbhf", MergeNone, "aarch64_sme_luti4_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;
} }
// //
@@ -748,30 +748,30 @@ let SMETargetGuard = "sme2" in {
// FDOT // FDOT
let SMETargetGuard = "sme-f8f32" in { let SMETargetGuard = "sme-f8f32" in {
- def SVDOT_LANE_FP8_ZA32_VG1x2 : Inst<"svdot_lane_za32[_mf8]_vg1x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_3>]>;+ def SVDOT_LANE_FP8_ZA32_VG1x2 : Inst<"svdot_lane_za32[_mf8]_vg1x2", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_3>]>;
- def SVDOT_LANE_FP8_ZA32_VG1x4 : Inst<"svdot_lane_za32[_mf8]_vg1x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_3>]>;+ def SVDOT_LANE_FP8_ZA32_VG1x4 : Inst<"svdot_lane_za32[_mf8]_vg1x4", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_3>]>;
- def SVVDOTB_LANE_FP8_ZA32_VG1x4 : Inst<"svvdotb_lane_za32[_mf8]_vg1x4_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdotb_lane_za32_vg1x4", [IsOverloadNone, IsStreaming, IsInOutZA, SetsFPMR], [ImmCheck<3, ImmCheck0_3>]>;+ def SVVDOTB_LANE_FP8_ZA32_VG1x4 : Inst<"svvdotb_lane_za32[_mf8]_vg1x4", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdotb_lane_za32_vg1x4", [IsOverloadNone, IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
- def SVVDOTT_LANE_FP8_ZA32_VG1x4 : Inst<"svvdott_lane_za32[_mf8]_vg1x4_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdott_lane_za32_vg1x4", [IsOverloadNone, IsStreaming, IsInOutZA, SetsFPMR], [ImmCheck<3, ImmCheck0_3>]>;+ def SVVDOTT_LANE_FP8_ZA32_VG1x4 : Inst<"svvdott_lane_za32[_mf8]_vg1x4", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdott_lane_za32_vg1x4", [IsOverloadNone, IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
- def SVDOT_SINGLE_FP8_ZA32_VG1x2 : Inst<"svdot[_single]_za32[_mf8]_vg1x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_SINGLE_FP8_ZA32_VG1x2 : Inst<"svdot[_single]_za32[_mf8]_vg1x2", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x2", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVDOT_SINGLE_FP8_ZA32_VG1x4 : Inst<"svdot[_single]_za32[_mf8]_vg1x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_SINGLE_FP8_ZA32_VG1x4 : Inst<"svdot[_single]_za32[_mf8]_vg1x4", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x4", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVDOT_MULTI_FP8_ZA32_VG1x2 : Inst<"svdot_za32[_mf8]_vg1x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_MULTI_FP8_ZA32_VG1x2 : Inst<"svdot_za32[_mf8]_vg1x2", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x2", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVDOT_MULTI_FP8_ZA32_VG1x4 : Inst<"svdot_za32[_mf8]_vg1x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_MULTI_FP8_ZA32_VG1x4 : Inst<"svdot_za32[_mf8]_vg1x4", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x4", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
} }
let SMETargetGuard = "sme-f8f16" in { let SMETargetGuard = "sme-f8f16" in {
- def SVDOT_LANE_FP8_ZA16_VG1x2 : Inst<"svdot_lane_za16[_mf8]_vg1x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>;+ def SVDOT_LANE_FP8_ZA16_VG1x2 : Inst<"svdot_lane_za16[_mf8]_vg1x2", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x2", [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>;
- def SVDOT_LANE_FP8_ZA16_VG1x4 : Inst<"svdot_lane_za16[_mf8]_vg1x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>;+ def SVDOT_LANE_FP8_ZA16_VG1x4 : Inst<"svdot_lane_za16[_mf8]_vg1x4", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x4", [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>;
- def SVVDOT_LANE_FP8_ZA16_VG1x2 : Inst<"svvdot_lane_za16[_mf8]_vg1x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdot_lane_za16_vg1x2", [IsOverloadNone, IsStreaming, IsInOutZA, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>;+ def SVVDOT_LANE_FP8_ZA16_VG1x2 : Inst<"svvdot_lane_za16[_mf8]_vg1x2", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fvdot_lane_za16_vg1x2", [IsOverloadNone, IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
- def SVDOT_SINGLE_FP8_ZA16_VG1x2 : Inst<"svdot[_single]_za16[_mf8]_vg1x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_SINGLE_FP8_ZA16_VG1x2 : Inst<"svdot[_single]_za16[_mf8]_vg1x2", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x2", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVDOT_SINGLE_FP8_ZA16_VG1x4 : Inst<"svdot[_single]_za16[_mf8]_vg1x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_SINGLE_FP8_ZA16_VG1x4 : Inst<"svdot[_single]_za16[_mf8]_vg1x4", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x4", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVDOT_MULTI_FP8_ZA16_VG1x2 : Inst<"svdot_za16[_mf8]_vg1x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_MULTI_FP8_ZA16_VG1x2 : Inst<"svdot_za16[_mf8]_vg1x2", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x2", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVDOT_MULTI_FP8_ZA16_VG1x4 : Inst<"svdot_za16[_mf8]_vg1x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ def SVDOT_MULTI_FP8_ZA16_VG1x4 : Inst<"svdot_za16[_mf8]_vg1x4", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x4", [IsStreaming, IsInOutZA, IsOverloadNone], []>;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -811,12 +811,12 @@ multiclass ZAReadz<string n_suffix, string vg_num, string t, string i_prefix, li
} }
} }
-defm SVREADZ_ZA8_X2 : ZAReadz<"za8", "2", "cUc", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;+defm SVREADZ_ZA8_X2 : ZAReadz<"za8", "2", "cUcm", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREADZ_ZA16_X2 : ZAReadz<"za16", "2", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>; defm SVREADZ_ZA16_X2 : ZAReadz<"za16", "2", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREADZ_ZA32_X2 : ZAReadz<"za32", "2", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>; defm SVREADZ_ZA32_X2 : ZAReadz<"za32", "2", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64_X2 : ZAReadz<"za64", "2", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>; defm SVREADZ_ZA64_X2 : ZAReadz<"za64", "2", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;
-defm SVREADZ_ZA8_X4 : ZAReadz<"za8", "4", "cUc", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;+defm SVREADZ_ZA8_X4 : ZAReadz<"za8", "4", "cUcm", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREADZ_ZA16_X4 : ZAReadz<"za16", "4", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>; defm SVREADZ_ZA16_X4 : ZAReadz<"za16", "4", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREADZ_ZA32_X4 : ZAReadz<"za32", "4", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>; defm SVREADZ_ZA32_X4 : ZAReadz<"za32", "4", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64_X4 : ZAReadz<"za64", "4", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>; defm SVREADZ_ZA64_X4 : ZAReadz<"za64", "4", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;
@@ -834,15 +834,15 @@ multiclass ZAReadzSingle<string n_suffix, string t, string i_prefix, list<ImmChe
} }
} }
-defm SVREADZ_ZA8 : ZAReadzSingle<"za8", "cUc", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;+defm SVREADZ_ZA8 : ZAReadzSingle<"za8", "cUcm", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_0>]>;
defm SVREADZ_ZA16 : ZAReadzSingle<"za16", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>; defm SVREADZ_ZA16 : ZAReadzSingle<"za16", "sUshb", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_1>]>;
defm SVREADZ_ZA32 : ZAReadzSingle<"za32", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>; defm SVREADZ_ZA32 : ZAReadzSingle<"za32", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64 : ZAReadzSingle<"za64", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>; defm SVREADZ_ZA64 : ZAReadzSingle<"za64", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;
-defm SVREADZ_ZA128 : ZAReadzSingle<"za128", "csilUcUiUsUlbhfd", "aarch64_sme_readz_q", [ImmCheck<0, ImmCheck0_15>]>;+defm SVREADZ_ZA128 : ZAReadzSingle<"za128", "csilUcUiUsUlmbhfd", "aarch64_sme_readz_q", [ImmCheck<0, ImmCheck0_15>]>;
multiclass ZAReadzArray<string vg_num>{ multiclass ZAReadzArray<string vg_num>{
let SMETargetGuard = "sme2p1" in { let SMETargetGuard = "sme2p1" in {
- def NAME # _B : SInst<"svreadz_za8_{d}_vg1x" # vg_num, vg_num # "m", "cUc", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;+ def NAME # _B : SInst<"svreadz_za8_{d}_vg1x" # vg_num, vg_num # "m", "cUcm", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
def NAME # _H : SInst<"svreadz_za16_{d}_vg1x" # vg_num, vg_num # "m", "sUsbh", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>; def NAME # _H : SInst<"svreadz_za16_{d}_vg1x" # vg_num, vg_num # "m", "sUsbh", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
def NAME # _S : SInst<"svreadz_za32_{d}_vg1x" # vg_num, vg_num # "m", "iUif", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>; def NAME # _S : SInst<"svreadz_za32_{d}_vg1x" # vg_num, vg_num # "m", "iUif", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
def NAME # _D : SInst<"svreadz_za64_{d}_vg1x" # vg_num, vg_num # "m", "lUld", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>; def NAME # _D : SInst<"svreadz_za64_{d}_vg1x" # vg_num, vg_num # "m", "lUld", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
@@ -859,51 +859,51 @@ let SMETargetGuard = "sme-lutv2" in {
} }
let SMETargetGuard = "sme-f8f32" in { let SMETargetGuard = "sme-f8f32" in {
- def SVMOPA_FP8_ZA32 : Inst<"svmopa_za32[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za32",+ def SVMOPA_FP8_ZA32 : Inst<"svmopa_za32[_mf8]_m", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za32",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>;
// FMLALL (indexed) // FMLALL (indexed)
- def SVMLA_FP8_LANE_ZA32_VG4x1 : Inst<"svmla_lane_za32[_mf8]_vg4x1_fpm", "vmddi>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x1",+ def SVMLA_FP8_LANE_ZA32_VG4x1 : Inst<"svmla_lane_za32[_mf8]_vg4x1", "vmddi>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x1",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
- def SVMLA_FP8_LANE_ZA32_VG4x2 : Inst<"svmla_lane_za32[_mf8]_vg4x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x2",+ def SVMLA_FP8_LANE_ZA32_VG4x2 : Inst<"svmla_lane_za32[_mf8]_vg4x2", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x2",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
- def SVMLA_FP8_LANE_ZA16_VG4x4 : Inst<"svmla_lane_za32[_mf8]_vg4x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x4",+ def SVMLA_FP8_LANE_ZA16_VG4x4 : Inst<"svmla_lane_za32[_mf8]_vg4x4", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fmlall_lane_za32_vg4x4",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
// FMLALL (single) // FMLALL (single)
- def SVMLA_FP8_SINGLE_ZA32_VG4x1 : Inst<"svmla[_single]_za32[_mf8]_vg4x1_fpm", "vmdd>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x1",+ def SVMLA_FP8_SINGLE_ZA32_VG4x1 : Inst<"svmla[_single]_za32[_mf8]_vg4x1", "vmdd>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x1",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVMLA_FP8_SINGLE_ZA32_VG4x2 : Inst<"svmla[_single]_za32[_mf8]_vg4x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x2",+ def SVMLA_FP8_SINGLE_ZA32_VG4x2 : Inst<"svmla[_single]_za32[_mf8]_vg4x2", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x2",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVMLA_FP8_SINGLE_ZA32_VG4x4 : Inst<"svmla[_single]_za32[_mf8]_vg4x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x4",+ def SVMLA_FP8_SINGLE_ZA32_VG4x4 : Inst<"svmla[_single]_za32[_mf8]_vg4x4", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x4",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
// FMLALL (multiple) // FMLALL (multiple)
- def SVMLA_FP8_MULTI_ZA32_VG4x2 : Inst<"svmla_za32[_mf8]_vg4x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x2",+ def SVMLA_FP8_MULTI_ZA32_VG4x2 : Inst<"svmla_za32[_mf8]_vg4x2", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x2",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVMLA_FP8_MULTI_ZA32_VG4x4 : Inst<"svmla_za32[_mf8]_vg4x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x4",+ def SVMLA_FP8_MULTI_ZA32_VG4x4 : Inst<"svmla_za32[_mf8]_vg4x4", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x4",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
} }
let SMETargetGuard = "sme-f8f16" in { let SMETargetGuard = "sme-f8f16" in {
- def SVMOPA_FP8_ZA16 : Inst<"svmopa_za16[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za16",+ def SVMOPA_FP8_ZA16 : Inst<"svmopa_za16[_mf8]_m", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za16",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>;
// FMLAL (indexed) // FMLAL (indexed)
- def SVMLA_FP8_LANE_ZA16_VG2x1 : Inst<"svmla_lane_za16[_mf8]_vg2x1_fpm", "vmddi>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x1",+ def SVMLA_FP8_LANE_ZA16_VG2x1 : Inst<"svmla_lane_za16[_mf8]_vg2x1", "vmddi>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x1",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
- def SVMLA_FP8_LANE_ZA16_VG2x2 : Inst<"svmla_lane_za16[_mf8]_vg2x2_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x2",+ def SVMLA_FP8_LANE_ZA16_VG2x2 : Inst<"svmla_lane_za16[_mf8]_vg2x2", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x2",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
- def SVMLA_FP8_LANE_ZA16_VG2x4 : Inst<"svmla_lane_za16[_mf8]_vg2x4_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x4",+ def SVMLA_FP8_LANE_ZA16_VG2x4 : Inst<"svmla_lane_za16[_mf8]_vg2x4", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fmlal_lane_za16_vg2x4",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;+ [IsStreaming, IsInOutZA, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
// FMLAL (single) // FMLAL (single)
- def SVMLA_FP8_SINGLE_ZA16_VG2x1 : Inst<"svmla[_single]_za16[_mf8]_vg2x1_fpm", "vmdd>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x1",+ def SVMLA_FP8_SINGLE_ZA16_VG2x1 : Inst<"svmla[_single]_za16[_mf8]_vg2x1", "vmdd>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x1",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVMLA_FP8_SINGLE_ZA16_VG2x2 : Inst<"svmla[_single]_za16[_mf8]_vg2x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x2",+ def SVMLA_FP8_SINGLE_ZA16_VG2x2 : Inst<"svmla[_single]_za16[_mf8]_vg2x2", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x2",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVMLA_FP8_SINGLE_ZA16_VG2x4 : Inst<"svmla[_single]_za16[_mf8]_vg2x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x4",+ def SVMLA_FP8_SINGLE_ZA16_VG2x4 : Inst<"svmla[_single]_za16[_mf8]_vg2x4", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x4",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
// FMLAL (multiple) // FMLAL (multiple)
- def SVMLA_FP8_MULTI_ZA16_VG2x2 : Inst<"svmla_za16[_mf8]_vg2x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x2",+ def SVMLA_FP8_MULTI_ZA16_VG2x2 : Inst<"svmla_za16[_mf8]_vg2x2", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x2",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
- def SVMLA_FP8_MULTI_ZA16_VG2x4 : Inst<"svmla_za16[_mf8]_vg2x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x4",+ def SVMLA_FP8_MULTI_ZA16_VG2x4 : Inst<"svmla_za16[_mf8]_vg2x4", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x4",
- [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;+ [IsStreaming, IsInOutZA, IsOverloadNone], []>;
} }
} // let SVETargetGuard = InvalidMode } // let SVETargetGuard = InvalidMode
clang/include/clang/Basic/arm_sve.td
@@ -2104,7 +2104,7 @@ let SVETargetGuard = "sve2p1", SMETargetGuard = "sme" in {
def SVSCLAMP : SInst<"svclamp[_{d}]", "dddd", "csil", MergeNone, "aarch64_sve_sclamp", [VerifyRuntimeMode], []>; def SVSCLAMP : SInst<"svclamp[_{d}]", "dddd", "csil", MergeNone, "aarch64_sve_sclamp", [VerifyRuntimeMode], []>;
def SVUCLAMP : SInst<"svclamp[_{d}]", "dddd", "UcUsUiUl", MergeNone, "aarch64_sve_uclamp", [VerifyRuntimeMode], []>; def SVUCLAMP : SInst<"svclamp[_{d}]", "dddd", "UcUsUiUl", MergeNone, "aarch64_sve_uclamp", [VerifyRuntimeMode], []>;
-defm SVREVD : SInstZPZ<"svrevd", "csilUcUsUiUlbhfd", "aarch64_sve_revd">;+defm SVREVD : SInstZPZ<"svrevd", "csilUcUsUiUlmbhfd", "aarch64_sve_revd">;
} }
let SVETargetGuard = "sve2p1", SMETargetGuard = "sme2" in { let SVETargetGuard = "sve2p1", SMETargetGuard = "sme2" in {
@@ -2223,8 +2223,8 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2" in {
def SVADD_SINGLE_X4 : SInst<"svadd[_single_{d}_x4]", "44d", "cUcsUsiUilUl", MergeNone, "aarch64_sve_add_single_x4", [IsStreaming], []>; def SVADD_SINGLE_X4 : SInst<"svadd[_single_{d}_x4]", "44d", "cUcsUsiUilUl", MergeNone, "aarch64_sve_add_single_x4", [IsStreaming], []>;
// 2-way and 4-way selects // 2-way and 4-way selects
- def SVSEL_X2 : SInst<"svsel[_{d}_x2]", "2}22", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_sel_x2", [IsStreaming], []>;+ def SVSEL_X2 : SInst<"svsel[_{d}_x2]", "2}22", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_sel_x2", [IsStreaming], []>;
- def SVSEL_X4 : SInst<"svsel[_{d}_x4]", "4}44", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_sel_x4", [IsStreaming], []>;+ def SVSEL_X4 : SInst<"svsel[_{d}_x4]", "4}44", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_sel_x4", [IsStreaming], []>;
// SRSHL / URSHL // SRSHL / URSHL
def SVSRSHL_SINGLE_X2 : SInst<"svrshl[_single_{d}_x2]", "22d", "csil", MergeNone, "aarch64_sve_srshl_single_x2", [IsStreaming], []>; def SVSRSHL_SINGLE_X2 : SInst<"svrshl[_single_{d}_x2]", "22d", "csil", MergeNone, "aarch64_sve_srshl_single_x2", [IsStreaming], []>;
@@ -2402,15 +2402,15 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2" in {
// //
let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2" in { let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2" in {
- def SVZIP_X2 : SInst<"svzip[_{d}_x2]", "22", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_zip_x2", [IsStreaming], []>;+ def SVZIP_X2 : SInst<"svzip[_{d}_x2]", "22", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_zip_x2", [IsStreaming], []>;
- def SVZIPQ_X2 : SInst<"svzipq[_{d}_x2]", "22", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_zipq_x2", [IsStreaming], []>;+ def SVZIPQ_X2 : SInst<"svzipq[_{d}_x2]", "22", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_zipq_x2", [IsStreaming], []>;
- def SVZIP_X4 : SInst<"svzip[_{d}_x4]", "44", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_zip_x4", [IsStreaming], []>;+ def SVZIP_X4 : SInst<"svzip[_{d}_x4]", "44", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_zip_x4", [IsStreaming], []>;
- def SVZIPQ_X4 : SInst<"svzipq[_{d}_x4]", "44", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_zipq_x4", [IsStreaming], []>;+ def SVZIPQ_X4 : SInst<"svzipq[_{d}_x4]", "44", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_zipq_x4", [IsStreaming], []>;
- def SVUZP_X2 : SInst<"svuzp[_{d}_x2]", "22", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_uzp_x2", [IsStreaming], []>;+ def SVUZP_X2 : SInst<"svuzp[_{d}_x2]", "22", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_uzp_x2", [IsStreaming], []>;
- def SVUZPQ_X2 : SInst<"svuzpq[_{d}_x2]", "22", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_uzpq_x2", [IsStreaming], []>;+ def SVUZPQ_X2 : SInst<"svuzpq[_{d}_x2]", "22", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_uzpq_x2", [IsStreaming], []>;
- def SVUZP_X4 : SInst<"svuzp[_{d}_x4]", "44", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_uzp_x4", [IsStreaming], []>;+ def SVUZP_X4 : SInst<"svuzp[_{d}_x4]", "44", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_uzp_x4", [IsStreaming], []>;
- def SVUZPQ_X4 : SInst<"svuzpq[_{d}_x4]", "44", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_uzpq_x4", [IsStreaming], []>;+ def SVUZPQ_X4 : SInst<"svuzpq[_{d}_x4]", "44", "cUcsUsiUilUlmbhfd", MergeNone, "aarch64_sve_uzpq_x4", [IsStreaming], []>;
} }
// //
@@ -2432,18 +2432,18 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2,fp8" in {
def FSCALE_X4 : Inst<"svscale[_{d}_x4]", "444.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x4", [IsStreaming],[]>; def FSCALE_X4 : Inst<"svscale[_{d}_x4]", "444.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x4", [IsStreaming],[]>;
// Convert from FP8 to half-precision/BFloat16 multi-vector // Convert from FP8 to half-precision/BFloat16 multi-vector
- def SVF1CVT_X2 : Inst<"svcvt1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1_x2", [IsStreaming, SetsFPMR], []>;+ def SVF1CVT_X2 : Inst<"svcvt1_{d}[_mf8]_x2", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1_x2", [IsStreaming], []>;
- def SVF2CVT_X2 : Inst<"svcvt2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2_x2", [IsStreaming, SetsFPMR], []>;+ def SVF2CVT_X2 : Inst<"svcvt2_{d}[_mf8]_x2", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2_x2", [IsStreaming], []>;
// Convert from FP8 to deinterleaved half-precision/BFloat16 multi-vector // Convert from FP8 to deinterleaved half-precision/BFloat16 multi-vector
- def SVF1CVTL_X2 : Inst<"svcvtl1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl1_x2", [IsStreaming, SetsFPMR], []>;+ def SVF1CVTL_X2 : Inst<"svcvtl1_{d}[_mf8]_x2", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl1_x2", [IsStreaming], []>;
- def SVF2CVTL_X2 : Inst<"svcvtl2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl2_x2", [IsStreaming, SetsFPMR], []>;+ def SVF2CVTL_X2 : Inst<"svcvtl2_{d}[_mf8]_x2", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl2_x2", [IsStreaming], []>;
// Convert from single/half/bfloat multivector to FP8 // Convert from single/half/bfloat multivector to FP8
- def SVFCVT_X2 : Inst<"svcvt_mf8[_{d}_x2]_fpm", "~2>", "bh", MergeNone, "aarch64_sve_fp8_cvt_x2", [IsStreaming, SetsFPMR], []>;+ def SVFCVT_X2 : Inst<"svcvt_mf8[_{d}_x2]", "~2>", "bh", MergeNone, "aarch64_sve_fp8_cvt_x2", [IsStreaming], []>;
- def SVFCVT_X4 : Inst<"svcvt_mf8[_{d}_x4]_fpm", "~4>", "f", MergeNone, "aarch64_sve_fp8_cvt_x4", [IsOverloadNone, IsStreaming, SetsFPMR], []>;+ def SVFCVT_X4 : Inst<"svcvt_mf8[_{d}_x4]", "~4>", "f", MergeNone, "aarch64_sve_fp8_cvt_x4", [IsOverloadNone, IsStreaming], []>;
// interleaved // interleaved
- def SVFCVTN_X4 : Inst<"svcvtn_mf8[_{d}_x4]_fpm", "~4>", "f", MergeNone, "aarch64_sve_fp8_cvtn_x4", [IsOverloadNone, IsStreaming, SetsFPMR], []>;+ def SVFCVTN_X4 : Inst<"svcvtn_mf8[_{d}_x4]", "~4>", "f", MergeNone, "aarch64_sve_fp8_cvtn_x4", [IsOverloadNone, IsStreaming], []>;
} }
let SVETargetGuard = "sve2p1", SMETargetGuard = "sme2" in { let SVETargetGuard = "sve2p1", SMETargetGuard = "sme2" in {
@@ -2464,67 +2464,67 @@ let SVETargetGuard = "sve2,fp8", SMETargetGuard = "sme2,fp8" in {
// SVE FP8 widening conversions // SVE FP8 widening conversions
// 8-bit floating-point convert to BFloat16/Float16 // 8-bit floating-point convert to BFloat16/Float16
- def SVF1CVT : SInst<"svcvt1_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1", [VerifyRuntimeMode, SetsFPMR]>;+ def SVF1CVT : SInst<"svcvt1_{d}[_mf8]", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1", [VerifyRuntimeMode]>;
- def SVF2CVT : SInst<"svcvt2_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2", [VerifyRuntimeMode, SetsFPMR]>;+ def SVF2CVT : SInst<"svcvt2_{d}[_mf8]", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2", [VerifyRuntimeMode]>;
// 8-bit floating-point convert to BFloat16/Float16 (top) // 8-bit floating-point convert to BFloat16/Float16 (top)
- def SVF1CVTLT : SInst<"svcvtlt1_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvtlt1", [VerifyRuntimeMode, SetsFPMR]>;+ def SVF1CVTLT : SInst<"svcvtlt1_{d}[_mf8]", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvtlt1", [VerifyRuntimeMode]>;
- def SVF2CVTLT : SInst<"svcvtlt2_{d}[_mf8]_fpm", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvtlt2", [VerifyRuntimeMode, SetsFPMR]>;+ def SVF2CVTLT : SInst<"svcvtlt2_{d}[_mf8]", "d~>", "bh", MergeNone, "aarch64_sve_fp8_cvtlt2", [VerifyRuntimeMode]>;
// BFloat16/Float16 convert, narrow and interleave to 8-bit floating-point // BFloat16/Float16 convert, narrow and interleave to 8-bit floating-point
- def SVFCVTN : SInst<"svcvtn_mf8[_{d}_x2]_fpm", "~2>", "bh", MergeNone, "aarch64_sve_fp8_cvtn", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFCVTN : SInst<"svcvtn_mf8[_{d}_x2]", "~2>", "bh", MergeNone, "aarch64_sve_fp8_cvtn", [VerifyRuntimeMode]>;
// Single-precision convert, narrow and interleave to 8-bit floating-point (top and bottom) // Single-precision convert, narrow and interleave to 8-bit floating-point (top and bottom)
- def SVFCVTNB : SInst<"svcvtnb_mf8[_f32_x2]_fpm", "~2>", "f", MergeNone, "aarch64_sve_fp8_cvtnb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFCVTNB : SInst<"svcvtnb_mf8[_f32_x2]", "~2>", "f", MergeNone, "aarch64_sve_fp8_cvtnb", [VerifyRuntimeMode]>;
- def SVFCVTNT : SInst<"svcvtnt_mf8[_f32_x2]_fpm", "~~2>", "f", MergeNone, "aarch64_sve_fp8_cvtnt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFCVTNT : SInst<"svcvtnt_mf8[_f32_x2]", "~~2>", "f", MergeNone, "aarch64_sve_fp8_cvtnt", [VerifyRuntimeMode]>;
} }
let SVETargetGuard = "sve2,fp8dot2", SMETargetGuard ="sme,ssve-fp8dot2" in { let SVETargetGuard = "sve2,fp8dot2", SMETargetGuard ="sme,ssve-fp8dot2" in {
// 8-bit floating-point dot product to half-precision (vectors) // 8-bit floating-point dot product to half-precision (vectors)
- def SVFDOT_2WAY : SInst<"svdot[_f16_mf8]_fpm", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFDOT_2WAY : SInst<"svdot[_f16_mf8]", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode]>;
- def SVFDOT_N_2WAY : SInst<"svdot[_n_f16_mf8]_fpm", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFDOT_N_2WAY : SInst<"svdot[_n_f16_mf8]", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode]>;
// 8-bit floating-point dot product to half-precision (indexed) // 8-bit floating-point dot product to half-precision (indexed)
- def SVFDOT_LANE_2WAY : SInst<"svdot_lane[_f16_mf8]_fpm", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fdot_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>;+ def SVFDOT_LANE_2WAY : SInst<"svdot_lane[_f16_mf8]", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fdot_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_7>]>;
} }
let SVETargetGuard = "sve2,fp8dot4", SMETargetGuard ="sme,ssve-fp8dot4" in { let SVETargetGuard = "sve2,fp8dot4", SMETargetGuard ="sme,ssve-fp8dot4" in {
// 8-bit floating-point dot product to single-precision (vectors) // 8-bit floating-point dot product to single-precision (vectors)
- def SVFDOT_4WAY : SInst<"svdot[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFDOT_4WAY : SInst<"svdot[_f32_mf8]", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode]>;
- def SVFDOT_N_4WAY : SInst<"svdot[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFDOT_N_4WAY : SInst<"svdot[_n_f32_mf8]", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fdot", [VerifyRuntimeMode]>;
// 8-bit floating-point dot product to single-precision (indexed) // 8-bit floating-point dot product to single-precision (indexed)
- def SVFDOT_LANE_4WAY : SInst<"svdot_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fdot_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_3>]>;+ def SVFDOT_LANE_4WAY : SInst<"svdot_lane[_f32_mf8]", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fdot_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_3>]>;
} }
let SVETargetGuard = "sve2,fp8fma", SMETargetGuard = "sme,ssve-fp8fma" in { let SVETargetGuard = "sve2,fp8fma", SMETargetGuard = "sme,ssve-fp8fma" in {
// 8-bit floating-point multiply-add long to half-precision (bottom) // 8-bit floating-point multiply-add long to half-precision (bottom)
- def SVFMLALB : SInst<"svmlalb[_f16_mf8]_fpm", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fmlalb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALB : SInst<"svmlalb[_f16_mf8]", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fmlalb", [VerifyRuntimeMode]>;
- def SVFMLALB_N : SInst<"svmlalb[_n_f16_mf8]_fpm", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fmlalb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALB_N : SInst<"svmlalb[_n_f16_mf8]", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fmlalb", [VerifyRuntimeMode]>;
- // 8-bit floating-point multiply-add long to ha_fpmlf-precision (bottom, indexed)+ // 8-bit floating-point multiply-add long to half-precision (bottom, indexed)
- def SVFMLALB_LANE : SInst<"svmlalb_lane[_f16_mf8]_fpm", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fmlalb_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_15>]>;+ def SVFMLALB_LANE : SInst<"svmlalb_lane[_f16_mf8]", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fmlalb_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_15>]>;
// 8-bit floating-point multiply-add long to half-precision (top) // 8-bit floating-point multiply-add long to half-precision (top)
- def SVFMLALT : SInst<"svmlalt[_f16_mf8]_fpm", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fmlalt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALT : SInst<"svmlalt[_f16_mf8]", "dd~~>", "h", MergeNone, "aarch64_sve_fp8_fmlalt", [VerifyRuntimeMode]>;
- def SVFMLALT_N : SInst<"svmlalt[_n_f16_mf8]_fpm", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fmlalt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALT_N : SInst<"svmlalt[_n_f16_mf8]", "dd~!>", "h", MergeNone, "aarch64_sve_fp8_fmlalt", [VerifyRuntimeMode]>;
// 8-bit floating-point multiply-add long to half-precision (top, indexed) // 8-bit floating-point multiply-add long to half-precision (top, indexed)
- def SVFMLALT_LANE : SInst<"svmlalt_lane[_f16_mf8]_fpm", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fmlalt_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_15>]>;+ def SVFMLALT_LANE : SInst<"svmlalt_lane[_f16_mf8]", "dd~~i>", "h", MergeNone, "aarch64_sve_fp8_fmlalt_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_15>]>;
// 8-bit floating-point multiply-add long long to single-precision (all top/bottom variants) // 8-bit floating-point multiply-add long long to single-precision (all top/bottom variants)
- def SVFMLALLBB : SInst<"svmlallbb[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLBB : SInst<"svmlallbb[_f32_mf8]", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb", [VerifyRuntimeMode]>;
- def SVFMLALLBB_N : SInst<"svmlallbb[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLBB_N : SInst<"svmlallbb[_n_f32_mf8]", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb", [VerifyRuntimeMode]>;
- def SVFMLALLBT : SInst<"svmlallbt[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLBT : SInst<"svmlallbt[_f32_mf8]", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt", [VerifyRuntimeMode]>;
- def SVFMLALLBT_N : SInst<"svmlallbt[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLBT_N : SInst<"svmlallbt[_n_f32_mf8]", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt", [VerifyRuntimeMode]>;
- def SVFMLALLTB : SInst<"svmlalltb[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLTB : SInst<"svmlalltb[_f32_mf8]", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb", [VerifyRuntimeMode]>;
- def SVFMLALLTB_N : SInst<"svmlalltb[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLTB_N : SInst<"svmlalltb[_n_f32_mf8]", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb", [VerifyRuntimeMode]>;
- def SVFMLALLTT : SInst<"svmlalltt[_f32_mf8]_fpm", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLTT : SInst<"svmlalltt[_f32_mf8]", "dd~~>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt", [VerifyRuntimeMode]>;
- def SVFMLALLTT_N : SInst<"svmlalltt[_n_f32_mf8]_fpm", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt", [VerifyRuntimeMode, SetsFPMR]>;+ def SVFMLALLTT_N : SInst<"svmlalltt[_n_f32_mf8]", "dd~!>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt", [VerifyRuntimeMode]>;
// 8-bit floating-point multiply-add long long to single-precision (indexed, all top/bottom variants) // 8-bit floating-point multiply-add long long to single-precision (indexed, all top/bottom variants)
- def SVFMLALLBB_LANE : SInst<"svmlallbb_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>;+ def SVFMLALLBB_LANE : SInst<"svmlallbb_lane[_f32_mf8]", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlallbb_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_7>]>;
- def SVFMLALLBT_LANE : SInst<"svmlallbt_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>;+ def SVFMLALLBT_LANE : SInst<"svmlallbt_lane[_f32_mf8]", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlallbt_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_7>]>;
- def SVFMLALLTB_LANE : SInst<"svmlalltb_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>;+ def SVFMLALLTB_LANE : SInst<"svmlalltb_lane[_f32_mf8]", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlalltb_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_7>]>;
- def SVFMLALLTT_LANE : SInst<"svmlalltt_lane[_f32_mf8]_fpm", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt_lane", [VerifyRuntimeMode, SetsFPMR], [ImmCheck<3, ImmCheck0_7>]>;+ def SVFMLALLTT_LANE : SInst<"svmlalltt_lane[_f32_mf8]", "dd~~i>", "f", MergeNone, "aarch64_sve_fp8_fmlalltt_lane", [VerifyRuntimeMode], [ImmCheck<3, ImmCheck0_7>]>;
} }
clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h
@@ -0,0 +1,52 @@
+//===- CIRAttrVisitor.h - Visitor for CIR attributes ------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CirAttrVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H
+#define LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H
+
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
+
+namespace cir {
+
+template <typename ImplClass, typename RetTy> class CirAttrVisitor {
+public:
+ // FIXME: Create a TableGen list to automatically handle new attributes
+ RetTy visit(mlir::Attribute attr) {
+ if (const auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr))
+ return getImpl().visitCirIntAttr(intAttr);
+ if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(attr))
+ return getImpl().visitCirFPAttr(fltAttr);
+ if (const auto ptrAttr = mlir::dyn_cast<cir::ConstPtrAttr>(attr))
+ return getImpl().visitCirConstPtrAttr(ptrAttr);
+ llvm_unreachable("unhandled attribute type");
+ }
+
+ // If the implementation chooses not to implement a certain visit
+ // method, fall back to the parent.
+ RetTy visitCirIntAttr(cir::IntAttr attr) {
+ return getImpl().visitCirAttr(attr);
+ }
+ RetTy visitCirFPAttr(cir::FPAttr attr) {
+ return getImpl().visitCirAttr(attr);
+ }
+ RetTy visitCirConstPtrAttr(cir::ConstPtrAttr attr) {
+ return getImpl().visitCirAttr(attr);
+ }
+
+ RetTy visitCirAttr(mlir::Attribute attr) { return RetTy(); }
+
+ ImplClass &getImpl() { return *static_cast<ImplClass *>(this); }
+};
+
+} // namespace cir
+
+#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H
clang/include/clang/CIR/LowerToLLVM.h
@@ -12,8 +12,6 @@
#ifndef CLANG_CIR_LOWERTOLLVM_H #ifndef CLANG_CIR_LOWERTOLLVM_H
#define CLANG_CIR_LOWERTOLLVM_H #define CLANG_CIR_LOWERTOLLVM_H
-#include "mlir/Pass/Pass.h"
-
#include <memory> #include <memory>
namespace llvm { namespace llvm {
clang/include/clang/CIR/MissingFeatures.h
@@ -0,0 +1,43 @@
+//===---- MissingFeatures.h - Checks for unimplemented features -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file introduces some helper classes to guard against features that
+// CIR dialect supports that we do not have and also do not have great ways to
+// assert against.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_MISSINGFEATURES_H
+#define CLANG_CIR_MISSINGFEATURES_H
+
+namespace cir {
+
+// As a way to track features that haven't yet been implemented this class
+// explicitly contains a list of static fns that will return false that you
+// can guard against. If and when a feature becomes implemented simply changing
+// this return to true will cause compilation to fail at all the points in which
+// we noted that we needed to address. This is a much more explicit way to
+// handle "TODO"s.
+struct MissingFeatures {
+ // Address space related
+ static bool addressSpace() { return false; }
+
+ // This isn't needed until we add support for bools.
+ static bool convertTypeForMemory() { return false; }
+
+ // Unhandled global/linkage information.
+ static bool opGlobalDSOLocal() { return false; }
+ static bool opGlobalThreadLocal() { return false; }
+ static bool opGlobalConstant() { return false; }
+ static bool opGlobalAlignment() { return false; }
+ static bool opGlobalLinkage() { return false; }
+};
+
+} // namespace cir
+
+#endif // CLANG_CIR_MISSINGFEATURES_H
clang/include/clang/Driver/Driver.h
@@ -797,22 +797,14 @@ private:
const ToolChain &getToolChain(const llvm::opt::ArgList &Args, const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
const llvm::Triple &Target) const; const llvm::Triple &Target) const;
- /// @}+ /// Retrieves a ToolChain for a particular \p Target triple for offloading.
-
- /// Retrieves a ToolChain for a particular device \p Target triple
- ///
- /// \param[in] HostTC is the host ToolChain paired with the device
- ///
- /// \param[in] TargetDeviceOffloadKind (e.g. OFK_Cuda/OFK_OpenMP/OFK_SYCL) is
- /// an Offloading action that is optionally passed to a ToolChain (used by
- /// CUDA, to specify if it's used in conjunction with OpenMP)
/// ///
/// Will cache ToolChains for the life of the driver object, and create them /// Will cache ToolChains for the life of the driver object, and create them
/// on-demand. /// on-demand.
- const ToolChain &getOffloadingDeviceToolChain(+ const ToolChain &getOffloadToolChain(const llvm::opt::ArgList &Args,
- const llvm::opt::ArgList &Args, const llvm::Triple &Target,+ const Action::OffloadKind Kind,
- const ToolChain &HostTC,+ const llvm::Triple &Target,
- const Action::OffloadKind &TargetDeviceOffloadKind) const;+ const llvm::Triple &AuxTarget) const;
/// Get bitmasks for which option flags to include and exclude based on /// Get bitmasks for which option flags to include and exclude based on
/// the driver mode. /// the driver mode.
clang/include/clang/Driver/Options.td
@@ -932,7 +932,9 @@ def W_Joined : Joined<["-"], "W">, Group<W_Group>,
def Xanalyzer : Separate<["-"], "Xanalyzer">, def Xanalyzer : Separate<["-"], "Xanalyzer">,
HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">, HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">,
Group<StaticAnalyzer_Group>; Group<StaticAnalyzer_Group>;
-def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[NoXarchOption]>;+def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[NoXarchOption]>,
+ HelpText<"Pass <arg> to the compiliation if the target matches <arch>">,
+ MetaVarName<"<arch> <arg>">;
def Xarch_host : Separate<["-"], "Xarch_host">, Flags<[NoXarchOption]>, def Xarch_host : Separate<["-"], "Xarch_host">, Flags<[NoXarchOption]>,
HelpText<"Pass <arg> to the CUDA/HIP host compilation">, MetaVarName<"<arg>">; HelpText<"Pass <arg> to the CUDA/HIP host compilation">, MetaVarName<"<arg>">;
def Xarch_device : Separate<["-"], "Xarch_device">, Flags<[NoXarchOption]>, def Xarch_device : Separate<["-"], "Xarch_device">, Flags<[NoXarchOption]>,
@@ -1115,8 +1117,8 @@ def fno_convergent_functions : Flag<["-"], "fno-convergent-functions">,
// Common offloading options // Common offloading options
let Group = offload_Group in { let Group = offload_Group in {
-def offload_arch_EQ : Joined<["--"], "offload-arch=">, Flags<[NoXarchOption]>,+def offload_arch_EQ : Joined<["--"], "offload-arch=">,
- Visibility<[ClangOption, FlangOption]>,+ Visibility<[ClangOption, FlangOption]>, Flags<[NoXarchOption]>,
HelpText<"Specify an offloading device architecture for CUDA, HIP, or OpenMP. (e.g. sm_35). " HelpText<"Specify an offloading device architecture for CUDA, HIP, or OpenMP. (e.g. sm_35). "
"If 'native' is used the compiler will detect locally installed architectures. " "If 'native' is used the compiler will detect locally installed architectures. "
"For HIP offloading, the device architecture can be followed by target ID features " "For HIP offloading, the device architecture can be followed by target ID features "
@@ -1793,6 +1795,11 @@ def fprofile_update_EQ : Joined<["-"], "fprofile-update=">,
Values<"atomic,prefer-atomic,single">, Values<"atomic,prefer-atomic,single">,
MetaVarName<"<method>">, HelpText<"Set update method of profile counters">, MetaVarName<"<method>">, HelpText<"Set update method of profile counters">,
MarshallingInfoFlag<CodeGenOpts<"AtomicProfileUpdate">>; MarshallingInfoFlag<CodeGenOpts<"AtomicProfileUpdate">>;
+def fprofile_continuous : Flag<["-"], "fprofile-continuous">,
+ Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Enable continuous instrumentation profiling mode">,
+ MarshallingInfoFlag<CodeGenOpts<"ContinuousProfileSync">>;
+
defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling", defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling",
CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse, CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Emit">, PosFlag<SetTrue, [], [ClangOption], "Emit">,
@@ -2524,6 +2531,10 @@ defm sanitize_cfi_canonical_jump_tables : BoolOption<"f", "sanitize-cfi-canonica
"Do not make">, "Do not make">,
BothFlags<[], [ClangOption], " the jump table addresses canonical in the symbol table">>, BothFlags<[], [ClangOption], " the jump table addresses canonical in the symbol table">>,
Group<f_clang_Group>; Group<f_clang_Group>;
+def fsanitize_kcfi_arity : Flag<["-"], "fsanitize-kcfi-arity">,
+ Group<f_clang_Group>,
+ HelpText<"Embed function arity information into the KCFI patchable function prefix">,
+ MarshallingInfoFlag<CodeGenOpts<"SanitizeKcfiArity">>;
defm sanitize_stats : BoolOption<"f", "sanitize-stats", defm sanitize_stats : BoolOption<"f", "sanitize-stats",
CodeGenOpts<"SanitizeStats">, DefaultFalse, CodeGenOpts<"SanitizeStats">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Enable">, PosFlag<SetTrue, [], [ClangOption], "Enable">,
@@ -3410,8 +3421,6 @@ def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>,
def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>; def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>; def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>;
def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
-def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>,
- Visibility<[ClangOption, FlangOption]>;
defm init_global_zero : BoolOptionWithoutMarshalling<"f", "init-global-zero", defm init_global_zero : BoolOptionWithoutMarshalling<"f", "init-global-zero",
PosFlag<SetTrue, [], [FlangOption, FC1Option], PosFlag<SetTrue, [], [FlangOption, FC1Option],
"Zero initialize globals without default initialization (default)">, "Zero initialize globals without default initialization (default)">,
@@ -3923,7 +3932,9 @@ defm strict_vtable_pointers : BoolFOption<"strict-vtable-pointers",
" overwriting polymorphic C++ objects">, " overwriting polymorphic C++ objects">,
NegFlag<SetFalse>>; NegFlag<SetFalse>>;
def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>, def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>,
- Visibility<[ClangOption, FlangOption]>;+ Visibility<[ClangOption, CLOption, FlangOption]>;
+def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>,
+ Visibility<[ClangOption, CLOption, FlangOption]>;
def fpointer_tbaa : Flag<["-"], "fpointer-tbaa">, Group<f_Group>; def fpointer_tbaa : Flag<["-"], "fpointer-tbaa">, Group<f_Group>;
def fdriver_only : Flag<["-"], "fdriver-only">, Flags<[NoXarchOption]>, def fdriver_only : Flag<["-"], "fdriver-only">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, CLOption, DXCOption]>, Visibility<[ClangOption, CLOption, DXCOption]>,
@@ -4063,6 +4074,10 @@ def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Issue call to specified function rather than a trap instruction">, HelpText<"Issue call to specified function rather than a trap instruction">,
MarshallingInfoString<CodeGenOpts<"TrapFuncName">>; MarshallingInfoString<CodeGenOpts<"TrapFuncName">>;
+def floop_interchange : Flag<["-"], "floop-interchange">, Group<f_Group>,
+ HelpText<"Enable the loop interchange pass">, Visibility<[ClangOption, CC1Option]>;
+def fno_loop_interchange: Flag<["-"], "fno-loop-interchange">, Group<f_Group>,
+ HelpText<"Disable the loop interchange pass">, Visibility<[ClangOption, CC1Option]>;
def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>, def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>,
HelpText<"Turn on loop unroller">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; HelpText<"Turn on loop unroller">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>;
def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>, def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>,
@@ -5825,6 +5840,9 @@ def start_no_unused_arguments : Flag<["--"], "start-no-unused-arguments">,
HelpText<"Don't emit warnings about unused arguments for the following arguments">; HelpText<"Don't emit warnings about unused arguments for the following arguments">;
def static_libgcc : Flag<["-"], "static-libgcc">; def static_libgcc : Flag<["-"], "static-libgcc">;
def static_libstdcxx : Flag<["-"], "static-libstdc++">; def static_libstdcxx : Flag<["-"], "static-libstdc++">;
+def static_libclosure : Flag<["-"], "static-libclosure">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Generate code for statically linking libclosure (BlocksRuntime)">;
def static : Flag<["-", "--"], "static">, Group<Link_Group>, def static : Flag<["-", "--"], "static">, Group<Link_Group>,
Visibility<[ClangOption, FlangOption]>, Visibility<[ClangOption, FlangOption]>,
Flags<[NoArgumentUnused]>; Flags<[NoArgumentUnused]>;
@@ -6876,6 +6894,7 @@ defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string in
defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">; defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">;
defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">; defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">;
defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed unless overridden by IMPLICIT statements">; defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed unless overridden by IMPLICIT statements">;
+defm implicit_none_ext : OptInFC1FFlag<"implicit-none-ext", "No implicit externals allowed">;
defm underscoring : OptInFC1FFlag<"underscoring", "Appends one trailing underscore to external names">; defm underscoring : OptInFC1FFlag<"underscoring", "Appends one trailing underscore to external names">;
defm ppc_native_vec_elem_order: BoolOptionWithoutMarshalling<"f", "ppc-native-vector-element-order", defm ppc_native_vec_elem_order: BoolOptionWithoutMarshalling<"f", "ppc-native-vector-element-order",
PosFlag<SetTrue, [], [ClangOption], "Specifies PowerPC native vector element order (default)">, PosFlag<SetTrue, [], [ClangOption], "Specifies PowerPC native vector element order (default)">,
clang/include/clang/Driver/SanitizerArgs.h
@@ -43,6 +43,7 @@ class SanitizerArgs {
bool CfiICallGeneralizePointers = false; bool CfiICallGeneralizePointers = false;
bool CfiICallNormalizeIntegers = false; bool CfiICallNormalizeIntegers = false;
bool CfiCanonicalJumpTables = false; bool CfiCanonicalJumpTables = false;
+ bool KcfiArity = false;
int AsanFieldPadding = 0; int AsanFieldPadding = 0;
bool SharedRuntime = false; bool SharedRuntime = false;
bool StableABI = false; bool StableABI = false;
clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -1146,11 +1146,29 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
StringRef Name = Decl->getName(); StringRef Name = Decl->getName();
+ auto nameMatches = [&Name](TagDecl *TagDecl) {
+ StringRef TagName = TagDecl->getName();
+
+ if (TagName == Name)
+ return true;
+
+ // Also check whether the tag decl's name is the same as the typedef name
+ // with prefixed underscores
+ if (TagName.starts_with('_')) {
+ StringRef StrippedName = TagName.ltrim('_');
+
+ if (StrippedName == Name)
+ return true;
+ }
+
+ return false;
+ };
+
// If the underlying type was defined as part of the typedef modify it's // If the underlying type was defined as part of the typedef modify it's
// fragments directly and pretend the typedef doesn't exist. // fragments directly and pretend the typedef doesn't exist.
if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) { if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() && if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() &&
- Decl->getName() == TagDecl->getName()) {+ nameMatches(TagDecl)) {
SmallString<128> TagUSR; SmallString<128> TagUSR;
index::generateUSRForDecl(TagDecl, TagUSR); index::generateUSRForDecl(TagDecl, TagUSR);
if (auto *Record = API.findRecordForUSR(TagUSR)) { if (auto *Record = API.findRecordForUSR(TagUSR)) {
@@ -1164,6 +1182,11 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
.append(Name, DeclarationFragments::FragmentKind::Identifier) .append(Name, DeclarationFragments::FragmentKind::Identifier)
.appendSemicolon(); .appendSemicolon();
+ // Replace the name and subheading in case it's underscored so we can
+ // use the non-underscored version
+ Record->Name = Name;
+ Record->SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl);
+
return true; return true;
} }
} }
clang/include/clang/Format/Format.h
@@ -1212,6 +1212,22 @@ struct FormatStyle {
/// \version 3.7 /// \version 3.7
bool BinPackArguments; bool BinPackArguments;
+ /// If ``BinPackLongBracedList`` is ``true`` it overrides
+ /// ``BinPackArguments`` if there are 20 or more items in a braced
+ /// initializer list.
+ /// \code
+ /// BinPackLongBracedList: false vs. BinPackLongBracedList: true
+ /// vector<int> x{ vector<int> x{1, 2, ...,
+ /// 20, 21};
+ /// 1,
+ /// 2,
+ /// ...,
+ /// 20,
+ /// 21};
+ /// \endcode
+ /// \version 21
+ bool BinPackLongBracedList;
+
/// Different way to try to fit all parameters on a line. /// Different way to try to fit all parameters on a line.
enum BinPackParametersStyle : int8_t { enum BinPackParametersStyle : int8_t {
/// Bin-pack parameters. /// Bin-pack parameters.
@@ -2252,6 +2268,33 @@ struct FormatStyle {
/// \version 16 /// \version 16
BreakBeforeInlineASMColonStyle BreakBeforeInlineASMColon; BreakBeforeInlineASMColonStyle BreakBeforeInlineASMColon;
+ /// If ``true``, break before a template closing bracket (``>``) when there is
+ /// a line break after the matching opening bracket (``<``).
+ /// \code
+ /// true:
+ /// template <typename Foo, typename Bar>
+ ///
+ /// template <typename Foo,
+ /// typename Bar>
+ ///
+ /// template <
+ /// typename Foo,
+ /// typename Bar
+ /// >
+ ///
+ /// false:
+ /// template <typename Foo, typename Bar>
+ ///
+ /// template <typename Foo,
+ /// typename Bar>
+ ///
+ /// template <
+ /// typename Foo,
+ /// typename Bar>
+ /// \endcode
+ /// \version 21
+ bool BreakBeforeTemplateCloser;
+
/// If ``true``, ternary operators will be placed after line breaks. /// If ``true``, ternary operators will be placed after line breaks.
/// \code /// \code
/// true: /// true:
@@ -5239,6 +5282,7 @@ struct FormatStyle {
R.AlwaysBreakBeforeMultilineStrings && R.AlwaysBreakBeforeMultilineStrings &&
AttributeMacros == R.AttributeMacros && AttributeMacros == R.AttributeMacros &&
BinPackArguments == R.BinPackArguments && BinPackArguments == R.BinPackArguments &&
+ BinPackLongBracedList == R.BinPackLongBracedList &&
BinPackParameters == R.BinPackParameters && BinPackParameters == R.BinPackParameters &&
BitFieldColonSpacing == R.BitFieldColonSpacing && BitFieldColonSpacing == R.BitFieldColonSpacing &&
BracedInitializerIndentWidth == R.BracedInitializerIndentWidth && BracedInitializerIndentWidth == R.BracedInitializerIndentWidth &&
@@ -5251,6 +5295,7 @@ struct FormatStyle {
BreakBeforeBraces == R.BreakBeforeBraces && BreakBeforeBraces == R.BreakBeforeBraces &&
BreakBeforeConceptDeclarations == R.BreakBeforeConceptDeclarations && BreakBeforeConceptDeclarations == R.BreakBeforeConceptDeclarations &&
BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon && BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon &&
+ BreakBeforeTemplateCloser == R.BreakBeforeTemplateCloser &&
BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
BreakBinaryOperations == R.BreakBinaryOperations && BreakBinaryOperations == R.BreakBinaryOperations &&
BreakConstructorInitializers == R.BreakConstructorInitializers && BreakConstructorInitializers == R.BreakConstructorInitializers &&
clang/include/clang/Lex/Preprocessor.h
@@ -933,7 +933,7 @@ private:
} }
ArrayRef<ModuleMacro*> getOverriddenMacros() const { ArrayRef<ModuleMacro*> getOverriddenMacros() const {
- if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())+ if (auto *Info = dyn_cast_if_present<ModuleMacroInfo *>(State))
return Info->OverriddenMacros; return Info->OverriddenMacros;
return {}; return {};
} }
clang/include/clang/Parse/Parser.h
@@ -3710,6 +3710,7 @@ private:
SourceLocation RParenLoc; SourceLocation RParenLoc;
SourceLocation EndLoc; SourceLocation EndLoc;
SourceLocation MiscLoc; SourceLocation MiscLoc;
+ OpenACCAtomicKind AtomicKind;
SmallVector<Expr *> Exprs; SmallVector<Expr *> Exprs;
SmallVector<OpenACCClause *> Clauses; SmallVector<OpenACCClause *> Clauses;
// TODO OpenACC: As we implement support for the Atomic, Routine, and Cache // TODO OpenACC: As we implement support for the Atomic, Routine, and Cache
clang/include/clang/Sema/Overload.h
@@ -933,7 +933,7 @@ class Sema;
/// Have we matched any packs on the parameter side, versus any non-packs on /// Have we matched any packs on the parameter side, versus any non-packs on
/// the argument side, in a context where the opposite matching is also /// the argument side, in a context where the opposite matching is also
/// allowed? /// allowed?
- bool HasMatchedPackOnParmToNonPackOnArg : 1;+ bool StrictPackMatch : 1;
/// True if the candidate was found using ADL. /// True if the candidate was found using ADL.
LLVM_PREFERRED_TYPE(CallExpr::ADLCallKind) LLVM_PREFERRED_TYPE(CallExpr::ADLCallKind)
@@ -1010,8 +1010,7 @@ class Sema;
friend class OverloadCandidateSet; friend class OverloadCandidateSet;
OverloadCandidate() OverloadCandidate()
: IsSurrogate(false), IgnoreObjectArgument(false), : IsSurrogate(false), IgnoreObjectArgument(false),
- TookAddressOfOverload(false),+ TookAddressOfOverload(false), StrictPackMatch(false),
- HasMatchedPackOnParmToNonPackOnArg(false),
IsADLCandidate(llvm::to_underlying(CallExpr::NotADL)), IsADLCandidate(llvm::to_underlying(CallExpr::NotADL)),
RewriteKind(CRK_None) {} RewriteKind(CRK_None) {}
}; };
clang/include/clang/Sema/Sema.h
@@ -3664,6 +3664,12 @@ public:
NonTrivialCUnionContext UseContext, NonTrivialCUnionContext UseContext,
unsigned NonTrivialKind); unsigned NonTrivialKind);
+ /// Certain globally-unique variables might be accidentally duplicated if
+ /// built into multiple shared libraries with hidden visibility. This can
+ /// cause problems if the variable is mutable, its initialization is
+ /// effectful, or its address is taken.
+ bool GloballyUniqueObjectMightBeAccidentallyDuplicated(const VarDecl *Dcl);
+
/// AddInitializerToDecl - Adds the initializer Init to the /// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct /// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization. /// initialization rather than copy initialization.
@@ -10174,18 +10180,15 @@ public:
/// \param PartialOverloading true if we are performing "partial" overloading /// \param PartialOverloading true if we are performing "partial" overloading
/// based on an incomplete set of function arguments. This feature is used by /// based on an incomplete set of function arguments. This feature is used by
/// code completion. /// code completion.
- void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl,+ void AddOverloadCandidate(
- ArrayRef<Expr *> Args,+ FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
- bool SuppressUserConversions = false,+ bool PartialOverloading = false, bool AllowExplicit = true,
- bool PartialOverloading = false,+ bool AllowExplicitConversion = false,
- bool AllowExplicit = true,+ ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
- bool AllowExplicitConversion = false,+ ConversionSequenceList EarlyConversions = {},
- ADLCallKind IsADLCandidate = ADLCallKind::NotADL,+ OverloadCandidateParamOrder PO = {},
- ConversionSequenceList EarlyConversions = {},+ bool AggregateCandidateDeduction = false, bool StrictPackMatch = false);
- OverloadCandidateParamOrder PO = {},
- bool AggregateCandidateDeduction = false,
- bool HasMatchedPackOnParmToNonPackOnArg = false);
/// Add all of the function declarations in the given function set to /// Add all of the function declarations in the given function set to
/// the overload candidate set. /// the overload candidate set.
@@ -10221,7 +10224,7 @@ public:
bool PartialOverloading = false, bool PartialOverloading = false,
ConversionSequenceList EarlyConversions = {}, ConversionSequenceList EarlyConversions = {},
OverloadCandidateParamOrder PO = {}, OverloadCandidateParamOrder PO = {},
- bool HasMatchedPackOnParmToNonPackOnArg = false);+ bool StrictPackMatch = false);
/// Add a C++ member function template as a candidate to the candidate /// Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member /// set, using template argument deduction to produce an appropriate member
@@ -10268,7 +10271,7 @@ public:
CXXRecordDecl *ActingContext, Expr *From, QualType ToType, CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
bool AllowExplicit, bool AllowResultConversion = true, bool AllowExplicit, bool AllowResultConversion = true,
- bool HasMatchedPackOnParmToNonPackOnArg = false);+ bool StrictPackMatch = false);
/// Adds a conversion function template specialization /// Adds a conversion function template specialization
/// candidate to the overload set, using template argument deduction /// candidate to the overload set, using template argument deduction
@@ -11688,7 +11691,7 @@ public:
/// Is set to true when, in the context of TTP matching, a pack parameter /// Is set to true when, in the context of TTP matching, a pack parameter
/// matches non-pack arguments. /// matches non-pack arguments.
- bool MatchedPackOnParmToNonPackOnArg = false;+ bool StrictPackMatch = false;
}; };
/// Check that the given template argument corresponds to the given /// Check that the given template argument corresponds to the given
@@ -11797,7 +11800,7 @@ public:
TemplateParameterList *Params, TemplateParameterList *Params,
TemplateArgumentLoc &Arg, TemplateArgumentLoc &Arg,
bool PartialOrdering, bool PartialOrdering,
- bool *MatchedPackOnParmToNonPackOnArg);+ bool *StrictPackMatch);
void NoteTemplateLocation(const NamedDecl &Decl, void NoteTemplateLocation(const NamedDecl &Decl,
std::optional<SourceRange> ParamRange = {}); std::optional<SourceRange> ParamRange = {});
@@ -12491,7 +12494,7 @@ public:
bool isTemplateTemplateParameterAtLeastAsSpecializedAs( bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg, TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg,
const DefaultArguments &DefaultArgs, SourceLocation ArgLoc, const DefaultArguments &DefaultArgs, SourceLocation ArgLoc,
- bool PartialOrdering, bool *MatchedPackOnParmToNonPackOnArg);+ bool PartialOrdering, bool *StrictPackMatch);
/// Mark which template parameters are used in a given expression. /// Mark which template parameters are used in a given expression.
/// ///
@@ -13493,8 +13496,8 @@ public:
bool InstantiateClassTemplateSpecialization( bool InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec, ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK, bool Complain = true,+ TemplateSpecializationKind TSK, bool Complain,
- bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false);+ bool PrimaryStrictPackMatch);
/// Instantiates the definitions of all of the member /// Instantiates the definitions of all of the member
/// of the given class, which is an instantiation of a class template /// of the given class, which is an instantiation of a class template
clang/include/clang/Sema/SemaHLSL.h
@@ -141,6 +141,9 @@ public:
// Diagnose whether the input ID is uint/unit2/uint3 type. // Diagnose whether the input ID is uint/unit2/uint3 type.
bool diagnoseInputIDType(QualType T, const ParsedAttr &AL); bool diagnoseInputIDType(QualType T, const ParsedAttr &AL);
+ bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
+ bool ContainsBitField(QualType BaseTy);
+ bool CanPerformElementwiseCast(Expr *Src, QualType DestType);
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg); ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg);
QualType getInoutParameterType(QualType Ty); QualType getInoutParameterType(QualType Ty);
@@ -160,9 +163,9 @@ private:
ResourceBindings Bindings; ResourceBindings Bindings;
private: private:
- void collectResourcesOnVarDecl(VarDecl *D);+ void collectResourceBindingsOnVarDecl(VarDecl *D);
- void collectResourcesOnUserRecordDecl(const VarDecl *VD,+ void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,
- const RecordType *RT);+ const RecordType *RT);
void processExplicitBindingsOnDecl(VarDecl *D); void processExplicitBindingsOnDecl(VarDecl *D);
}; };
clang/include/clang/Sema/SemaOpenACC.h
@@ -695,24 +695,53 @@ public:
/// should check legality of the statement as it appertains to this Construct. /// should check legality of the statement as it appertains to this Construct.
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
OpenACCDirectiveKind K, OpenACCDirectiveKind K,
+ OpenACCAtomicKind AtKind,
ArrayRef<const OpenACCClause *> Clauses, ArrayRef<const OpenACCClause *> Clauses,
StmtResult AssocStmt); StmtResult AssocStmt);
+ StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
+ OpenACCDirectiveKind K,
+ ArrayRef<const OpenACCClause *> Clauses,
+ StmtResult AssocStmt) {
+ return ActOnAssociatedStmt(DirectiveLoc, K, OpenACCAtomicKind::None,
+ Clauses, AssocStmt);
+ }
+ /// Called to check the form of the `atomic` construct which has some fairly
+ /// sizable restrictions.
+ StmtResult CheckAtomicAssociatedStmt(SourceLocation AtomicDirLoc,
+ OpenACCAtomicKind AtKind,
+ StmtResult AssocStmt);
+
/// Called after the directive has been completely parsed, including the /// Called after the directive has been completely parsed, including the
/// declaration group or associated statement. /// declaration group or associated statement.
+ /// DirLoc: Location of the actual directive keyword.
/// LParenLoc: Location of the left paren, if it exists (not on all /// LParenLoc: Location of the left paren, if it exists (not on all
/// constructs). /// constructs).
/// MiscLoc: First misc location, if necessary (not all constructs). /// MiscLoc: First misc location, if necessary (not all constructs).
/// Exprs: List of expressions on the construct itself, if necessary (not all /// Exprs: List of expressions on the construct itself, if necessary (not all
/// constructs). /// constructs).
+ /// AK: The atomic kind of the directive, if necessary (atomic only)
/// RParenLoc: Location of the right paren, if it exists (not on all /// RParenLoc: Location of the right paren, if it exists (not on all
/// constructs). /// constructs).
+ /// EndLoc: The last source location of the driective.
+ /// Clauses: The list of clauses for the directive, if present.
+ /// AssocStmt: The associated statement for this construct, if necessary.
StmtResult ActOnEndStmtDirective( StmtResult ActOnEndStmtDirective(
OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
- SourceLocation RParenLoc, SourceLocation EndLoc,+ OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc,
ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt); ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
+ StmtResult ActOnEndStmtDirective(
+ OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
+ SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
+ SourceLocation RParenLoc, SourceLocation EndLoc,
+ ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
+ return ActOnEndStmtDirective(K, StartLoc, DirLoc, LParenLoc, MiscLoc, Exprs,
+ OpenACCAtomicKind::None, RParenLoc, EndLoc,
+ Clauses, AssocStmt);
+ }
+
/// Called after the directive has been completely parsed, including the /// Called after the directive has been completely parsed, including the
/// declaration group or associated statement. /// declaration group or associated statement.
DeclGroupRef ActOnEndDeclDirective(); DeclGroupRef ActOnEndDeclDirective();
clang/include/clang/Sema/SemaOpenMP.h
@@ -849,6 +849,9 @@ public:
ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc, ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
SourceLocation AppendArgsLoc, SourceRange SR); SourceLocation AppendArgsLoc, SourceRange SR);
+ /// Called on device_num selector in context selectors.
+ void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr);
+
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
@@ -1410,6 +1413,13 @@ public:
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL); void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL);
+ /// Setter and getter functions for device_num.
+ void setOpenMPDeviceNum(int Num);
+
+ int getOpenMPDeviceNum() const;
+
+ void setOpenMPDeviceNumID(StringRef ID);
+
private: private:
void *VarDataSharingAttributesStack; void *VarDataSharingAttributesStack;
@@ -1480,6 +1490,12 @@ private:
/// All `omp assumes` we encountered so far. /// All `omp assumes` we encountered so far.
SmallVector<OMPAssumeAttr *, 4> OMPAssumeGlobal; SmallVector<OMPAssumeAttr *, 4> OMPAssumeGlobal;
+
+ /// Device number specified by the context selector.
+ int DeviceNum = -1;
+
+ /// Device number identifier specified by the context selector.
+ StringRef DeviceNumID;
}; };
} // namespace clang } // namespace clang
clang/include/clang/Sema/TemplateDeduction.h
@@ -54,7 +54,7 @@ class TemplateDeductionInfo {
/// Have we matched any packs on the parameter side, versus any non-packs on /// Have we matched any packs on the parameter side, versus any non-packs on
/// the argument side, in a context where the opposite matching is also /// the argument side, in a context where the opposite matching is also
/// allowed? /// allowed?
- bool MatchedPackOnParmToNonPackOnArg = false;+ bool StrictPackMatch = false;
/// The template parameter depth for which we're performing deduction. /// The template parameter depth for which we're performing deduction.
unsigned DeducedDepth; unsigned DeducedDepth;
@@ -92,13 +92,9 @@ public:
return DeducedDepth; return DeducedDepth;
} }
- bool hasMatchedPackOnParmToNonPackOnArg() const {+ bool hasStrictPackMatch() const { return StrictPackMatch; }
- return MatchedPackOnParmToNonPackOnArg;
- }
- void setMatchedPackOnParmToNonPackOnArg() {+ void setStrictPackMatch() { StrictPackMatch = true; }
- MatchedPackOnParmToNonPackOnArg = true;
- }
/// Get the number of explicitly-specified arguments. /// Get the number of explicitly-specified arguments.
unsigned getNumExplicitArgs() const { unsigned getNumExplicitArgs() const {
clang/include/clang/Serialization/ASTBitCodes.h
@@ -2045,6 +2045,7 @@ enum StmtCode {
STMT_OPENACC_SHUTDOWN_CONSTRUCT, STMT_OPENACC_SHUTDOWN_CONSTRUCT,
STMT_OPENACC_SET_CONSTRUCT, STMT_OPENACC_SET_CONSTRUCT,
STMT_OPENACC_UPDATE_CONSTRUCT, STMT_OPENACC_UPDATE_CONSTRUCT,
+ STMT_OPENACC_ATOMIC_CONSTRUCT,
// HLSL Constructs // HLSL Constructs
EXPR_HLSL_OUT_ARG, EXPR_HLSL_OUT_ARG,
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -989,30 +989,41 @@ def decodeValueOfObjCType : Checker<"decodeValueOfObjCType">,
let ParentPackage = Security in { let ParentPackage = Security in {
-def FloatLoopCounter : Checker<"FloatLoopCounter">,+ def ArrayBoundChecker : Checker<"ArrayBound">,
- HelpText<"Warn on using a floating point value as a loop counter (CERT: "+ HelpText<"Warn about out of bounds access to memory">,
- "FLP30-C, FLP30-CPP)">,+ Documentation<HasDocumentation>;
- Dependencies<[SecuritySyntaxChecker]>,+
- Documentation<HasDocumentation>;+ def FloatLoopCounter
-+ : Checker<"FloatLoopCounter">,
-def MmapWriteExecChecker : Checker<"MmapWriteExec">,+ HelpText<
- HelpText<"Warn on mmap() calls with both writable and executable access">,+ "Warn on using a floating point value as a loop counter (CERT: "
- Documentation<HasDocumentation>;+ "FLP30-C, FLP30-CPP)">,
-+ Dependencies<[SecuritySyntaxChecker]>,
-def PointerSubChecker : Checker<"PointerSub">,+ Documentation<HasDocumentation>;
- HelpText<"Check for pointer subtractions on two pointers pointing to "+
- "different memory chunks">,+ def MmapWriteExecChecker
- Documentation<HasDocumentation>;+ : Checker<"MmapWriteExec">,
-+ HelpText<
-def PutenvStackArray : Checker<"PutenvStackArray">,+ "Warn on mmap() calls with both writable and executable access">,
- HelpText<"Finds calls to the function 'putenv' which pass a pointer to "+ Documentation<HasDocumentation>;
- "an automatic (stack-allocated) array as the argument.">,+
- Documentation<HasDocumentation>;+ def PointerSubChecker
-+ : Checker<"PointerSub">,
-def SetgidSetuidOrderChecker : Checker<"SetgidSetuidOrder">,+ HelpText<"Check for pointer subtractions on two pointers pointing to "
- HelpText<"Warn on possible reversed order of 'setgid(getgid()))' and "+ "different memory chunks">,
- "'setuid(getuid())' (CERT: POS36-C)">,+ Documentation<HasDocumentation>;
- Documentation<HasDocumentation>;+
+ def PutenvStackArray
+ : Checker<"PutenvStackArray">,
+ HelpText<"Finds calls to the function 'putenv' which pass a pointer to "
+ "an automatic (stack-allocated) array as the argument.">,
+ Documentation<HasDocumentation>;
+
+ def SetgidSetuidOrderChecker
+ : Checker<"SetgidSetuidOrder">,
+ HelpText<"Warn on possible reversed order of 'setgid(getgid()))' and "
+ "'setuid(getuid())' (CERT: POS36-C)">,
+ Documentation<HasDocumentation>;
} // end "security" } // end "security"
@@ -1035,14 +1046,6 @@ let ParentPackage = ENV in {
let ParentPackage = SecurityAlpha in { let ParentPackage = SecurityAlpha in {
-def ArrayBoundChecker : Checker<"ArrayBound">,
- HelpText<"Warn about buffer overflows (older checker)">,
- Documentation<HasDocumentation>;
-
-def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">,
- HelpText<"Warn about buffer overflows (newer checker)">,
- Documentation<HasDocumentation>;
-
def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">, def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
HelpText<"Check for an out-of-bound pointer being returned to callers">, HelpText<"Check for an out-of-bound pointer being returned to callers">,
Documentation<HasDocumentation>; Documentation<HasDocumentation>;
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
@@ -35,7 +35,7 @@ public:
/// Match calls to functions from the C standard library. This also /// Match calls to functions from the C standard library. This also
/// recognizes builtin variants whose name is derived by adding /// recognizes builtin variants whose name is derived by adding
/// "__builtin", "__inline" or similar prefixes or suffixes; but only /// "__builtin", "__inline" or similar prefixes or suffixes; but only
- /// matches functions than are externally visible and are declared either+ /// matches functions that are externally visible and are declared either
/// directly within a TU or in the namespace 'std'. /// directly within a TU or in the namespace 'std'.
/// For the exact heuristics, see CheckerContext::isCLibraryFunction(). /// For the exact heuristics, see CheckerContext::isCLibraryFunction().
CLibrary, CLibrary,
@@ -152,7 +152,7 @@ public:
/// exists only when that is not available, for example, when _only_ /// exists only when that is not available, for example, when _only_
/// syntactic check is done on a piece of code. /// syntactic check is done on a piece of code.
/// ///
- /// Also, StdLibraryFunctionsChecker::Signature is likely a better candicade+ /// Also, StdLibraryFunctionsChecker::Signature is likely a better candidate
/// for syntactic only matching if you are writing a new checker. This is /// for syntactic only matching if you are writing a new checker. This is
/// handy if a CallDescriptionMap is already there. /// handy if a CallDescriptionMap is already there.
/// ///
@@ -233,7 +233,7 @@ public:
/// exists only when that is not available, for example, when _only_ /// exists only when that is not available, for example, when _only_
/// syntactic check is done on a piece of code. /// syntactic check is done on a piece of code.
/// ///
- /// Also, StdLibraryFunctionsChecker::Signature is likely a better candicade+ /// Also, StdLibraryFunctionsChecker::Signature is likely a better candidate
/// for syntactic only matching if you are writing a new checker. This is /// for syntactic only matching if you are writing a new checker. This is
/// handy if a CallDescriptionMap is already there. /// handy if a CallDescriptionMap is already there.
/// ///
@@ -274,7 +274,7 @@ public:
/// exists only when that is not available, for example, when _only_ /// exists only when that is not available, for example, when _only_
/// syntactic check is done on a piece of code. /// syntactic check is done on a piece of code.
/// ///
- /// Also, StdLibraryFunctionsChecker::Signature is likely a better candicade+ /// Also, StdLibraryFunctionsChecker::Signature is likely a better candidate
/// for syntactic only matching if you are writing a new checker. This is /// for syntactic only matching if you are writing a new checker. This is
/// handy if a CallDescriptionMap is already there. /// handy if a CallDescriptionMap is already there.
/// ///
clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -344,7 +344,7 @@ public:
}; };
/// The region containing globals which can be modified by calls to /// The region containing globals which can be modified by calls to
-/// "internally" defined functions - (for now just) functions other then system+/// "internally" defined functions - (for now just) functions other than system
/// calls. /// calls.
class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager; friend class MemRegionManager;
@@ -1021,7 +1021,7 @@ public:
} }
}; };
-/// ParamVarRegion - Represents a region for paremters. Only parameters of the+/// ParamVarRegion - Represents a region for parameters. Only parameters of the
/// function in the current stack frame are represented as `ParamVarRegion`s. /// function in the current stack frame are represented as `ParamVarRegion`s.
/// Parameters of top-level analyzed functions as well as captured paremeters /// Parameters of top-level analyzed functions as well as captured paremeters
/// by lambdas and blocks are repesented as `VarRegion`s. /// by lambdas and blocks are repesented as `VarRegion`s.
clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h
@@ -55,15 +55,18 @@ enum class ScanningOptimizations {
HeaderSearch = 1, HeaderSearch = 1,
/// Remove warnings from system modules. /// Remove warnings from system modules.
- SystemWarnings = 2,+ SystemWarnings = (1 << 1),
/// Remove unused -ivfsoverlay arguments. /// Remove unused -ivfsoverlay arguments.
- VFS = 4,+ VFS = (1 << 2),
/// Canonicalize -D and -U options. /// Canonicalize -D and -U options.
- Macros = 8,+ Macros = (1 << 3),
- DSS_LAST_BITMASK_ENUM(Macros),+ /// Ignore the compiler's working directory if it is safe.
+ IgnoreCWD = (1 << 4),
+
+ DSS_LAST_BITMASK_ENUM(IgnoreCWD),
Default = All Default = All
}; };
clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -128,14 +128,17 @@ public:
/// \param LookupModuleOutput This function is called to fill in /// \param LookupModuleOutput This function is called to fill in
/// "-fmodule-file=", "-o" and other output /// "-fmodule-file=", "-o" and other output
/// arguments for dependencies. /// arguments for dependencies.
+ /// \param TUBuffer Optional memory buffer for translation unit input. If
+ /// TUBuffer is nullopt, the input should be included in the
+ /// Commandline already.
/// ///
/// \returns a \c StringError with the diagnostic output if clang errors /// \returns a \c StringError with the diagnostic output if clang errors
/// occurred, \c TranslationUnitDeps otherwise. /// occurred, \c TranslationUnitDeps otherwise.
- llvm::Expected<TranslationUnitDeps>+ llvm::Expected<TranslationUnitDeps> getTranslationUnitDependencies(
- getTranslationUnitDependencies(const std::vector<std::string> &CommandLine,+ const std::vector<std::string> &CommandLine, StringRef CWD,
- StringRef CWD,+ const llvm::DenseSet<ModuleID> &AlreadySeen,
- const llvm::DenseSet<ModuleID> &AlreadySeen,+ LookupModuleOutputCallback LookupModuleOutput,
- LookupModuleOutputCallback LookupModuleOutput);+ std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
/// Given a compilation context specified via the Clang driver command-line, /// Given a compilation context specified via the Clang driver command-line,
/// gather modular dependencies of module with the given name, and return the /// gather modular dependencies of module with the given name, and return the
clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
@@ -17,6 +17,7 @@
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBufferRef.h"
#include <optional> #include <optional>
#include <string> #include <string>
@@ -83,9 +84,21 @@ public:
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS); llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
/// Run the dependency scanning tool for a given clang driver command-line, /// Run the dependency scanning tool for a given clang driver command-line,
- /// and report the discovered dependencies to the provided consumer. If \p+ /// and report the discovered dependencies to the provided consumer. If
- /// ModuleName isn't empty, this function reports the dependencies of module+ /// TUBuffer is not nullopt, it is used as TU input for the dependency
- /// \p ModuleName.+ /// scanning. Otherwise, the input should be included as part of the
+ /// command-line.
+ ///
+ /// \returns false if clang errors occurred (with diagnostics reported to
+ /// \c DiagConsumer), true otherwise.
+ bool computeDependencies(
+ StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
+ DependencyConsumer &DepConsumer, DependencyActionController &Controller,
+ DiagnosticConsumer &DiagConsumer,
+ std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
+
+ /// Run the dependency scanning tool for a given clang driver command-line
+ /// for a specific module.
/// ///
/// \returns false if clang errors occurred (with diagnostics reported to /// \returns false if clang errors occurred (with diagnostics reported to
/// \c DiagConsumer), true otherwise. /// \c DiagConsumer), true otherwise.
@@ -94,13 +107,28 @@ public:
DependencyConsumer &DepConsumer, DependencyConsumer &DepConsumer,
DependencyActionController &Controller, DependencyActionController &Controller,
DiagnosticConsumer &DiagConsumer, DiagnosticConsumer &DiagConsumer,
- std::optional<StringRef> ModuleName = std::nullopt);+ StringRef ModuleName);
+
+ /// Run the dependency scanning tool for a given clang driver command-line
+ /// for a specific translation unit via file system or memory buffer.
+ ///
/// \returns A \c StringError with the diagnostic output if clang errors /// \returns A \c StringError with the diagnostic output if clang errors
/// occurred, success otherwise. /// occurred, success otherwise.
llvm::Error computeDependencies( llvm::Error computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine, StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller, DependencyConsumer &Consumer, DependencyActionController &Controller,
- std::optional<StringRef> ModuleName = std::nullopt);+ std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
+
+ /// Run the dependency scanning tool for a given clang driver command-line
+ /// for a specific module.
+ ///
+ /// \returns A \c StringError with the diagnostic output if clang errors
+ /// occurred, success otherwise.
+ llvm::Error computeDependencies(StringRef WorkingDirectory,
+ const std::vector<std::string> &CommandLine,
+ DependencyConsumer &Consumer,
+ DependencyActionController &Controller,
+ StringRef ModuleName);
bool shouldEagerLoadModules() const { return EagerLoadModules; } bool shouldEagerLoadModules() const { return EagerLoadModules; }
@@ -121,6 +149,15 @@ private:
ScanningOptimizations OptimizeArgs; ScanningOptimizations OptimizeArgs;
/// Whether to set up command-lines to load PCM files eagerly. /// Whether to set up command-lines to load PCM files eagerly.
bool EagerLoadModules; bool EagerLoadModules;
+
+ /// Private helper functions.
+ bool scanDependencies(StringRef WorkingDirectory,
+ const std::vector<std::string> &CommandLine,
+ DependencyConsumer &Consumer,
+ DependencyActionController &Controller,
+ DiagnosticConsumer &DC,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ std::optional<StringRef> ModuleName);
}; };
} // end namespace dependencies } // end namespace dependencies
clang/include/module.modulemap
@@ -45,16 +45,11 @@ module Clang_Basic {
textual header "clang/Basic/BuiltinsAMDGPU.def" textual header "clang/Basic/BuiltinsAMDGPU.def"
textual header "clang/Basic/BuiltinsARM.def" textual header "clang/Basic/BuiltinsARM.def"
textual header "clang/Basic/BuiltinsHexagonMapCustomDep.def" textual header "clang/Basic/BuiltinsHexagonMapCustomDep.def"
- textual header "clang/Basic/BuiltinsLoongArch.def"
textual header "clang/Basic/BuiltinsLoongArchBase.def" textual header "clang/Basic/BuiltinsLoongArchBase.def"
textual header "clang/Basic/BuiltinsLoongArchLASX.def" textual header "clang/Basic/BuiltinsLoongArchLASX.def"
textual header "clang/Basic/BuiltinsLoongArchLSX.def" textual header "clang/Basic/BuiltinsLoongArchLSX.def"
textual header "clang/Basic/BuiltinsMips.def" textual header "clang/Basic/BuiltinsMips.def"
- textual header "clang/Basic/BuiltinsNEON.def"
textual header "clang/Basic/BuiltinsPPC.def" textual header "clang/Basic/BuiltinsPPC.def"
- textual header "clang/Basic/BuiltinsRISCVVector.def"
- textual header "clang/Basic/BuiltinsSME.def"
- textual header "clang/Basic/BuiltinsSVE.def"
textual header "clang/Basic/BuiltinsSystemZ.def" textual header "clang/Basic/BuiltinsSystemZ.def"
textual header "clang/Basic/BuiltinsVE.def" textual header "clang/Basic/BuiltinsVE.def"
textual header "clang/Basic/BuiltinsVEVL.gen.def" textual header "clang/Basic/BuiltinsVEVL.gen.def"
@@ -113,6 +108,8 @@ module Clang_Diagnostics {
module Parse { header "clang/Basic/DiagnosticParse.h" export * } module Parse { header "clang/Basic/DiagnosticParse.h" export * }
module Serialization { header "clang/Serialization/SerializationDiagnostic.h" export * } module Serialization { header "clang/Serialization/SerializationDiagnostic.h" export * }
module Refactoring { header "clang/Tooling/Refactoring/RefactoringDiagnostic.h" export * } module Refactoring { header "clang/Tooling/Refactoring/RefactoringDiagnostic.h" export * }
+
+ textual header "clang/Basic/AllDiagnosticKinds.inc"
} }
module Clang_Driver { module Clang_Driver {
clang/lib/AST/ASTContext.cpp
@@ -1055,7 +1055,8 @@ void ASTContext::PrintStats() const {
void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M, void ASTContext::mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
bool NotifyListeners) { bool NotifyListeners) {
if (NotifyListeners) if (NotifyListeners)
- if (auto *Listener = getASTMutationListener())+ if (auto *Listener = getASTMutationListener();
+ Listener && !ND->isUnconditionallyVisible())
Listener->RedefinedHiddenDefinition(ND, M); Listener->RedefinedHiddenDefinition(ND, M);
MergedDefModules[cast<NamedDecl>(ND->getCanonicalDecl())].push_back(M); MergedDefModules[cast<NamedDecl>(ND->getCanonicalDecl())].push_back(M);
@@ -3901,7 +3902,7 @@ QualType ASTContext::getArrayParameterType(QualType Ty) const {
if (Ty->isArrayParameterType()) if (Ty->isArrayParameterType())
return Ty; return Ty;
assert(Ty->isConstantArrayType() && "Ty must be an array type."); assert(Ty->isConstantArrayType() && "Ty must be an array type.");
- const auto *ATy = cast<ConstantArrayType>(Ty);+ const auto *ATy = cast<ConstantArrayType>(Ty.getDesugaredType(*this));
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
ATy->Profile(ID, *this, ATy->getElementType(), ATy->getZExtSize(), ATy->Profile(ID, *this, ATy->getElementType(), ATy->getZExtSize(),
ATy->getSizeExpr(), ATy->getSizeModifier(), ATy->getSizeExpr(), ATy->getSizeModifier(),
@@ -5319,6 +5320,19 @@ bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
return EnumTooLarge; return EnumTooLarge;
} }
+bool ASTContext::isRepresentableIntegerValue(llvm::APSInt &Value, QualType T) {
+ assert((T->isIntegralType(*this) || T->isEnumeralType()) &&
+ "Integral type required!");
+ unsigned BitWidth = getIntWidth(T);
+
+ if (Value.isUnsigned() || Value.isNonNegative()) {
+ if (T->isSignedIntegerOrEnumerationType())
+ --BitWidth;
+ return Value.getActiveBits() <= BitWidth;
+ }
+ return Value.getSignificantBits() <= BitWidth;
+}
+
QualType ASTContext::getUnresolvedUsingType( QualType ASTContext::getUnresolvedUsingType(
const UnresolvedUsingTypenameDecl *Decl) const { const UnresolvedUsingTypenameDecl *Decl) const {
if (Decl->TypeForDecl) if (Decl->TypeForDecl)
@@ -7224,6 +7238,16 @@ static bool isSameQualifier(const NestedNameSpecifier *X,
return !PX && !PY; return !PX && !PY;
} }
+static bool hasSameCudaAttrs(const FunctionDecl *A, const FunctionDecl *B) {
+ if (!A->getASTContext().getLangOpts().CUDA)
+ return true; // Target attributes are overloadable in CUDA compilation only.
+ if (A->hasAttr<CUDADeviceAttr>() != B->hasAttr<CUDADeviceAttr>())
+ return false;
+ if (A->hasAttr<CUDADeviceAttr>() && B->hasAttr<CUDADeviceAttr>())
+ return A->hasAttr<CUDAHostAttr>() == B->hasAttr<CUDAHostAttr>();
+ return true; // unattributed and __host__ functions are the same.
+}
+
/// Determine whether the attributes we can overload on are identical for A and /// Determine whether the attributes we can overload on are identical for A and
/// B. Will ignore any overloadable attrs represented in the type of A and B. /// B. Will ignore any overloadable attrs represented in the type of A and B.
static bool hasSameOverloadableAttrs(const FunctionDecl *A, static bool hasSameOverloadableAttrs(const FunctionDecl *A,
@@ -7254,7 +7278,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
if (Cand1ID != Cand2ID) if (Cand1ID != Cand2ID)
return false; return false;
} }
- return true;+ return hasSameCudaAttrs(A, B);
} }
bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
clang/lib/AST/ASTImporter.cpp
@@ -6320,10 +6320,10 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
updateLookupTableForTemplateParameters(*ToTPList); updateLookupTableForTemplateParameters(*ToTPList);
} else { // Not a partial specialization. } else { // Not a partial specialization.
- if (GetImportedOrCreateDecl(+ if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), D->getTagKind(),
- D2, D, Importer.getToContext(), D->getTagKind(), DC,+ DC, *BeginLocOrErr, *IdLocOrErr, ClassTemplate,
- *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs,+ TemplateArgs, D->hasStrictPackMatch(),
- PrevDecl))+ PrevDecl))
return D2; return D2;
// Update InsertPos, because preceding import calls may have invalidated // Update InsertPos, because preceding import calls may have invalidated
clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -135,11 +135,9 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
// Create a handle over the emitted code. // Create a handle over the emitted code.
Function *Func = P.getFunction(FuncDecl); Function *Func = P.getFunction(FuncDecl);
if (!Func) { if (!Func) {
- unsigned BuiltinID = FuncDecl->getBuiltinID();+ Func = P.createFunction(FuncDecl, ParamOffset, std::move(ParamTypes),
- Func =+ std::move(ParamDescriptors),
- P.createFunction(FuncDecl, ParamOffset, std::move(ParamTypes),+ std::move(ParamOffsets), HasThisPointer, HasRVO);
- std::move(ParamDescriptors), std::move(ParamOffsets),
- HasThisPointer, HasRVO, BuiltinID);
} }
assert(Func); assert(Func);
@@ -212,8 +210,7 @@ Function *ByteCodeEmitter::compileObjCBlock(const BlockExpr *BE) {
Function *Func = Function *Func =
P.createFunction(BE, ParamOffset, std::move(ParamTypes), P.createFunction(BE, ParamOffset, std::move(ParamTypes),
std::move(ParamDescriptors), std::move(ParamOffsets), std::move(ParamDescriptors), std::move(ParamOffsets),
- /*HasThisPointer=*/false, /*HasRVO=*/false,+ /*HasThisPointer=*/false, /*HasRVO=*/false);
- /*IsUnevaluatedBuiltin=*/false);
assert(Func); assert(Func);
Func->setDefined(true); Func->setDefined(true);
clang/lib/AST/ByteCode/Compiler.cpp
@@ -194,12 +194,12 @@ private:
template <class Emitter> template <class Emitter>
bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Expr *SubExpr = CE->getSubExpr(); const Expr *SubExpr = CE->getSubExpr();
- switch (CE->getCastKind()) {
- case CK_LValueToRValue: {+ if (DiscardResult)
- if (DiscardResult)+ return this->delegate(SubExpr);
- return this->discard(SubExpr);
+ switch (CE->getCastKind()) {
+ case CK_LValueToRValue: {
std::optional<PrimType> SubExprT = classify(SubExpr->getType()); std::optional<PrimType> SubExprT = classify(SubExpr->getType());
// Prepare storage for the result. // Prepare storage for the result.
if (!Initializing && !SubExprT) { if (!Initializing && !SubExprT) {
@@ -253,9 +253,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_UncheckedDerivedToBase: case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: { case CK_DerivedToBase: {
- if (DiscardResult)
- return this->discard(SubExpr);
-
if (!this->delegate(SubExpr)) if (!this->delegate(SubExpr))
return false; return false;
@@ -285,9 +282,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
} }
case CK_BaseToDerived: { case CK_BaseToDerived: {
- if (DiscardResult)
- return this->discard(SubExpr);
-
if (!this->delegate(SubExpr)) if (!this->delegate(SubExpr))
return false; return false;
@@ -302,8 +296,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (!SubExpr->getType()->isFloatingType() || if (!SubExpr->getType()->isFloatingType() ||
!CE->getType()->isFloatingType()) !CE->getType()->isFloatingType())
return false; return false;
- if (DiscardResult)
- return this->discard(SubExpr);
if (!this->visit(SubExpr)) if (!this->visit(SubExpr))
return false; return false;
const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
@@ -311,8 +303,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
} }
case CK_IntegralToFloating: { case CK_IntegralToFloating: {
- if (DiscardResult)
- return this->discard(SubExpr);
std::optional<PrimType> FromT = classify(SubExpr->getType()); std::optional<PrimType> FromT = classify(SubExpr->getType());
if (!FromT) if (!FromT)
return false; return false;
@@ -327,8 +317,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_FloatingToBoolean: case CK_FloatingToBoolean:
case CK_FloatingToIntegral: { case CK_FloatingToIntegral: {
- if (DiscardResult)
- return this->discard(SubExpr);
std::optional<PrimType> ToT = classify(CE->getType()); std::optional<PrimType> ToT = classify(CE->getType());
@@ -352,9 +340,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_NullToMemberPointer: { case CK_NullToMemberPointer: {
if (!this->discard(SubExpr)) if (!this->discard(SubExpr))
return false; return false;
- if (DiscardResult)
- return true;
-
const Descriptor *Desc = nullptr; const Descriptor *Desc = nullptr;
const QualType PointeeType = CE->getType()->getPointeeType(); const QualType PointeeType = CE->getType()->getPointeeType();
if (!PointeeType.isNull()) { if (!PointeeType.isNull()) {
@@ -371,9 +356,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
} }
case CK_PointerToIntegral: { case CK_PointerToIntegral: {
- if (DiscardResult)
- return this->discard(SubExpr);
-
if (!this->visit(SubExpr)) if (!this->visit(SubExpr))
return false; return false;
@@ -399,8 +381,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return false; return false;
if (!this->emitArrayDecay(CE)) if (!this->emitArrayDecay(CE))
return false; return false;
- if (DiscardResult)
- return this->emitPopPtr(CE);
return true; return true;
} }
@@ -412,9 +392,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
// FIXME: I think the discard is wrong since the int->ptr cast might cause a // FIXME: I think the discard is wrong since the int->ptr cast might cause a
// diagnostic. // diagnostic.
PrimType T = classifyPrim(IntType); PrimType T = classifyPrim(IntType);
- if (DiscardResult)
- return this->emitPop(T, CE);
-
QualType PtrType = CE->getType(); QualType PtrType = CE->getType();
const Descriptor *Desc; const Descriptor *Desc;
if (std::optional<PrimType> T = classify(PtrType->getPointeeType())) if (std::optional<PrimType> T = classify(PtrType->getPointeeType()))
@@ -454,10 +431,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return false; return false;
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE); return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);
} }
-
- if (DiscardResult)
- return this->discard(SubExpr);
-
QualType SubExprTy = SubExpr->getType(); QualType SubExprTy = SubExpr->getType();
std::optional<PrimType> FromT = classify(SubExprTy); std::optional<PrimType> FromT = classify(SubExprTy);
// Casts from integer/vector to vector. // Casts from integer/vector to vector.
@@ -493,8 +466,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_FixedPointToBoolean: case CK_FixedPointToBoolean:
case CK_BooleanToSignedIntegral: case CK_BooleanToSignedIntegral:
case CK_IntegralCast: { case CK_IntegralCast: {
- if (DiscardResult)
- return this->discard(SubExpr);
std::optional<PrimType> FromT = classify(SubExpr->getType()); std::optional<PrimType> FromT = classify(SubExpr->getType());
std::optional<PrimType> ToT = classify(CE->getType()); std::optional<PrimType> ToT = classify(CE->getType());
@@ -546,8 +517,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_IntegralComplexToBoolean: case CK_IntegralComplexToBoolean:
case CK_FloatingComplexToBoolean: { case CK_FloatingComplexToBoolean: {
- if (DiscardResult)
- return this->discard(SubExpr);
if (!this->visit(SubExpr)) if (!this->visit(SubExpr))
return false; return false;
return this->emitComplexBoolCast(SubExpr); return this->emitComplexBoolCast(SubExpr);
@@ -585,9 +554,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_FloatingComplexToIntegralComplex: { case CK_FloatingComplexToIntegralComplex: {
assert(CE->getType()->isAnyComplexType()); assert(CE->getType()->isAnyComplexType());
assert(SubExpr->getType()->isAnyComplexType()); assert(SubExpr->getType()->isAnyComplexType());
- if (DiscardResult)
- return this->discard(SubExpr);
-
if (!Initializing) { if (!Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(CE); std::optional<unsigned> LocalIndex = allocateLocal(CE);
if (!LocalIndex) if (!LocalIndex)
@@ -633,9 +599,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
assert(classify(SubExpr->getType())); assert(classify(SubExpr->getType()));
assert(CE->getType()->isVectorType()); assert(CE->getType()->isVectorType());
- if (DiscardResult)
- return this->discard(SubExpr);
-
if (!Initializing) { if (!Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(CE); std::optional<unsigned> LocalIndex = allocateLocal(CE);
if (!LocalIndex) if (!LocalIndex)
@@ -3370,15 +3333,23 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
PrimType SizeT = classifyPrim(Stripped->getType()); PrimType SizeT = classifyPrim(Stripped->getType());
+ // Save evaluated array size to a variable.
+ unsigned ArrayLen = allocateLocalPrimitive(
+ Stripped, SizeT, /*IsConst=*/false, /*IsExtended=*/false);
+ if (!this->visit(Stripped))
+ return false;
+ if (!this->emitSetLocal(SizeT, ArrayLen, E))
+ return false;
+
if (PlacementDest) { if (PlacementDest) {
if (!this->visit(PlacementDest)) if (!this->visit(PlacementDest))
return false; return false;
- if (!this->visit(Stripped))+ if (!this->emitGetLocal(SizeT, ArrayLen, E))
return false; return false;
if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E)) if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
return false; return false;
} else { } else {
- if (!this->visit(Stripped))+ if (!this->emitGetLocal(SizeT, ArrayLen, E))
return false; return false;
if (ElemT) { if (ElemT) {
@@ -3392,10 +3363,113 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
} }
} }
- if (Init && !this->visitInitializer(Init))+ if (Init) {
- return false;+ QualType InitType = Init->getType();
+ size_t StaticInitElems = 0;
+ const Expr *DynamicInit = nullptr;
+ if (const ConstantArrayType *CAT =
+ Ctx.getASTContext().getAsConstantArrayType(InitType)) {
+ StaticInitElems = CAT->getZExtSize();
+ if (!this->visitInitializer(Init))
+ return false;
- } else {+ if (const auto *ILE = dyn_cast<InitListExpr>(Init);
+ ILE && ILE->hasArrayFiller())
+ DynamicInit = ILE->getArrayFiller();
+ }
+
+ // The initializer initializes a certain number of elements, S.
+ // However, the complete number of elements, N, might be larger than that.
+ // In this case, we need to get an initializer for the remaining elements.
+ // There are to cases:
+ // 1) For the form 'new Struct[n];', the initializer is a
+ // CXXConstructExpr and its type is an IncompleteArrayType.
+ // 2) For the form 'new Struct[n]{1,2,3}', the initializer is an
+ // InitListExpr and the initializer for the remaining elements
+ // is the array filler.
+
+ if (DynamicInit || InitType->isIncompleteArrayType()) {
+ const Function *CtorFunc = nullptr;
+ if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
+ CtorFunc = getFunction(CE->getConstructor());
+ if (!CtorFunc)
+ return false;
+ }
+
+ LabelTy EndLabel = this->getLabel();
+ LabelTy StartLabel = this->getLabel();
+
+ // In the nothrow case, the alloc above might have returned nullptr.
+ // Don't call any constructors that case.
+ if (IsNoThrow) {
+ if (!this->emitDupPtr(E))
+ return false;
+ if (!this->emitNullPtr(0, nullptr, E))
+ return false;
+ if (!this->emitEQPtr(E))
+ return false;
+ if (!this->jumpTrue(EndLabel))
+ return false;
+ }
+
+ // Create loop variables.
+ unsigned Iter = allocateLocalPrimitive(
+ Stripped, SizeT, /*IsConst=*/false, /*IsExtended=*/false);
+ if (!this->emitConst(StaticInitElems, SizeT, E))
+ return false;
+ if (!this->emitSetLocal(SizeT, Iter, E))
+ return false;
+
+ this->fallthrough(StartLabel);
+ this->emitLabel(StartLabel);
+ // Condition. Iter < ArrayLen?
+ if (!this->emitGetLocal(SizeT, Iter, E))
+ return false;
+ if (!this->emitGetLocal(SizeT, ArrayLen, E))
+ return false;
+ if (!this->emitLT(SizeT, E))
+ return false;
+ if (!this->jumpFalse(EndLabel))
+ return false;
+
+ // Pointer to the allocated array is already on the stack.
+ if (!this->emitGetLocal(SizeT, Iter, E))
+ return false;
+ if (!this->emitArrayElemPtr(SizeT, E))
+ return false;
+
+ if (DynamicInit) {
+ if (std::optional<PrimType> InitT = classify(DynamicInit)) {
+ if (!this->visit(DynamicInit))
+ return false;
+ if (!this->emitStorePop(*InitT, E))
+ return false;
+ } else {
+ if (!this->visitInitializer(DynamicInit))
+ return false;
+ if (!this->emitPopPtr(E))
+ return false;
+ }
+ } else {
+ assert(CtorFunc);
+ if (!this->emitCall(CtorFunc, 0, E))
+ return false;
+ }
+
+ // ++Iter;
+ if (!this->emitGetPtrLocal(Iter, E))
+ return false;
+ if (!this->emitIncPop(SizeT, E))
+ return false;
+
+ if (!this->jump(StartLabel))
+ return false;
+
+ this->fallthrough(EndLabel);
+ this->emitLabel(EndLabel);
+ }
+ }
+ } else { // Non-array.
if (PlacementDest) { if (PlacementDest) {
if (!this->visit(PlacementDest)) if (!this->visit(PlacementDest))
return false; return false;
@@ -4676,7 +4750,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
OCE && OCE->isAssignmentOp()) { OCE && OCE->isAssignmentOp()) {
// Just like with regular assignments, we need to special-case assignment // Just like with regular assignments, we need to special-case assignment
// operators here and evaluate the RHS (the second arg) before the LHS (the // operators here and evaluate the RHS (the second arg) before the LHS (the
- // first arg. We fix this by using a Flip op later.+ // first arg). We fix this by using a Flip op later.
assert(Args.size() == 2); assert(Args.size() == 2);
IsAssignmentOperatorCall = true; IsAssignmentOperatorCall = true;
std::reverse(Args.begin(), Args.end()); std::reverse(Args.begin(), Args.end());
@@ -4715,6 +4789,14 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
} else if (!this->visit(MC->getImplicitObjectArgument())) { } else if (!this->visit(MC->getImplicitObjectArgument())) {
return false; return false;
} }
+ } else if (const auto *PD =
+ dyn_cast<CXXPseudoDestructorExpr>(E->getCallee())) {
+ const Expr *Base = PD->getBase();
+ if (!Base->isGLValue())
+ return this->discard(Base);
+ if (!this->visit(Base))
+ return false;
+ return this->emitKill(E);
} else if (!FuncDecl) { } else if (!FuncDecl) {
const Expr *Callee = E->getCallee(); const Expr *Callee = E->getCallee();
CalleeOffset = this->allocateLocalPrimitive(Callee, PT_FnPtr, true, false); CalleeOffset = this->allocateLocalPrimitive(Callee, PT_FnPtr, true, false);
@@ -4991,8 +5073,8 @@ bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
template <class Emitter> template <class Emitter>
bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS) { bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS) {
for (const auto *D : DS->decls()) { for (const auto *D : DS->decls()) {
- if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl,+ if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, BaseUsingDecl,
- FunctionDecl>(D))+ FunctionDecl, NamespaceAliasDecl>(D))
continue; continue;
const auto *VD = dyn_cast<VarDecl>(D); const auto *VD = dyn_cast<VarDecl>(D);
@@ -5596,6 +5678,22 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr)) if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
return false; return false;
+
+ // Mark all chain links as initialized.
+ unsigned InitFieldOffset = 0;
+ for (const NamedDecl *ND : IFD->chain().drop_back()) {
+ const auto *FD = cast<FieldDecl>(ND);
+ const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
+ assert(FieldRecord);
+ NestedField = FieldRecord->getField(FD);
+ InitFieldOffset += NestedField->Offset;
+ assert(NestedField);
+ if (!this->emitGetPtrThisField(InitFieldOffset, InitExpr))
+ return false;
+ if (!this->emitFinishInitPop(InitExpr))
+ return false;
+ }
+
} else { } else {
assert(Init->isDelegatingInitializer()); assert(Init->isDelegatingInitializer());
if (!this->emitThis(InitExpr)) if (!this->emitThis(InitExpr))
@@ -5664,6 +5762,21 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor); return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor);
} }
+template <class Emitter>
+bool Compiler<Emitter>::compileUnionAssignmentOperator(
+ const CXXMethodDecl *MD) {
+ if (!this->emitThis(MD))
+ return false;
+
+ auto PVD = MD->getParamDecl(0);
+ ParamOffset PO = this->Params[PVD]; // Must exist.
+
+ if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))
+ return false;
+
+ return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);
+}
+
template <class Emitter> template <class Emitter>
bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) { bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
// Classify the return type. // Classify the return type.
@@ -5675,9 +5788,16 @@ bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
return this->compileDestructor(Dtor); return this->compileDestructor(Dtor);
// Emit custom code if this is a lambda static invoker. // Emit custom code if this is a lambda static invoker.
- if (const auto *MD = dyn_cast<CXXMethodDecl>(F);+ if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
- MD && MD->isLambdaStaticInvoker())+ const RecordDecl *RD = MD->getParent();
- return this->emitLambdaStaticInvokerBody(MD);+
+ if (RD->isUnion() &&
+ (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()))
+ return this->compileUnionAssignmentOperator(MD);
+
+ if (MD->isLambdaStaticInvoker())
+ return this->emitLambdaStaticInvokerBody(MD);
+ }
// Regular functions. // Regular functions.
if (const auto *Body = F->getBody()) if (const auto *Body = F->getBody())
@@ -6188,9 +6308,6 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
return this->emitGetPtrParam(It->second.Offset, E); return this->emitGetPtrParam(It->second.Offset, E);
} }
-
- if (D->getType()->isReferenceType())
- return this->emitDummyPtr(D, E);
} }
// In case we need to re-visit a declaration. // In case we need to re-visit a declaration.
clang/lib/AST/ByteCode/Compiler.h
@@ -383,6 +383,7 @@ private:
bool emitBuiltinBitCast(const CastExpr *E); bool emitBuiltinBitCast(const CastExpr *E);
bool compileConstructor(const CXXConstructorDecl *Ctor); bool compileConstructor(const CXXConstructorDecl *Ctor);
bool compileDestructor(const CXXDestructorDecl *Dtor); bool compileDestructor(const CXXDestructorDecl *Dtor);
+ bool compileUnionAssignmentOperator(const CXXMethodDecl *MD);
bool checkLiteralType(const Expr *E); bool checkLiteralType(const Expr *E);
clang/lib/AST/ByteCode/Descriptor.h
@@ -61,6 +61,11 @@ struct alignas(void *) GlobalInlineDescriptor {
}; };
static_assert(sizeof(GlobalInlineDescriptor) == sizeof(void *), ""); static_assert(sizeof(GlobalInlineDescriptor) == sizeof(void *), "");
+enum class Lifetime : uint8_t {
+ Started,
+ Ended,
+};
+
/// Inline descriptor embedded in structures and arrays. /// Inline descriptor embedded in structures and arrays.
/// ///
/// Such descriptors precede all composite array elements and structure fields. /// Such descriptors precede all composite array elements and structure fields.
@@ -100,12 +105,14 @@ struct InlineDescriptor {
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned IsArrayElement : 1; unsigned IsArrayElement : 1;
+ Lifetime LifeState;
+
const Descriptor *Desc; const Descriptor *Desc;
InlineDescriptor(const Descriptor *D) InlineDescriptor(const Descriptor *D)
: Offset(sizeof(InlineDescriptor)), IsConst(false), IsInitialized(false), : Offset(sizeof(InlineDescriptor)), IsConst(false), IsInitialized(false),
IsBase(false), IsActive(false), IsFieldMutable(false), IsBase(false), IsActive(false), IsFieldMutable(false),
- IsArrayElement(false), Desc(D) {}+ IsArrayElement(false), LifeState(Lifetime::Started), Desc(D) {}
void dump() const { dump(llvm::errs()); } void dump() const { dump(llvm::errs()); }
void dump(llvm::raw_ostream &OS) const; void dump(llvm::raw_ostream &OS) const;
clang/lib/AST/ByteCode/Disasm.cpp
@@ -240,7 +240,7 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
else if (isRecord()) else if (isRecord())
OS << " record"; OS << " record";
else if (isPrimitive()) else if (isPrimitive())
- OS << " primitive";+ OS << " primitive " << primTypeToString(getPrimType());
if (isZeroSizeArray()) if (isZeroSizeArray())
OS << " zero-size-array"; OS << " zero-size-array";
clang/lib/AST/ByteCode/Function.cpp
@@ -19,12 +19,28 @@ Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
llvm::SmallVectorImpl<PrimType> &&ParamTypes, llvm::SmallVectorImpl<PrimType> &&ParamTypes,
llvm::DenseMap<unsigned, ParamDescriptor> &&Params, llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
llvm::SmallVectorImpl<unsigned> &&ParamOffsets, llvm::SmallVectorImpl<unsigned> &&ParamOffsets,
- bool HasThisPointer, bool HasRVO, unsigned BuiltinID)+ bool HasThisPointer, bool HasRVO)
- : P(P), Source(Source), ArgSize(ArgSize), ParamTypes(std::move(ParamTypes)),+ : P(P), Kind(FunctionKind::Normal), Source(Source), ArgSize(ArgSize),
- Params(std::move(Params)), ParamOffsets(std::move(ParamOffsets)),+ ParamTypes(std::move(ParamTypes)), Params(std::move(Params)),
- HasThisPointer(HasThisPointer), HasRVO(HasRVO), BuiltinID(BuiltinID) {+ ParamOffsets(std::move(ParamOffsets)), HasThisPointer(HasThisPointer),
- if (const auto *F = Source.dyn_cast<const FunctionDecl *>())+ HasRVO(HasRVO) {
+ if (const auto *F = dyn_cast<const FunctionDecl *>(Source)) {
Variadic = F->isVariadic(); Variadic = F->isVariadic();
+ BuiltinID = F->getBuiltinID();
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(F)) {
+ Virtual = CD->isVirtual();
+ Kind = FunctionKind::Ctor;
+ } else if (const auto *CD = dyn_cast<CXXDestructorDecl>(F)) {
+ Virtual = CD->isVirtual();
+ Kind = FunctionKind::Dtor;
+ } else if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
+ Virtual = MD->isVirtual();
+ if (MD->isLambdaStaticInvoker())
+ Kind = FunctionKind::LambdaStaticInvoker;
+ else if (clang::isLambdaCallOperator(F))
+ Kind = FunctionKind::LambdaCallOperator;
+ }
+ }
} }
Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const {
@@ -45,13 +61,6 @@ SourceInfo Function::getSource(CodePtr PC) const {
return It->second; return It->second;
} }
-bool Function::isVirtual() const {
- if (const auto *M = dyn_cast_if_present<CXXMethodDecl>(
- Source.dyn_cast<const FunctionDecl *>()))
- return M->isVirtual();
- return false;
-}
-
/// Unevaluated builtins don't get their arguments put on the stack /// Unevaluated builtins don't get their arguments put on the stack
/// automatically. They instead operate on the AST of their Call /// automatically. They instead operate on the AST of their Call
/// Expression. /// Expression.
clang/lib/AST/ByteCode/Function.h
@@ -51,6 +51,11 @@ public:
return llvm::make_range(Descriptors.begin(), Descriptors.end()); return llvm::make_range(Descriptors.begin(), Descriptors.end());
} }
+ llvm::iterator_range<LocalVectorTy::const_reverse_iterator>
+ locals_reverse() const {
+ return llvm::reverse(Descriptors);
+ }
+
private: private:
/// Object descriptors in this block. /// Object descriptors in this block.
LocalVectorTy Descriptors; LocalVectorTy Descriptors;
@@ -80,6 +85,13 @@ using FunctionDeclTy =
/// ///
class Function final { class Function final {
public: public:
+ enum class FunctionKind {
+ Normal,
+ Ctor,
+ Dtor,
+ LambdaStaticInvoker,
+ LambdaCallOperator,
+ };
using ParamDescriptor = std::pair<PrimType, Descriptor *>; using ParamDescriptor = std::pair<PrimType, Descriptor *>;
/// Returns the size of the function's local stack. /// Returns the size of the function's local stack.
@@ -141,43 +153,31 @@ public:
bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); } bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); }
/// Checks if the function is virtual. /// Checks if the function is virtual.
- bool isVirtual() const;+ bool isVirtual() const { return Virtual; };
/// Checks if the function is a constructor. /// Checks if the function is a constructor.
- bool isConstructor() const {+ bool isConstructor() const { return Kind == FunctionKind::Ctor; }
- return isa_and_nonnull<CXXConstructorDecl>(
- dyn_cast<const FunctionDecl *>(Source));
- }
/// Checks if the function is a destructor. /// Checks if the function is a destructor.
- bool isDestructor() const {+ bool isDestructor() const { return Kind == FunctionKind::Dtor; }
- return isa_and_nonnull<CXXDestructorDecl>(
- dyn_cast<const FunctionDecl *>(Source));
- }
-
- /// Returns the parent record decl, if any.
- const CXXRecordDecl *getParentDecl() const {
- if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(
- dyn_cast<const FunctionDecl *>(Source)))
- return MD->getParent();
- return nullptr;
- }
/// Returns whether this function is a lambda static invoker, /// Returns whether this function is a lambda static invoker,
/// which we generate custom byte code for. /// which we generate custom byte code for.
bool isLambdaStaticInvoker() const { bool isLambdaStaticInvoker() const {
- if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(+ return Kind == FunctionKind::LambdaStaticInvoker;
- dyn_cast<const FunctionDecl *>(Source)))
- return MD->isLambdaStaticInvoker();
- return false;
} }
/// Returns whether this function is the call operator /// Returns whether this function is the call operator
/// of a lambda record decl. /// of a lambda record decl.
bool isLambdaCallOperator() const { bool isLambdaCallOperator() const {
+ return Kind == FunctionKind::LambdaCallOperator;
+ }
+
+ /// Returns the parent record decl, if any.
+ const CXXRecordDecl *getParentDecl() const {
if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>( if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(
dyn_cast<const FunctionDecl *>(Source))) dyn_cast<const FunctionDecl *>(Source)))
- return clang::isLambdaCallOperator(MD);+ return MD->getParent();
- return false;+ return nullptr;
} }
/// Checks if the function is fully done compiling. /// Checks if the function is fully done compiling.
@@ -213,7 +213,7 @@ public:
bool isThisPointerExplicit() const { bool isThisPointerExplicit() const {
if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>( if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(
- Source.dyn_cast<const FunctionDecl *>()))+ dyn_cast<const FunctionDecl *>(Source)))
return MD->isExplicitObjectMemberFunction(); return MD->isExplicitObjectMemberFunction();
return false; return false;
} }
@@ -232,7 +232,7 @@ private:
llvm::SmallVectorImpl<PrimType> &&ParamTypes, llvm::SmallVectorImpl<PrimType> &&ParamTypes,
llvm::DenseMap<unsigned, ParamDescriptor> &&Params, llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer, llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,
- bool HasRVO, unsigned BuiltinID);+ bool HasRVO);
/// Sets the code of a function. /// Sets the code of a function.
void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode, void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,
@@ -255,6 +255,8 @@ private:
/// Program reference. /// Program reference.
Program &P; Program &P;
+ /// Function Kind.
+ FunctionKind Kind;
/// Declaration this function was compiled from. /// Declaration this function was compiled from.
FunctionDeclTy Source; FunctionDeclTy Source;
/// Local area size: storage + metadata. /// Local area size: storage + metadata.
@@ -289,6 +291,7 @@ private:
bool HasBody = false; bool HasBody = false;
bool Defined = false; bool Defined = false;
bool Variadic = false; bool Variadic = false;
+ bool Virtual = false;
unsigned BuiltinID = 0; unsigned BuiltinID = 0;
public: public:
clang/lib/AST/ByteCode/Interp.cpp
@@ -65,17 +65,17 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD); const ValueDecl *VD);
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
const ValueDecl *D) { const ValueDecl *D) {
- const SourceInfo &E = S.Current->getSource(OpPC);
if (isa<ParmVarDecl>(D)) { if (isa<ParmVarDecl>(D)) {
if (D->getType()->isReferenceType()) if (D->getType()->isReferenceType())
return false; return false;
+ const SourceInfo &Loc = S.Current->getSource(OpPC);
if (S.getLangOpts().CPlusPlus11) { if (S.getLangOpts().CPlusPlus11) {
- S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;+ S.FFDiag(Loc, diag::note_constexpr_function_param_value_unknown) << D;
S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange(); S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
} else { } else {
- S.FFDiag(E);+ S.FFDiag(Loc);
} }
return false; return false;
} }
@@ -561,6 +561,18 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false; return false;
} }
+static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ AccessKinds AK) {
+ if (Ptr.getLifetime() == Lifetime::Started)
+ return true;
+
+ if (!S.checkingPotentialConstantExpression()) {
+ S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
+ << AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
+ }
+ return false;
+}
+
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (Ptr.isInitialized()) if (Ptr.isInitialized())
return true; return true;
@@ -605,6 +617,8 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false; return false;
if (!CheckActive(S, OpPC, Ptr, AK)) if (!CheckActive(S, OpPC, Ptr, AK))
return false; return false;
+ if (!CheckLifetime(S, OpPC, Ptr, AK))
+ return false;
if (!CheckInitialized(S, OpPC, Ptr, AK)) if (!CheckInitialized(S, OpPC, Ptr, AK))
return false; return false;
if (!CheckTemporary(S, OpPC, Ptr, AK)) if (!CheckTemporary(S, OpPC, Ptr, AK))
@@ -634,6 +648,8 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false; return false;
if (!CheckActive(S, OpPC, Ptr, AK_Read)) if (!CheckActive(S, OpPC, Ptr, AK_Read))
return false; return false;
+ if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
+ return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
return false; return false;
if (!CheckTemporary(S, OpPC, Ptr, AK_Read)) if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
@@ -650,6 +666,8 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false; return false;
if (!CheckDummy(S, OpPC, Ptr, AK_Assign)) if (!CheckDummy(S, OpPC, Ptr, AK_Assign))
return false; return false;
+ if (!CheckLifetime(S, OpPC, Ptr, AK_Assign))
+ return false;
if (!CheckExtern(S, OpPC, Ptr)) if (!CheckExtern(S, OpPC, Ptr))
return false; return false;
if (!CheckRange(S, OpPC, Ptr, AK_Assign)) if (!CheckRange(S, OpPC, Ptr, AK_Assign))
@@ -1546,34 +1564,38 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) { bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) {
assert(E); assert(E);
- if (S.getLangOpts().CPlusPlus26)
- return true;
-
- const auto &Loc = S.Current->getSource(OpPC);
-
if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) { if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
const FunctionDecl *OperatorNew = NewExpr->getOperatorNew(); const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
- if (!S.getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {+ if (NewExpr->getNumPlacementArgs() > 0) {
// This is allowed pre-C++26, but only an std function. // This is allowed pre-C++26, but only an std function.
- if (S.Current->isStdFunction())+ if (S.getLangOpts().CPlusPlus26 || S.Current->isStdFunction())
return true; return true;
- S.FFDiag(Loc, diag::note_constexpr_new_placement)+ S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement)
<< /*C++26 feature*/ 1 << E->getSourceRange(); << /*C++26 feature*/ 1 << E->getSourceRange();
- } else if (NewExpr->getNumPlacementArgs() == 1 &&
- !OperatorNew->isReservedGlobalPlacementOperator()) {
- S.FFDiag(Loc, diag::note_constexpr_new_placement)
- << /*Unsupported*/ 0 << E->getSourceRange();
} else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) { } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
- S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_new_non_replaceable)
<< isa<CXXMethodDecl>(OperatorNew) << OperatorNew; << isa<CXXMethodDecl>(OperatorNew) << OperatorNew;
+ return false;
+ } else if (!S.getLangOpts().CPlusPlus26 &&
+ NewExpr->getNumPlacementArgs() == 1 &&
+ !OperatorNew->isReservedGlobalPlacementOperator()) {
+ if (!S.getLangOpts().CPlusPlus26) {
+ S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_placement)
+ << /*Unsupported*/ 0 << E->getSourceRange();
+ return false;
+ }
+ return true;
} }
} else { } else {
const auto *DeleteExpr = cast<CXXDeleteExpr>(E); const auto *DeleteExpr = cast<CXXDeleteExpr>(E);
const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete(); const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) { if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
- S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_new_non_replaceable)
<< isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete; << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete;
+ return false;
} }
} }
clang/lib/AST/ByteCode/Interp.h
@@ -379,15 +379,14 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits)); APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
// Report undefined behaviour, stopping if required. // Report undefined behaviour, stopping if required.
- const Expr *E = S.Current->getExpr(OpPC);
- QualType Type = E->getType();
if (S.checkingForUndefinedBehavior()) { if (S.checkingForUndefinedBehavior()) {
+ const Expr *E = S.Current->getExpr(OpPC);
+ QualType Type = E->getType();
SmallString<32> Trunc; SmallString<32> Trunc;
Value.trunc(Result.bitWidth()) Value.trunc(Result.bitWidth())
.toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
/*UpperCase=*/true, /*InsertSeparators=*/true); /*UpperCase=*/true, /*InsertSeparators=*/true);
- auto Loc = E->getExprLoc();+ S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
- S.report(Loc, diag::warn_integer_constant_overflow)
<< Trunc << Type << E->getSourceRange(); << Trunc << Type << E->getSourceRange();
} }
@@ -737,16 +736,14 @@ bool Neg(InterpState &S, CodePtr OpPC) {
S.Stk.push<T>(Result); S.Stk.push<T>(Result);
APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1); APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1);
- const Expr *E = S.Current->getExpr(OpPC);
- QualType Type = E->getType();
-
if (S.checkingForUndefinedBehavior()) { if (S.checkingForUndefinedBehavior()) {
+ const Expr *E = S.Current->getExpr(OpPC);
+ QualType Type = E->getType();
SmallString<32> Trunc; SmallString<32> Trunc;
NegatedValue.trunc(Result.bitWidth()) NegatedValue.trunc(Result.bitWidth())
.toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
/*UpperCase=*/true, /*InsertSeparators=*/true); /*UpperCase=*/true, /*InsertSeparators=*/true);
- auto Loc = E->getExprLoc();+ S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
- S.report(Loc, diag::warn_integer_constant_overflow)
<< Trunc << Type << E->getSourceRange(); << Trunc << Type << E->getSourceRange();
return true; return true;
} }
@@ -800,15 +797,14 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
APResult = --Value.toAPSInt(Bits); APResult = --Value.toAPSInt(Bits);
// Report undefined behaviour, stopping if required. // Report undefined behaviour, stopping if required.
- const Expr *E = S.Current->getExpr(OpPC);
- QualType Type = E->getType();
if (S.checkingForUndefinedBehavior()) { if (S.checkingForUndefinedBehavior()) {
+ const Expr *E = S.Current->getExpr(OpPC);
+ QualType Type = E->getType();
SmallString<32> Trunc; SmallString<32> Trunc;
APResult.trunc(Result.bitWidth()) APResult.trunc(Result.bitWidth())
.toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false, .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
/*UpperCase=*/true, /*InsertSeparators=*/true); /*UpperCase=*/true, /*InsertSeparators=*/true);
- auto Loc = E->getExprLoc();+ S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
- S.report(Loc, diag::warn_integer_constant_overflow)
<< Trunc << Type << E->getSourceRange(); << Trunc << Type << E->getSourceRange();
return true; return true;
} }
@@ -1258,6 +1254,12 @@ bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
return true; return true;
} }
+static inline bool Kill(InterpState &S, CodePtr OpPC) {
+ const auto &Ptr = S.Stk.pop<Pointer>();
+ Ptr.endLifetime();
+ return true;
+}
+
/// 1) Pops the value from the stack. /// 1) Pops the value from the stack.
/// 2) Writes the value to the local variable with the /// 2) Writes the value to the local variable with the
/// given offset. /// given offset.
@@ -1482,7 +1484,10 @@ bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
template <PrimType Name, class T = typename PrimConv<Name>::T> template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) { bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
const T &Value = S.Stk.pop<T>(); const T &Value = S.Stk.pop<T>();
- const Pointer &Field = S.Stk.peek<Pointer>().atField(I);+ const Pointer &Ptr = S.Stk.peek<Pointer>();
+ if (!CheckRange(S, OpPC, Ptr, CSK_Field))
+ return false;
+ const Pointer &Field = Ptr.atField(I);
Field.deref<T>() = Value; Field.deref<T>() = Value;
Field.activate(); Field.activate();
Field.initialize(); Field.initialize();
clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -99,7 +99,7 @@ void InterpFrame::initScope(unsigned Idx) {
} }
void InterpFrame::destroy(unsigned Idx) { void InterpFrame::destroy(unsigned Idx) {
- for (auto &Local : Func->getScope(Idx).locals()) {+ for (auto &Local : Func->getScope(Idx).locals_reverse()) {
S.deallocate(localBlock(Local.Offset)); S.deallocate(localBlock(Local.Offset));
} }
} }
clang/lib/AST/ByteCode/Opcodes.td
@@ -394,6 +394,11 @@ def GetLocal : AccessOpcode { let HasCustomEval = 1; }
// [] -> [Pointer] // [] -> [Pointer]
def SetLocal : AccessOpcode { let HasCustomEval = 1; } def SetLocal : AccessOpcode { let HasCustomEval = 1; }
+def Kill : Opcode {
+ let Types = [];
+ let Args = [];
+}
+
def CheckDecl : Opcode { def CheckDecl : Opcode {
let Args = [ArgVarDecl]; let Args = [ArgVarDecl];
} }
clang/lib/AST/ByteCode/Pointer.h
@@ -687,6 +687,22 @@ public:
/// Deactivates an entire strurcutre. /// Deactivates an entire strurcutre.
void deactivate() const; void deactivate() const;
+ Lifetime getLifetime() const {
+ if (!isBlockPointer())
+ return Lifetime::Started;
+ if (asBlockPointer().Base < sizeof(InlineDescriptor))
+ return Lifetime::Started;
+ return getInlineDesc()->LifeState;
+ }
+
+ void endLifetime() const {
+ if (!isBlockPointer())
+ return;
+ if (asBlockPointer().Base < sizeof(InlineDescriptor))
+ return;
+ getInlineDesc()->LifeState = Lifetime::Ended;
+ }
+
/// Compare two pointers. /// Compare two pointers.
ComparisonCategoryResult compare(const Pointer &Other) const { ComparisonCategoryResult compare(const Pointer &Other) const {
if (!hasSameBase(*this, Other)) if (!hasSameBase(*this, Other))
clang/lib/AST/ByteCode/Program.cpp
@@ -18,14 +18,12 @@ using namespace clang;
using namespace clang::interp; using namespace clang::interp;
unsigned Program::getOrCreateNativePointer(const void *Ptr) { unsigned Program::getOrCreateNativePointer(const void *Ptr) {
- auto It = NativePointerIndices.find(Ptr);+ auto [It, Inserted] =
- if (It != NativePointerIndices.end())+ NativePointerIndices.try_emplace(Ptr, NativePointers.size());
- return It->second;+ if (Inserted)
+ NativePointers.push_back(Ptr);
- unsigned Idx = NativePointers.size();+ return It->second;
- NativePointers.push_back(Ptr);
- NativePointerIndices[Ptr] = Idx;
- return Idx;
} }
const void *Program::getNativePointer(unsigned Idx) { const void *Program::getNativePointer(unsigned Idx) {
@@ -35,6 +33,7 @@ const void *Program::getNativePointer(unsigned Idx) {
unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) { unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) {
const size_t CharWidth = S->getCharByteWidth(); const size_t CharWidth = S->getCharByteWidth();
const size_t BitWidth = CharWidth * Ctx.getCharBit(); const size_t BitWidth = CharWidth * Ctx.getCharBit();
+ unsigned StringLength = S->getLength();
PrimType CharType; PrimType CharType;
switch (CharWidth) { switch (CharWidth) {
@@ -55,15 +54,15 @@ unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) {
Base = S; Base = S;
// Create a descriptor for the string. // Create a descriptor for the string.
- Descriptor *Desc = allocateDescriptor(Base, CharType, Descriptor::GlobalMD,+ Descriptor *Desc =
- S->getLength() + 1,+ allocateDescriptor(Base, CharType, Descriptor::GlobalMD, StringLength + 1,
- /*isConst=*/true,+ /*isConst=*/true,
- /*isTemporary=*/false,+ /*isTemporary=*/false,
- /*isMutable=*/false);+ /*isMutable=*/false);
// Allocate storage for the string. // Allocate storage for the string.
// The byte length does not include the null terminator. // The byte length does not include the null terminator.
- unsigned I = Globals.size();+ unsigned GlobalIndex = Globals.size();
unsigned Sz = Desc->getAllocSize(); unsigned Sz = Desc->getAllocSize();
auto *G = new (Allocator, Sz) Global(Ctx.getEvalID(), Desc, /*isStatic=*/true, auto *G = new (Allocator, Sz) Global(Ctx.getEvalID(), Desc, /*isStatic=*/true,
/*isExtern=*/false); /*isExtern=*/false);
@@ -74,33 +73,32 @@ unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) {
// Construct the string in storage. // Construct the string in storage.
const Pointer Ptr(G->block()); const Pointer Ptr(G->block());
- for (unsigned I = 0, N = S->getLength(); I <= N; ++I) {+ for (unsigned I = 0; I <= StringLength; ++I) {
- Pointer Field = Ptr.atIndex(I).narrow();+ Pointer Field = Ptr.atIndex(I);
- const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I);+ const uint32_t CodePoint = I == StringLength ? 0 : S->getCodeUnit(I);
switch (CharType) { switch (CharType) {
case PT_Sint8: { case PT_Sint8: {
using T = PrimConv<PT_Sint8>::T; using T = PrimConv<PT_Sint8>::T;
Field.deref<T>() = T::from(CodePoint, BitWidth); Field.deref<T>() = T::from(CodePoint, BitWidth);
- Field.initialize();
break; break;
} }
case PT_Uint16: { case PT_Uint16: {
using T = PrimConv<PT_Uint16>::T; using T = PrimConv<PT_Uint16>::T;
Field.deref<T>() = T::from(CodePoint, BitWidth); Field.deref<T>() = T::from(CodePoint, BitWidth);
- Field.initialize();
break; break;
} }
case PT_Uint32: { case PT_Uint32: {
using T = PrimConv<PT_Uint32>::T; using T = PrimConv<PT_Uint32>::T;
Field.deref<T>() = T::from(CodePoint, BitWidth); Field.deref<T>() = T::from(CodePoint, BitWidth);
- Field.initialize();
break; break;
} }
default: default:
llvm_unreachable("unsupported character type"); llvm_unreachable("unsupported character type");
} }
} }
- return I;+ Ptr.initialize();
+
+ return GlobalIndex;
} }
Pointer Program::getPtrGlobal(unsigned Idx) const { Pointer Program::getPtrGlobal(unsigned Idx) const {
clang/lib/AST/CommentLexer.cpp
@@ -196,6 +196,15 @@ const char *skipWhitespace(const char *BufferPtr, const char *BufferEnd) {
return BufferEnd; return BufferEnd;
} }
+const char *skipHorizontalWhitespace(const char *BufferPtr,
+ const char *BufferEnd) {
+ for (; BufferPtr != BufferEnd; ++BufferPtr) {
+ if (!isHorizontalWhitespace(*BufferPtr))
+ return BufferPtr;
+ }
+ return BufferEnd;
+}
+
bool isWhitespace(const char *BufferPtr, const char *BufferEnd) { bool isWhitespace(const char *BufferPtr, const char *BufferEnd) {
return skipWhitespace(BufferPtr, BufferEnd) == BufferEnd; return skipWhitespace(BufferPtr, BufferEnd) == BufferEnd;
} }
@@ -637,17 +646,41 @@ void Lexer::setupAndLexHTMLStartTag(Token &T) {
formTokenWithChars(T, TagNameEnd, tok::html_start_tag); formTokenWithChars(T, TagNameEnd, tok::html_start_tag);
T.setHTMLTagStartName(Name); T.setHTMLTagStartName(Name);
- BufferPtr = skipWhitespace(BufferPtr, CommentEnd);+ BufferPtr = skipHorizontalWhitespace(BufferPtr, CommentEnd);
+ if (BufferPtr == CommentEnd) { // in BCPL comments
+ State = LS_HTMLStartTag;
+ return;
+ }
const char C = *BufferPtr; const char C = *BufferPtr;
if (BufferPtr != CommentEnd && if (BufferPtr != CommentEnd &&
- (C == '>' || C == '/' || isHTMLIdentifierStartingCharacter(C)))+ (C == '>' || C == '/' || isVerticalWhitespace(C) ||
+ isHTMLIdentifierStartingCharacter(C)))
State = LS_HTMLStartTag; State = LS_HTMLStartTag;
} }
void Lexer::lexHTMLStartTag(Token &T) { void Lexer::lexHTMLStartTag(Token &T) {
assert(State == LS_HTMLStartTag); assert(State == LS_HTMLStartTag);
+ // Skip leading whitespace and comment decorations
+ while (isVerticalWhitespace(*BufferPtr)) {
+ BufferPtr = skipNewline(BufferPtr, CommentEnd);
+
+ if (CommentState == LCS_InsideCComment)
+ skipLineStartingDecorations();
+
+ BufferPtr = skipHorizontalWhitespace(BufferPtr, CommentEnd);
+ if (BufferPtr == CommentEnd) {
+ // HTML starting tags must be defined in a single comment block.
+ // It's likely a user-error where they forgot to terminate the comment.
+ State = LS_Normal;
+ // Since at least one newline was skipped and one token needs to be lexed,
+ // return a newline.
+ formTokenWithChars(T, BufferPtr, tok::newline);
+ return;
+ }
+ }
+
const char *TokenPtr = BufferPtr; const char *TokenPtr = BufferPtr;
char C = *TokenPtr; char C = *TokenPtr;
if (isHTMLIdentifierCharacter(C)) { if (isHTMLIdentifierCharacter(C)) {
@@ -693,14 +726,13 @@ void Lexer::lexHTMLStartTag(Token &T) {
// Now look ahead and return to normal state if we don't see any HTML tokens // Now look ahead and return to normal state if we don't see any HTML tokens
// ahead. // ahead.
- BufferPtr = skipWhitespace(BufferPtr, CommentEnd);+ BufferPtr = skipHorizontalWhitespace(BufferPtr, CommentEnd);
if (BufferPtr == CommentEnd) { if (BufferPtr == CommentEnd) {
- State = LS_Normal;
return; return;
} }
C = *BufferPtr; C = *BufferPtr;
- if (!isHTMLIdentifierStartingCharacter(C) &&+ if (!isHTMLIdentifierStartingCharacter(C) && !isVerticalWhitespace(C) &&
C != '=' && C != '\"' && C != '\'' && C != '>' && C != '/') { C != '=' && C != '\"' && C != '\'' && C != '>' && C != '/') {
State = LS_Normal; State = LS_Normal;
return; return;
@@ -774,8 +806,17 @@ again:
BufferPtr++; BufferPtr++;
CommentState = LCS_InsideBCPLComment; CommentState = LCS_InsideBCPLComment;
- if (State != LS_VerbatimBlockBody && State != LS_VerbatimBlockFirstLine)+ switch (State) {
+ case LS_VerbatimBlockFirstLine:
+ case LS_VerbatimBlockBody:
+ break;
+ case LS_HTMLStartTag:
+ BufferPtr = skipHorizontalWhitespace(BufferPtr, BufferEnd);
+ break;
+ default:
State = LS_Normal; State = LS_Normal;
+ break;
+ }
CommentEnd = findBCPLCommentEnd(BufferPtr, BufferEnd); CommentEnd = findBCPLCommentEnd(BufferPtr, BufferEnd);
goto again; goto again;
} }
@@ -807,6 +848,14 @@ again:
while(EndWhitespace != BufferEnd && *EndWhitespace != '/') while(EndWhitespace != BufferEnd && *EndWhitespace != '/')
EndWhitespace++; EndWhitespace++;
+ // When lexing the start of an HTML tag (i.e. going through the attributes)
+ // there won't be any newlines generated.
+ if (State == LS_HTMLStartTag && EndWhitespace != BufferEnd) {
+ CommentState = LCS_BeforeComment;
+ BufferPtr = EndWhitespace;
+ goto again;
+ }
+
// Turn any whitespace between comments (and there is only whitespace // Turn any whitespace between comments (and there is only whitespace
// between them -- guaranteed by comment extraction) into a newline. We // between them -- guaranteed by comment extraction) into a newline. We
// have two newlines between C comments in total (first one was synthesized // have two newlines between C comments in total (first one was synthesized
@@ -829,6 +878,14 @@ again:
BufferPtr += 2; BufferPtr += 2;
assert(BufferPtr <= BufferEnd); assert(BufferPtr <= BufferEnd);
+ // When lexing the start of an HTML tag (i.e. going through the
+ // attributes) there won't be any newlines generated - whitespace still
+ // needs to be skipped.
+ if (State == LS_HTMLStartTag && BufferPtr != BufferEnd) {
+ CommentState = LCS_BetweenComments;
+ goto again;
+ }
+
// Synthenize newline just after the C comment, regardless if there is // Synthenize newline just after the C comment, regardless if there is
// actually a newline. // actually a newline.
formTokenWithChars(T, BufferPtr, tok::newline); formTokenWithChars(T, BufferPtr, tok::newline);
clang/lib/AST/Decl.cpp
@@ -3065,6 +3065,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.IsIneligibleOrNotSelected = false; FunctionDeclBits.IsIneligibleOrNotSelected = false;
FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.HasImplicitReturnZero = false;
FunctionDeclBits.IsLateTemplateParsed = false; FunctionDeclBits.IsLateTemplateParsed = false;
+ FunctionDeclBits.IsInstantiatedFromMemberTemplate = false;
FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind); FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind);
FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false; FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false;
FunctionDeclBits.InstantiationIsPending = false; FunctionDeclBits.InstantiationIsPending = false;
clang/lib/AST/DeclBase.cpp
@@ -1203,6 +1203,8 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
if (Ty->isFunctionPointerType()) if (Ty->isFunctionPointerType())
Ty = Ty->castAs<PointerType>()->getPointeeType(); Ty = Ty->castAs<PointerType>()->getPointeeType();
+ else if (Ty->isMemberFunctionPointerType())
+ Ty = Ty->castAs<MemberPointerType>()->getPointeeType();
else if (Ty->isFunctionReferenceType()) else if (Ty->isFunctionReferenceType())
Ty = Ty->castAs<ReferenceType>()->getPointeeType(); Ty = Ty->castAs<ReferenceType>()->getPointeeType();
else if (BlocksToo && Ty->isBlockPointerType()) else if (BlocksToo && Ty->isBlockPointerType())
clang/lib/AST/DeclTemplate.cpp
@@ -957,18 +957,17 @@ FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
// ClassTemplateSpecializationDecl Implementation // ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
-ClassTemplateSpecializationDecl::+ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(
-ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,+ ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC,
- DeclContext *DC, SourceLocation StartLoc,+ SourceLocation StartLoc, SourceLocation IdLoc,
- SourceLocation IdLoc,+ ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
- ClassTemplateDecl *SpecializedTemplate,+ bool StrictPackMatch, ClassTemplateSpecializationDecl *PrevDecl)
- ArrayRef<TemplateArgument> Args,
- ClassTemplateSpecializationDecl *PrevDecl)
: CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc, : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate->getIdentifier(), PrevDecl),
- SpecializedTemplate(SpecializedTemplate),+ SpecializedTemplate(SpecializedTemplate),
- TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),+ TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
- SpecializationKind(TSK_Undeclared) {+ SpecializationKind(TSK_Undeclared), StrictPackMatch(StrictPackMatch) {
+ assert(DK == Kind::ClassTemplateSpecialization || StrictPackMatch == false);
} }
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
@@ -977,18 +976,14 @@ ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
SourceLocation(), nullptr, nullptr), SourceLocation(), nullptr, nullptr),
SpecializationKind(TSK_Undeclared) {} SpecializationKind(TSK_Undeclared) {}
-ClassTemplateSpecializationDecl *+ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
-ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,+ ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
- DeclContext *DC,+ SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate,
- SourceLocation StartLoc,+ ArrayRef<TemplateArgument> Args, bool StrictPackMatch,
- SourceLocation IdLoc,+ ClassTemplateSpecializationDecl *PrevDecl) {
- ClassTemplateDecl *SpecializedTemplate,+ auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
- ArrayRef<TemplateArgument> Args,+ Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
- ClassTemplateSpecializationDecl *PrevDecl) {+ SpecializedTemplate, Args, StrictPackMatch, PrevDecl);
- auto *Result =
- new (Context, DC) ClassTemplateSpecializationDecl(
- Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
- SpecializedTemplate, Args, PrevDecl);
Result->setMayHaveOutOfDateDef(false); Result->setMayHaveOutOfDateDef(false);
// If the template decl is incomplete, copy the external lexical storage from // If the template decl is incomplete, copy the external lexical storage from
@@ -1175,7 +1170,9 @@ ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *PrevDecl) ClassTemplatePartialSpecializationDecl *PrevDecl)
: ClassTemplateSpecializationDecl( : ClassTemplateSpecializationDecl(
Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc, Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
- SpecializedTemplate, Args, PrevDecl),+ // Tracking StrictPackMatch for Partial
+ // Specializations is not needed.
+ SpecializedTemplate, Args, /*StrictPackMatch=*/false, PrevDecl),
TemplateParams(Params), InstantiatedFromMember(nullptr, false) { TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
if (AdoptTemplateParameterList(Params, this)) if (AdoptTemplateParameterList(Params, this))
setInvalidDecl(); setInvalidDecl();
clang/lib/AST/Expr.cpp
@@ -1956,6 +1956,7 @@ bool CastExpr::CastConsistency() const {
case CK_FixedPointToBoolean: case CK_FixedPointToBoolean:
case CK_HLSLArrayRValue: case CK_HLSLArrayRValue:
case CK_HLSLVectorTruncation: case CK_HLSLVectorTruncation:
+ case CK_HLSLElementwiseCast:
CheckNoBasePath: CheckNoBasePath:
assert(path_empty() && "Cast kind should not have a base path!"); assert(path_empty() && "Cast kind should not have a base path!");
break; break;
clang/lib/AST/ExprConstant.cpp
@@ -12536,10 +12536,9 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) {
static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
assert(!LVal.Designator.Invalid); assert(!LVal.Designator.Invalid);
- auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) {+ auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD) {
const RecordDecl *Parent = FD->getParent(); const RecordDecl *Parent = FD->getParent();
- Invalid = Parent->isInvalidDecl();+ if (Parent->isInvalidDecl() || Parent->isUnion())
- if (Invalid || Parent->isUnion())
return true; return true;
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent); const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent);
return FD->getFieldIndex() + 1 == Layout.getFieldCount(); return FD->getFieldIndex() + 1 == Layout.getFieldCount();
@@ -12548,14 +12547,12 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
auto &Base = LVal.getLValueBase(); auto &Base = LVal.getLValueBase();
if (auto *ME = dyn_cast_or_null<MemberExpr>(Base.dyn_cast<const Expr *>())) { if (auto *ME = dyn_cast_or_null<MemberExpr>(Base.dyn_cast<const Expr *>())) {
if (auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { if (auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
- bool Invalid;+ if (!IsLastOrInvalidFieldDecl(FD))
- if (!IsLastOrInvalidFieldDecl(FD, Invalid))+ return false;
- return Invalid;
} else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) { } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) {
for (auto *FD : IFD->chain()) { for (auto *FD : IFD->chain()) {
- bool Invalid;+ if (!IsLastOrInvalidFieldDecl(cast<FieldDecl>(FD)))
- if (!IsLastOrInvalidFieldDecl(cast<FieldDecl>(FD), Invalid))+ return false;
- return Invalid;
} }
} }
} }
@@ -12591,9 +12588,8 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
return false; return false;
BaseType = CT->getElementType(); BaseType = CT->getElementType();
} else if (auto *FD = getAsField(Entry)) { } else if (auto *FD = getAsField(Entry)) {
- bool Invalid;+ if (!IsLastOrInvalidFieldDecl(FD))
- if (!IsLastOrInvalidFieldDecl(FD, Invalid))+ return false;
- return Invalid;
BaseType = FD->getType(); BaseType = FD->getType();
} else { } else {
assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); assert(getAsBaseClass(Entry) && "Expecting cast to a base class");
@@ -15047,6 +15043,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_NoOp: case CK_NoOp:
case CK_LValueToRValueBitCast: case CK_LValueToRValueBitCast:
case CK_HLSLArrayRValue: case CK_HLSLArrayRValue:
+ case CK_HLSLElementwiseCast:
return ExprEvaluatorBaseTy::VisitCastExpr(E); return ExprEvaluatorBaseTy::VisitCastExpr(E);
case CK_MemberPointerToBoolean: case CK_MemberPointerToBoolean:
@@ -15905,6 +15902,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_IntegralToFixedPoint: case CK_IntegralToFixedPoint:
case CK_MatrixCast: case CK_MatrixCast:
case CK_HLSLVectorTruncation: case CK_HLSLVectorTruncation:
+ case CK_HLSLElementwiseCast:
llvm_unreachable("invalid cast kind for complex value"); llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue: case CK_LValueToRValue:
clang/lib/AST/JSONNodeDumper.cpp
@@ -1003,6 +1003,11 @@ void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) { void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
VisitRecordDecl(RD); VisitRecordDecl(RD);
+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ if (CTSD->hasStrictPackMatch())
+ JOS.attribute("strict-pack-match", true);
+ }
+
// All other information requires a complete definition. // All other information requires a complete definition.
if (!RD->isCompleteDefinition()) if (!RD->isCompleteDefinition())
return; return;
clang/lib/AST/MicrosoftMangle.cpp
@@ -2810,49 +2810,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
break; break;
#include "clang/Basic/HLSLIntangibleTypes.def" #include "clang/Basic/HLSLIntangibleTypes.def"
-#define SVE_TYPE(Name, Id, SingletonId) \+ // Issue an error for any type not explicitly handled.
- case BuiltinType::Id:+ default:
-#define SVE_SCALAR_TYPE(Name, MangledName, Id, SingletonId, Bits)
-#include "clang/Basic/AArch64SVEACLETypes.def"
-#define PPC_VECTOR_TYPE(Name, Id, Size) \
- case BuiltinType::Id:
-#include "clang/Basic/PPCTypes.def"
-#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
-#include "clang/Basic/RISCVVTypes.def"
-#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
-#include "clang/Basic/AMDGPUTypes.def"
- case BuiltinType::ShortAccum:
- case BuiltinType::Accum:
- case BuiltinType::LongAccum:
- case BuiltinType::UShortAccum:
- case BuiltinType::UAccum:
- case BuiltinType::ULongAccum:
- case BuiltinType::ShortFract:
- case BuiltinType::Fract:
- case BuiltinType::LongFract:
- case BuiltinType::UShortFract:
- case BuiltinType::UFract:
- case BuiltinType::ULongFract:
- case BuiltinType::SatShortAccum:
- case BuiltinType::SatAccum:
- case BuiltinType::SatLongAccum:
- case BuiltinType::SatUShortAccum:
- case BuiltinType::SatUAccum:
- case BuiltinType::SatULongAccum:
- case BuiltinType::SatShortFract:
- case BuiltinType::SatFract:
- case BuiltinType::SatLongFract:
- case BuiltinType::SatUShortFract:
- case BuiltinType::SatUFract:
- case BuiltinType::SatULongFract:
- case BuiltinType::Ibm128:
- case BuiltinType::Float128: {
Error(Range.getBegin(), "built-in type: ", Error(Range.getBegin(), "built-in type: ",
T->getName(Context.getASTContext().getPrintingPolicy())) T->getName(Context.getASTContext().getPrintingPolicy()))
<< Range; << Range;
break; break;
} }
- }
} }
// <type> ::= <function-type> // <type> ::= <function-type>
clang/lib/AST/OpenMPClause.cpp
@@ -2073,6 +2073,11 @@ void OMPClausePrinter::VisitOMPNoOpenMPRoutinesClause(
OS << "no_openmp_routines"; OS << "no_openmp_routines";
} }
+void OMPClausePrinter::VisitOMPNoOpenMPConstructsClause(
+ OMPNoOpenMPConstructsClause *) {
+ OS << "no_openmp_constructs";
+}
+
void OMPClausePrinter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) { void OMPClausePrinter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {
OS << "no_parallelism"; OS << "no_parallelism";
} }
@@ -2927,9 +2932,13 @@ llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
TargetOMPContext::TargetOMPContext( TargetOMPContext::TargetOMPContext(
ASTContext &ASTCtx, std::function<void(StringRef)> &&DiagUnknownTrait, ASTContext &ASTCtx, std::function<void(StringRef)> &&DiagUnknownTrait,
const FunctionDecl *CurrentFunctionDecl, const FunctionDecl *CurrentFunctionDecl,
- ArrayRef<llvm::omp::TraitProperty> ConstructTraits)+ ArrayRef<llvm::omp::TraitProperty> ConstructTraits, int DeviceNum)
: OMPContext(ASTCtx.getLangOpts().OpenMPIsTargetDevice, : OMPContext(ASTCtx.getLangOpts().OpenMPIsTargetDevice,
- ASTCtx.getTargetInfo().getTriple()),+ ASTCtx.getTargetInfo().getTriple(),
+ ASTCtx.getLangOpts().OMPTargetTriples.empty()
+ ? llvm::Triple()
+ : ASTCtx.getLangOpts().OMPTargetTriples[0],
+ DeviceNum),
FeatureValidityCheck([&](StringRef FeatureName) { FeatureValidityCheck([&](StringRef FeatureName) {
return ASTCtx.getTargetInfo().isValidFeatureName(FeatureName); return ASTCtx.getTargetInfo().isValidFeatureName(FeatureName);
}), }),
clang/lib/AST/ParentMap.cpp
@@ -13,7 +13,6 @@
#include "clang/AST/ParentMap.h" #include "clang/AST/ParentMap.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtObjC.h" #include "clang/AST/StmtObjC.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
@@ -104,22 +103,6 @@ static void BuildParentMap(MapTy& M, Stmt* S,
BuildParentMap(M, SubStmt, OVMode); BuildParentMap(M, SubStmt, OVMode);
} }
break; break;
- case Stmt::CXXDefaultArgExprClass:
- if (auto *Arg = dyn_cast<CXXDefaultArgExpr>(S)) {
- if (Arg->hasRewrittenInit()) {
- M[Arg->getExpr()] = S;
- BuildParentMap(M, Arg->getExpr(), OVMode);
- }
- }
- break;
- case Stmt::CXXDefaultInitExprClass:
- if (auto *Init = dyn_cast<CXXDefaultInitExpr>(S)) {
- if (Init->hasRewrittenInit()) {
- M[Init->getExpr()] = S;
- BuildParentMap(M, Init->getExpr(), OVMode);
- }
- }
- break;
default: default:
for (Stmt *SubStmt : S->children()) { for (Stmt *SubStmt : S->children()) {
if (SubStmt) { if (SubStmt) {
clang/lib/AST/RawCommentList.cpp
@@ -287,13 +287,13 @@ void RawCommentList::addComment(const RawComment &RC,
// If this is the first Doxygen comment, save it (because there isn't // If this is the first Doxygen comment, save it (because there isn't
// anything to merge it with). // anything to merge it with).
- if (OrderedComments[CommentFile].empty()) {+ auto &OC = OrderedComments[CommentFile];
- OrderedComments[CommentFile][CommentOffset] =+ if (OC.empty()) {
- new (Allocator) RawComment(RC);+ OC[CommentOffset] = new (Allocator) RawComment(RC);
return; return;
} }
- const RawComment &C1 = *OrderedComments[CommentFile].rbegin()->second;+ const RawComment &C1 = *OC.rbegin()->second;
const RawComment &C2 = RC; const RawComment &C2 = RC;
// Merge comments only if there is only whitespace between them. // Merge comments only if there is only whitespace between them.
clang/lib/AST/StmtOpenACC.cpp
@@ -305,3 +305,19 @@ OpenACCUpdateConstruct::Create(const ASTContext &C, SourceLocation Start,
new (Mem) OpenACCUpdateConstruct(Start, DirectiveLoc, End, Clauses); new (Mem) OpenACCUpdateConstruct(Start, DirectiveLoc, End, Clauses);
return Inst; return Inst;
} }
+
+OpenACCAtomicConstruct *
+OpenACCAtomicConstruct::CreateEmpty(const ASTContext &C) {
+ void *Mem = C.Allocate(sizeof(OpenACCAtomicConstruct));
+ auto *Inst = new (Mem) OpenACCAtomicConstruct(EmptyShell{});
+ return Inst;
+}
+
+OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create(
+ const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
+ OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt) {
+ void *Mem = C.Allocate(sizeof(OpenACCAtomicConstruct));
+ auto *Inst = new (Mem)
+ OpenACCAtomicConstruct(Start, DirectiveLoc, AtKind, End, AssociatedStmt);
+ return Inst;
+}
clang/lib/AST/StmtPrinter.cpp
@@ -1242,6 +1242,16 @@ void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
OS << '\n'; OS << '\n';
} }
+void StmtPrinter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
+ Indent() << "#pragma acc atomic";
+
+ if (S->getAtomicKind() != OpenACCAtomicKind::None)
+ OS << " " << S->getAtomicKind();
+
+ OS << '\n';
+ PrintStmt(S->getAssociatedStmt());
+}
+
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Expr printing methods. // Expr printing methods.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@@ -1967,7 +1977,6 @@ void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) {
void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
const char *Name = nullptr; const char *Name = nullptr;
switch (Node->getOp()) { switch (Node->getOp()) {
-#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
case AtomicExpr::AO ## ID: \ case AtomicExpr::AO ## ID: \
Name = #ID "("; \ Name = #ID "("; \
clang/lib/AST/StmtProfile.cpp
@@ -606,6 +606,9 @@ void OMPClauseProfiler::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
void OMPClauseProfiler::VisitOMPNoOpenMPRoutinesClause( void OMPClauseProfiler::VisitOMPNoOpenMPRoutinesClause(
const OMPNoOpenMPRoutinesClause *) {} const OMPNoOpenMPRoutinesClause *) {}
+void OMPClauseProfiler::VisitOMPNoOpenMPConstructsClause(
+ const OMPNoOpenMPConstructsClause *) {}
+
void OMPClauseProfiler::VisitOMPNoParallelismClause( void OMPClauseProfiler::VisitOMPNoParallelismClause(
const OMPNoParallelismClause *) {} const OMPNoParallelismClause *) {}
@@ -2809,6 +2812,11 @@ void StmtProfiler::VisitOpenACCUpdateConstruct(
P.VisitOpenACCClauseList(S->clauses()); P.VisitOpenACCClauseList(S->clauses());
} }
+void StmtProfiler::VisitOpenACCAtomicConstruct(
+ const OpenACCAtomicConstruct *S) {
+ VisitStmt(S);
+}
+
void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) { void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) {
VisitStmt(S); VisitStmt(S);
} }
clang/lib/AST/TextNodeDumper.cpp
@@ -2525,8 +2525,11 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
OS << " instantiated_from"; OS << " instantiated_from";
dumpPointer(Instance); dumpPointer(Instance);
} }
- if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
dumpTemplateSpecializationKind(CTSD->getSpecializationKind()); dumpTemplateSpecializationKind(CTSD->getSpecializationKind());
+ if (CTSD->hasStrictPackMatch())
+ OS << " strict-pack-match";
+ }
dumpNestedNameSpecifier(D->getQualifier()); dumpNestedNameSpecifier(D->getQualifier());
@@ -3041,6 +3044,12 @@ void TextNodeDumper::VisitOpenACCUpdateConstruct(
VisitOpenACCConstructStmt(S); VisitOpenACCConstructStmt(S);
} }
+void TextNodeDumper::VisitOpenACCAtomicConstruct(
+ const OpenACCAtomicConstruct *S) {
+ VisitOpenACCConstructStmt(S);
+ OS << ' ' << S->getAtomicKind();
+}
+
void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) { void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
AddChild("begin", [=] { OS << S->getStartingElementPos(); }); AddChild("begin", [=] { OS << S->getStartingElementPos(); });
AddChild("number of elements", [=] { OS << S->getDataElementCount(); }); AddChild("number of elements", [=] { OS << S->getDataElementCount(); });
clang/lib/AST/VTableBuilder.cpp
@@ -1169,12 +1169,13 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
// //
// Do not set ThunkInfo::Method if Idx is already in VTableThunks. This // Do not set ThunkInfo::Method if Idx is already in VTableThunks. This
// can happen when covariant return adjustment is required too. // can happen when covariant return adjustment is required too.
- if (!VTableThunks.count(Idx)) {+ auto [It, Inserted] = VTableThunks.try_emplace(Idx);
+ if (Inserted) {
const CXXMethodDecl *Method = VTables.findOriginalMethodInMap(MD); const CXXMethodDecl *Method = VTables.findOriginalMethodInMap(MD);
- VTableThunks[Idx].Method = Method;+ It->second.Method = Method;
- VTableThunks[Idx].ThisType = Method->getThisType().getTypePtr();+ It->second.ThisType = Method->getThisType().getTypePtr();
} }
- VTableThunks[Idx].This = ThisAdjustment;+ It->second.This = ThisAdjustment;
}; };
SetThisAdjustmentThunk(VTableIndex); SetThisAdjustmentThunk(VTableIndex);
@@ -1653,8 +1654,9 @@ void ItaniumVTableBuilder::AddMethods(
// findOriginalMethod to find the method that created the entry if the // findOriginalMethod to find the method that created the entry if the
// method in the entry requires adjustment. // method in the entry requires adjustment.
if (!ReturnAdjustment.isEmpty()) { if (!ReturnAdjustment.isEmpty()) {
- VTableThunks[Components.size()].Method = MD;+ auto &VTT = VTableThunks[Components.size()];
- VTableThunks[Components.size()].ThisType = MD->getThisType().getTypePtr();+ VTT.Method = MD;
+ VTT.ThisType = MD->getThisType().getTypePtr();
} }
AddMethod(Overrider.Method, ReturnAdjustment); AddMethod(Overrider.Method, ReturnAdjustment);
clang/lib/Analysis/CFG.cpp
@@ -556,10 +556,6 @@ public:
private: private:
// Visitors to walk an AST and construct the CFG. // Visitors to walk an AST and construct the CFG.
- CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default,
- AddStmtChoice asc);
- CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default,
- AddStmtChoice asc);
CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc); CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc); CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
@@ -2045,6 +2041,8 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
} }
// First destroy member objects. // First destroy member objects.
+ if (RD->isUnion())
+ return;
for (auto *FI : RD->fields()) { for (auto *FI : RD->fields()) {
// Check for constant size array. Set type to array element type. // Check for constant size array. Set type to array element type.
QualType QT = FI->getType(); QualType QT = FI->getType();
@@ -2265,10 +2263,16 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
asc, ExternallyDestructed); asc, ExternallyDestructed);
case Stmt::CXXDefaultArgExprClass: case Stmt::CXXDefaultArgExprClass:
- return VisitCXXDefaultArgExpr(cast<CXXDefaultArgExpr>(S), asc);
-
case Stmt::CXXDefaultInitExprClass: case Stmt::CXXDefaultInitExprClass:
- return VisitCXXDefaultInitExpr(cast<CXXDefaultInitExpr>(S), asc);+ // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
+ // called function's declaration, not by the caller. If we simply add
+ // this expression to the CFG, we could end up with the same Expr
+ // appearing multiple times (PR13385).
+ //
+ // It's likewise possible for multiple CXXDefaultInitExprs for the same
+ // expression to be used in the same function (through aggregate
+ // initialization).
+ return VisitStmt(S, asc);
case Stmt::CXXBindTemporaryExprClass: case Stmt::CXXBindTemporaryExprClass:
return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
@@ -2438,40 +2442,6 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
return B; return B;
} }
-CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg,
- AddStmtChoice asc) {
- if (Arg->hasRewrittenInit()) {
- if (asc.alwaysAdd(*this, Arg)) {
- autoCreateBlock();
- appendStmt(Block, Arg);
- }
- return VisitStmt(Arg->getExpr(), asc);
- }
-
- // We can't add the default argument if it's not rewritten because the
- // expression inside a CXXDefaultArgExpr is owned by the called function's
- // declaration, not by the caller, we could end up with the same expression
- // appearing multiple times.
- return VisitStmt(Arg, asc);
-}
-
-CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init,
- AddStmtChoice asc) {
- if (Init->hasRewrittenInit()) {
- if (asc.alwaysAdd(*this, Init)) {
- autoCreateBlock();
- appendStmt(Block, Init);
- }
- return VisitStmt(Init->getExpr(), asc);
- }
-
- // We can't add the default initializer if it's not rewritten because multiple
- // CXXDefaultInitExprs for the same sub-expression to be used in the same
- // function (through aggregate initialization). we could end up with the same
- // expression appearing multiple times.
- return VisitStmt(Init, asc);
-}
-
CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) { CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
if (asc.alwaysAdd(*this, ILE)) { if (asc.alwaysAdd(*this, ILE)) {
autoCreateBlock(); autoCreateBlock();
clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
@@ -42,7 +42,8 @@ bool hasSmartPointerClassShape(const CXXRecordDecl &RD, bool &HasGet,
HasStar = true; HasStar = true;
StarReturnType = MD->getReturnType() StarReturnType = MD->getReturnType()
.getNonReferenceType() .getNonReferenceType()
- ->getCanonicalTypeUnqualified();+ ->getCanonicalTypeUnqualified()
+ .getUnqualifiedType();
} }
break; break;
case OO_Arrow: case OO_Arrow:
@@ -50,7 +51,8 @@ bool hasSmartPointerClassShape(const CXXRecordDecl &RD, bool &HasGet,
HasArrow = true; HasArrow = true;
ArrowReturnType = MD->getReturnType() ArrowReturnType = MD->getReturnType()
->getPointeeType() ->getPointeeType()
- ->getCanonicalTypeUnqualified();+ ->getCanonicalTypeUnqualified()
+ .getUnqualifiedType();
} }
break; break;
case OO_None: { case OO_None: {
@@ -62,14 +64,16 @@ bool hasSmartPointerClassShape(const CXXRecordDecl &RD, bool &HasGet,
HasGet = true; HasGet = true;
GetReturnType = MD->getReturnType() GetReturnType = MD->getReturnType()
->getPointeeType() ->getPointeeType()
- ->getCanonicalTypeUnqualified();+ ->getCanonicalTypeUnqualified()
+ .getUnqualifiedType();
} }
} else if (II->isStr("value")) { } else if (II->isStr("value")) {
if (MD->getReturnType()->isReferenceType()) { if (MD->getReturnType()->isReferenceType()) {
HasValue = true; HasValue = true;
ValueReturnType = MD->getReturnType() ValueReturnType = MD->getReturnType()
.getNonReferenceType() .getNonReferenceType()
- ->getCanonicalTypeUnqualified();+ ->getCanonicalTypeUnqualified()
+ .getUnqualifiedType();
} }
} }
} break; } break;
clang/lib/Analysis/ProgramPoint.cpp
@@ -49,6 +49,121 @@ LLVM_DUMP_METHOD void ProgramPoint::dump() const {
return printJson(llvm::errs()); return printJson(llvm::errs());
} }
+StringRef ProgramPoint::getProgramPointKindName(Kind K) {
+ switch (K) {
+ case BlockEdgeKind:
+ return "BlockEdge";
+ case BlockEntranceKind:
+ return "BlockEntrance";
+ case BlockExitKind:
+ return "BlockExit";
+ case PreStmtKind:
+ return "PreStmt";
+ case PreStmtPurgeDeadSymbolsKind:
+ return "PreStmtPurgeDeadSymbols";
+ case PostStmtPurgeDeadSymbolsKind:
+ return "PostStmtPurgeDeadSymbols";
+ case PostStmtKind:
+ return "PostStmt";
+ case PreLoadKind:
+ return "PreLoad";
+ case PostLoadKind:
+ return "PostLoad";
+ case PreStoreKind:
+ return "PreStore";
+ case PostStoreKind:
+ return "PostStore";
+ case PostConditionKind:
+ return "PostCondition";
+ case PostLValueKind:
+ return "PostLValue";
+ case PostAllocatorCallKind:
+ return "PostAllocatorCall";
+ case PostInitializerKind:
+ return "PostInitializer";
+ case CallEnterKind:
+ return "CallEnter";
+ case CallExitBeginKind:
+ return "CallExitBegin";
+ case CallExitEndKind:
+ return "CallExitEnd";
+ case FunctionExitKind:
+ return "FunctionExit";
+ case PreImplicitCallKind:
+ return "PreImplicitCall";
+ case PostImplicitCallKind:
+ return "PostImplicitCall";
+ case LoopExitKind:
+ return "LoopExit";
+ case EpsilonKind:
+ return "Epsilon";
+ }
+ llvm_unreachable("Unknown ProgramPoint kind");
+}
+
+std::optional<SourceLocation> ProgramPoint::getSourceLocation() const {
+ switch (getKind()) {
+ case BlockEdgeKind:
+ // If needed, the source and or destination beginning can be used to get
+ // source location.
+ return std::nullopt;
+ case BlockEntranceKind:
+ // If needed, first statement of the block can be used.
+ return std::nullopt;
+ case BlockExitKind:
+ if (const auto *B = castAs<BlockExit>().getBlock()) {
+ if (const auto *T = B->getTerminatorStmt()) {
+ return T->getBeginLoc();
+ }
+ }
+ return std::nullopt;
+ case PreStmtKind:
+ case PreStmtPurgeDeadSymbolsKind:
+ case PostStmtPurgeDeadSymbolsKind:
+ case PostStmtKind:
+ case PreLoadKind:
+ case PostLoadKind:
+ case PreStoreKind:
+ case PostStoreKind:
+ case PostConditionKind:
+ case PostLValueKind:
+ case PostAllocatorCallKind:
+ if (const Stmt *S = castAs<StmtPoint>().getStmt())
+ return S->getBeginLoc();
+ return std::nullopt;
+ case PostInitializerKind:
+ if (const auto *Init = castAs<PostInitializer>().getInitializer())
+ return Init->getSourceLocation();
+ return std::nullopt;
+ case CallEnterKind:
+ if (const Stmt *S = castAs<CallEnter>().getCallExpr())
+ return S->getBeginLoc();
+ return std::nullopt;
+ case CallExitBeginKind:
+ if (const Stmt *S = castAs<CallExitBegin>().getReturnStmt())
+ return S->getBeginLoc();
+ return std::nullopt;
+ case CallExitEndKind:
+ return std::nullopt;
+ case FunctionExitKind:
+ if (const auto *B = castAs<FunctionExitPoint>().getBlock();
+ B && B->getTerminatorStmt())
+ return B->getTerminatorStmt()->getBeginLoc();
+ return std::nullopt;
+ case PreImplicitCallKind:
+ return castAs<ImplicitCallPoint>().getLocation();
+ case PostImplicitCallKind:
+ return castAs<ImplicitCallPoint>().getLocation();
+ case LoopExitKind:
+ if (const Stmt *S = castAs<LoopExit>().getLoopStmt())
+ return S->getBeginLoc();
+ return std::nullopt;
+ case EpsilonKind:
+ return std::nullopt;
+ }
+ llvm_unreachable("Unknown ProgramPoint kind");
+}
+
void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const { void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
const ASTContext &Context = const ASTContext &Context =
getLocationContext()->getAnalysisDeclContext()->getASTContext(); getLocationContext()->getAnalysisDeclContext()->getASTContext();
clang/lib/Analysis/ReachableCode.cpp
@@ -454,12 +454,11 @@ bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
return isDeadRoot; return isDeadRoot;
} }
-// Check if the given `DeadStmt` is one of target statements or is a sub-stmt of+// Check if the given `DeadStmt` is a coroutine statement and is a substmt of
-// them. `Block` is the CFGBlock containing the `DeadStmt`.+// the coroutine statement. `Block` is the CFGBlock containing the `DeadStmt`.
-template <class... Ts>+static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) {
-static bool isDeadStmtInOneOf(const Stmt *DeadStmt, const CFGBlock *Block) {
// The coroutine statement, co_return, co_await, or co_yield. // The coroutine statement, co_return, co_await, or co_yield.
- const Stmt *TargetStmt = nullptr;+ const Stmt *CoroStmt = nullptr;
// Find the first coroutine statement after the DeadStmt in the block. // Find the first coroutine statement after the DeadStmt in the block.
bool AfterDeadStmt = false; bool AfterDeadStmt = false;
for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I != E; for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I != E;
@@ -468,27 +467,32 @@ static bool isDeadStmtInOneOf(const Stmt *DeadStmt, const CFGBlock *Block) {
const Stmt *S = CS->getStmt(); const Stmt *S = CS->getStmt();
if (S == DeadStmt) if (S == DeadStmt)
AfterDeadStmt = true; AfterDeadStmt = true;
- if (AfterDeadStmt && llvm::isa<Ts...>(S)) {+ if (AfterDeadStmt &&
- TargetStmt = S;+ // For simplicity, we only check simple coroutine statements.
+ (llvm::isa<CoreturnStmt>(S) || llvm::isa<CoroutineSuspendExpr>(S))) {
+ CoroStmt = S;
break; break;
} }
} }
- if (!TargetStmt)+ if (!CoroStmt)
return false; return false;
struct Checker : DynamicRecursiveASTVisitor { struct Checker : DynamicRecursiveASTVisitor {
const Stmt *DeadStmt; const Stmt *DeadStmt;
- bool IsSubStmtOfTargetStmt = false;+ bool CoroutineSubStmt = false;
- Checker(const Stmt *S) : DeadStmt(S) { ShouldVisitImplicitCode = true; }+ Checker(const Stmt *S) : DeadStmt(S) {
+ // Statements captured in the CFG can be implicit.
+ ShouldVisitImplicitCode = true;
+ }
bool VisitStmt(Stmt *S) override { bool VisitStmt(Stmt *S) override {
if (S == DeadStmt) if (S == DeadStmt)
- IsSubStmtOfTargetStmt = true;+ CoroutineSubStmt = true;
return true; return true;
} }
}; };
Checker checker(DeadStmt); Checker checker(DeadStmt);
- checker.TraverseStmt(const_cast<Stmt *>(TargetStmt));+ checker.TraverseStmt(const_cast<Stmt *>(CoroStmt));
- return checker.IsSubStmtOfTargetStmt;+ return checker.CoroutineSubStmt;
} }
static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) { static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) {
@@ -499,12 +503,7 @@ static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) {
// Coroutine statements are never considered dead statements, because removing // Coroutine statements are never considered dead statements, because removing
// them may change the function semantic if it is the only coroutine statement // them may change the function semantic if it is the only coroutine statement
// of the coroutine. // of the coroutine.
- //+ return !isInCoroutineStmt(S, Block);
- // If the dead stmt is a sub-stmt of CXXDefaultInitExpr and CXXDefaultArgExpr,
- // we would rather expect to find CXXDefaultInitExpr and CXXDefaultArgExpr as
- // a valid dead stmt.
- return !isDeadStmtInOneOf<CoreturnStmt, CoroutineSuspendExpr,
- CXXDefaultArgExpr, CXXDefaultInitExpr>(S, Block);
} }
const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) { const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
clang/lib/Analysis/UninitializedValues.cpp
@@ -379,8 +379,10 @@ void ClassifyRefs::classify(const Expr *E, Class C) {
} }
FindVarResult Var = findVar(E, DC); FindVarResult Var = findVar(E, DC);
- if (const DeclRefExpr *DRE = Var.getDeclRefExpr())+ if (const DeclRefExpr *DRE = Var.getDeclRefExpr()) {
- Classification[DRE] = std::max(Classification[DRE], C);+ auto &Class = Classification[DRE];
+ Class = std::max(Class, C);
+ }
} }
void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) { void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -930,7 +930,7 @@ AST_MATCHER(CallExpr, hasUnsafeSnprintfBuffer) {
// The array element type must be compatible with `char` otherwise an // The array element type must be compatible with `char` otherwise an
// explicit cast will be needed, which will make this check unreachable. // explicit cast will be needed, which will make this check unreachable.
// Therefore, the array extent is same as its' bytewise size. // Therefore, the array extent is same as its' bytewise size.
- if (Size->EvaluateAsConstantExpr(ER, Ctx)) {+ if (Size->EvaluateAsInt(ER, Ctx)) {
APSInt EVal = ER.Val.getInt(); // Size must have integer type APSInt EVal = ER.Val.getInt(); // Size must have integer type
return APSInt::compareValues(EVal, APSInt(CAT->getSize(), true)) != 0; return APSInt::compareValues(EVal, APSInt(CAT->getSize(), true)) != 0;
clang/lib/Basic/Builtins.cpp
@@ -29,54 +29,120 @@ const char *HeaderDesc::getName() const {
llvm_unreachable("Unknown HeaderDesc::HeaderID enum"); llvm_unreachable("Unknown HeaderDesc::HeaderID enum");
} }
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr unsigned NumBuiltins = Builtin::FirstTSBuiltin;
- {"not a builtin function", nullptr, nullptr, nullptr, HeaderDesc::NO_HEADER,+
- ALL_LANGUAGES},+#define GET_BUILTIN_STR_TABLE
-#define BUILTIN(ID, TYPE, ATTRS) \+#include "clang/Basic/Builtins.inc"
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+#undef GET_BUILTIN_STR_TABLE
-#define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \+
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANGS},+static constexpr Builtin::Info BuiltinInfos[] = {
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \+ Builtin::Info{}, // No-builtin info entry.
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, LANGS},+#define GET_BUILTIN_INFOS
#include "clang/Basic/Builtins.inc" #include "clang/Basic/Builtins.inc"
+#undef GET_BUILTIN_INFOS
}; };
+static_assert(std::size(BuiltinInfos) == NumBuiltins);
-const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {+std::pair<const Builtin::InfosShard &, const Builtin::Info &>
- if (ID < Builtin::FirstTSBuiltin)+Builtin::Context::getShardAndInfo(unsigned ID) const {
- return BuiltinInfo[ID];+ assert((ID < (Builtin::FirstTSBuiltin + NumTargetBuiltins +
- assert(((ID - Builtin::FirstTSBuiltin) <+ NumAuxTargetBuiltins)) &&
- (TSRecords.size() + AuxTSRecords.size())) &&
"Invalid builtin ID!"); "Invalid builtin ID!");
- if (isAuxBuiltinID(ID))+
- return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];+ ArrayRef<InfosShard> Shards = BuiltinShards;
- return TSRecords[ID - Builtin::FirstTSBuiltin];+ if (isAuxBuiltinID(ID)) {
+ Shards = AuxTargetShards;
+ ID = getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin;
+ } else if (ID >= Builtin::FirstTSBuiltin) {
+ Shards = TargetShards;
+ ID -= Builtin::FirstTSBuiltin;
+ }
+
+ // Loop over the shards to find the one matching this ID. We don't expect to
+ // have many shards and so its better to search linearly than with a binary
+ // search.
+ for (const auto &Shard : Shards) {
+ if (ID < Shard.Infos.size()) {
+ return {Shard, Shard.Infos[ID]};
+ }
+
+ ID -= Shard.Infos.size();
+ }
+ llvm_unreachable("Invalid target builtin shard structure!");
+}
+
+std::string Builtin::Info::getName(const Builtin::InfosShard &Shard) const {
+ return (Twine(Shard.NamePrefix) + (*Shard.Strings)[Offsets.Name]).str();
+}
+
+/// Return the identifier name for the specified builtin,
+/// e.g. "__builtin_abs".
+std::string Builtin::Context::getName(unsigned ID) const {
+ const auto &[Shard, I] = getShardAndInfo(ID);
+ return I.getName(Shard);
+}
+
+std::string Builtin::Context::getQuotedName(unsigned ID) const {
+ const auto &[Shard, I] = getShardAndInfo(ID);
+ return (Twine("'") + Shard.NamePrefix + (*Shard.Strings)[I.Offsets.Name] +
+ "'")
+ .str();
+}
+
+const char *Builtin::Context::getTypeString(unsigned ID) const {
+ const auto &[Shard, I] = getShardAndInfo(ID);
+ return (*Shard.Strings)[I.Offsets.Type].data();
} }
+const char *Builtin::Context::getAttributesString(unsigned ID) const {
+ const auto &[Shard, I] = getShardAndInfo(ID);
+ return (*Shard.Strings)[I.Offsets.Attributes].data();
+}
+
+const char *Builtin::Context::getRequiredFeatures(unsigned ID) const {
+ const auto &[Shard, I] = getShardAndInfo(ID);
+ return (*Shard.Strings)[I.Offsets.Features].data();
+}
+
+Builtin::Context::Context() : BuiltinShards{{&BuiltinStrings, BuiltinInfos}} {}
+
void Builtin::Context::InitializeTarget(const TargetInfo &Target, void Builtin::Context::InitializeTarget(const TargetInfo &Target,
const TargetInfo *AuxTarget) { const TargetInfo *AuxTarget) {
- assert(TSRecords.empty() && "Already initialized target?");+ assert(TargetShards.empty() && "Already initialized target?");
- TSRecords = Target.getTargetBuiltins();+ assert(NumTargetBuiltins == 0 && "Already initialized target?");
- if (AuxTarget)+ TargetShards = Target.getTargetBuiltins();
- AuxTSRecords = AuxTarget->getTargetBuiltins();+ for (const auto &Shard : TargetShards)
+ NumTargetBuiltins += Shard.Infos.size();
+ if (AuxTarget) {
+ AuxTargetShards = AuxTarget->getTargetBuiltins();
+ for (const auto &Shard : AuxTargetShards)
+ NumAuxTargetBuiltins += Shard.Infos.size();
+ }
} }
bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) { bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) {
bool InStdNamespace = FuncName.consume_front("std-"); bool InStdNamespace = FuncName.consume_front("std-");
- for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin;+ for (const auto &Shard : {InfosShard{&BuiltinStrings, BuiltinInfos}})
- ++i) {+ if (llvm::StringRef FuncNameSuffix = FuncName;
- if (FuncName == BuiltinInfo[i].Name &&+ FuncNameSuffix.consume_front(Shard.NamePrefix))
- (bool)strchr(BuiltinInfo[i].Attributes, 'z') == InStdNamespace)+ for (const auto &I : Shard.Infos)
- return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;+ if (FuncNameSuffix == (*Shard.Strings)[I.Offsets.Name] &&
- }+ (bool)strchr((*Shard.Strings)[I.Offsets.Attributes].data(), 'z') ==
+ InStdNamespace)
+ return strchr((*Shard.Strings)[I.Offsets.Attributes].data(), 'f') !=
+ nullptr;
return false; return false;
} }
/// Is this builtin supported according to the given language options? /// Is this builtin supported according to the given language options?
-static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,+static bool builtinIsSupported(const llvm::StringTable &Strings,
+ const Builtin::Info &BuiltinInfo,
const LangOptions &LangOpts) { const LangOptions &LangOpts) {
+ auto AttributesStr = Strings[BuiltinInfo.Offsets.Attributes];
+
/* Builtins Unsupported */ /* Builtins Unsupported */
- if (LangOpts.NoBuiltin && strchr(BuiltinInfo.Attributes, 'f') != nullptr)+ if (LangOpts.NoBuiltin && strchr(AttributesStr.data(), 'f') != nullptr)
return false; return false;
/* CorBuiltins Unsupported */ /* CorBuiltins Unsupported */
if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG)) if (!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG))
@@ -123,7 +189,7 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG) if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
return false; return false;
/* consteval Unsupported */ /* consteval Unsupported */
- if (!LangOpts.CPlusPlus20 && strchr(BuiltinInfo.Attributes, 'G') != nullptr)+ if (!LangOpts.CPlusPlus20 && strchr(AttributesStr.data(), 'G') != nullptr)
return false; return false;
return true; return true;
} }
@@ -132,22 +198,34 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
/// appropriate builtin ID # and mark any non-portable builtin identifiers as /// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such. /// such.
void Builtin::Context::initializeBuiltins(IdentifierTable &Table, void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
- const LangOptions& LangOpts) {+ const LangOptions &LangOpts) {
- // Step #1: mark all target-independent builtins with their ID's.+ {
- for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i)+ unsigned ID = 0;
- if (builtinIsSupported(BuiltinInfo[i], LangOpts)) {+ // Step #1: mark all target-independent builtins with their ID's.
- Table.get(BuiltinInfo[i].Name).setBuiltinID(i);+ for (const auto &Shard : BuiltinShards)
- }+ for (const auto &I : Shard.Infos) {
-+ // If this is a real builtin (ID != 0) and is supported, add it.
- // Step #2: Register target-specific builtins.+ if (ID != 0 && builtinIsSupported(*Shard.Strings, I, LangOpts))
- for (unsigned i = 0, e = TSRecords.size(); i != e; ++i)+ Table.get(I.getName(Shard)).setBuiltinID(ID);
- if (builtinIsSupported(TSRecords[i], LangOpts))+ ++ID;
- Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin);+ }
+ assert(ID == FirstTSBuiltin && "Should have added all non-target IDs!");
+
+ // Step #2: Register target-specific builtins.
+ for (const auto &Shard : TargetShards)
+ for (const auto &I : Shard.Infos) {
+ if (builtinIsSupported(*Shard.Strings, I, LangOpts))
+ Table.get(I.getName(Shard)).setBuiltinID(ID);
+ ++ID;
+ }
- // Step #3: Register target-specific builtins for AuxTarget.+ // Step #3: Register target-specific builtins for AuxTarget.
- for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i)+ for (const auto &Shard : AuxTargetShards)
- Table.get(AuxTSRecords[i].Name)+ for (const auto &I : Shard.Infos) {
- .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());+ Table.get(I.getName(Shard)).setBuiltinID(ID);
+ ++ID;
+ }
+ }
// Step #4: Unregister any builtins specified by -fno-builtin-foo. // Step #4: Unregister any builtins specified by -fno-builtin-foo.
for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) { for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) {
@@ -163,12 +241,8 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
} }
} }
-std::string Builtin::Context::getQuotedName(unsigned ID) const {
- return (llvm::Twine("'") + getName(ID) + "'").str();
-}
-
unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const { unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const {
- const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V');+ const char *WidthPos = ::strchr(getAttributesString(ID), 'V');
if (!WidthPos) if (!WidthPos)
return 0; return 0;
@@ -191,7 +265,7 @@ bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
assert(::toupper(Fmt[0]) == Fmt[1] && assert(::toupper(Fmt[0]) == Fmt[1] &&
"Format string is not in the form \"xX\""); "Format string is not in the form \"xX\"");
- const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt);+ const char *Like = ::strpbrk(getAttributesString(ID), Fmt);
if (!Like) if (!Like)
return false; return false;
@@ -218,7 +292,7 @@ bool Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
bool Builtin::Context::performsCallback(unsigned ID, bool Builtin::Context::performsCallback(unsigned ID,
SmallVectorImpl<int> &Encoding) const { SmallVectorImpl<int> &Encoding) const {
- const char *CalleePos = ::strchr(getRecord(ID).Attributes, 'C');+ const char *CalleePos = ::strchr(getAttributesString(ID), 'C');
if (!CalleePos) if (!CalleePos)
return false; return false;
clang/lib/Basic/OpenMPKinds.cpp
@@ -765,6 +765,12 @@ bool clang::isOpenMPCapturingDirective(OpenMPDirectiveKind DKind) {
return false; return false;
} }
+bool clang::isOpenMPOrderConcurrentNestableDirective(
+ OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_atomic || DKind == OMPD_loop || DKind == OMPD_simd ||
+ DKind == OMPD_parallel || isOpenMPLoopTransformationDirective(DKind);
+}
+
void clang::getOpenMPCaptureRegions( void clang::getOpenMPCaptureRegions(
SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions, SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions,
OpenMPDirectiveKind DKind) { OpenMPDirectiveKind DKind) {
clang/lib/Basic/Targets/AArch64.cpp
@@ -26,36 +26,106 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumNeonBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ NEON::FirstFp16Builtin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumFp16Builtins =
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+ NEON::FirstTSBuiltin - NEON::FirstFp16Builtin;
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumSVEBuiltins =
-#include "clang/Basic/BuiltinsNEON.def"+ SVE::FirstNeonBridgeBuiltin - NEON::FirstTSBuiltin;
-+static constexpr int NumSVENeonBridgeBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ SVE::FirstTSBuiltin - SVE::FirstNeonBridgeBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumSMEBuiltins = SME::FirstTSBuiltin - SVE::FirstTSBuiltin;
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr int NumAArch64Builtins =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ AArch64::LastTSBuiltin - SME::FirstTSBuiltin;
-#include "clang/Basic/BuiltinsSVE.def"+static constexpr int NumBuiltins =
-+ AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
-#define BUILTIN(ID, TYPE, ATTRS) \+static_assert(NumBuiltins ==
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ (NumNeonBuiltins + NumFp16Builtins + NumSVEBuiltins +
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+ NumSVENeonBridgeBuiltins + NumSMEBuiltins + NumAArch64Builtins));
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#include "clang/Basic/BuiltinsSME.def"+namespace clang {
-+namespace NEON {
-#define BUILTIN(ID, TYPE, ATTRS) \+#define GET_NEON_BUILTIN_STR_TABLE
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+#include "clang/Basic/arm_neon.inc"
-#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \+#undef GET_NEON_BUILTIN_STR_TABLE
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG},+
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr std::array<Builtin::Info, NumNeonBuiltins> BuiltinInfos = {
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+#define GET_NEON_BUILTIN_INFOS
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \+#include "clang/Basic/arm_neon.inc"
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},+#undef GET_NEON_BUILTIN_INFOS
-#include "clang/Basic/BuiltinsAArch64.def"
}; };
+namespace FP16 {
+#define GET_NEON_BUILTIN_STR_TABLE
+#include "clang/Basic/arm_fp16.inc"
+#undef GET_NEON_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumFp16Builtins> BuiltinInfos = {
+#define GET_NEON_BUILTIN_INFOS
+#include "clang/Basic/arm_fp16.inc"
+#undef GET_NEON_BUILTIN_INFOS
+};
+} // namespace FP16
+} // namespace NEON
+
+namespace SVE {
+#define GET_SVE_BUILTIN_STR_TABLE
+#include "clang/Basic/arm_sve_builtins.inc"
+#undef GET_SVE_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumSVEBuiltins> BuiltinInfos = {
+#define GET_SVE_BUILTIN_INFOS
+#include "clang/Basic/arm_sve_builtins.inc"
+#undef GET_SVE_BUILTIN_INFOS
+};
+} // namespace SVE
+
+namespace SME {
+#define GET_SME_BUILTIN_STR_TABLE
+#include "clang/Basic/arm_sme_builtins.inc"
+#undef GET_SME_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumSMEBuiltins> BuiltinInfos = {
+#define GET_SME_BUILTIN_INFOS
+#include "clang/Basic/arm_sme_builtins.inc"
+#undef GET_SME_BUILTIN_INFOS
+};
+} // namespace SME
+} // namespace clang
+
+static constexpr llvm::StringTable BuiltinSVENeonBridgeStrings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#define GET_SVE_BUILTINS
+#include "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
+#undef GET_SVE_BUILTINS
+#undef TARGET_BUILTIN
+ ;
+static constexpr llvm::StringTable BuiltinAArch64Strings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsAArch64.def"
+ ;
+
+static constexpr auto BuiltinSVENeonBridgeInfos =
+ Builtin::MakeInfos<NumSVENeonBridgeBuiltins>({
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#define GET_SVE_BUILTINS
+#include "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
+#undef GET_SVE_BUILTINS
+#undef TARGET_BUILTIN
+ });
+static constexpr auto BuiltinAArch64Infos =
+ Builtin::MakeInfos<NumAArch64Builtins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY
+#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsAArch64.def"
+ });
+
void AArch64TargetInfo::setArchFeatures() { void AArch64TargetInfo::setArchFeatures() {
if (*ArchInfo == llvm::AArch64::ARMV8R) { if (*ArchInfo == llvm::AArch64::ARMV8R) {
HasDotProd = true; HasDotProd = true;
@@ -253,11 +323,19 @@ bool AArch64TargetInfo::validateGlobalRegisterVariable(
bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
BranchProtectionInfo &BPI, BranchProtectionInfo &BPI,
+ const LangOptions &LO,
StringRef &Err) const { StringRef &Err) const {
llvm::ARM::ParsedBranchProtection PBP; llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, HasPAuthLR)) if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, HasPAuthLR))
return false; return false;
+ // GCS is currently untested with ptrauth-returns, but enabling this could be
+ // allowed in future after testing with a suitable system.
+ if (LO.PointerAuthReturns &&
+ (PBP.Scope != "none" || PBP.BranchProtectionPAuthLR ||
+ PBP.GuardedControlStack))
+ return false;
+
BPI.SignReturnAddr = BPI.SignReturnAddr =
llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope) llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
.Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf) .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
@@ -697,9 +775,17 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
} }
} }
-ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -+AArch64TargetInfo::getTargetBuiltins() const {
- Builtin::FirstTSBuiltin);+ return {
+ {&NEON::BuiltinStrings, NEON::BuiltinInfos, "__builtin_neon_"},
+ {&NEON::FP16::BuiltinStrings, NEON::FP16::BuiltinInfos,
+ "__builtin_neon_"},
+ {&SVE::BuiltinStrings, SVE::BuiltinInfos, "__builtin_sve_"},
+ {&BuiltinSVENeonBridgeStrings, BuiltinSVENeonBridgeInfos},
+ {&SME::BuiltinStrings, SME::BuiltinInfos, "__builtin_sme_"},
+ {&BuiltinAArch64Strings, BuiltinAArch64Infos},
+ };
} }
std::optional<std::pair<unsigned, unsigned>> std::optional<std::pair<unsigned, unsigned>>
clang/lib/Basic/Targets/AArch64.h
@@ -132,6 +132,7 @@ public:
bool validateBranchProtection(StringRef Spec, StringRef Arch, bool validateBranchProtection(StringRef Spec, StringRef Arch,
BranchProtectionInfo &BPI, BranchProtectionInfo &BPI,
+ const LangOptions &LO,
StringRef &Err) const override; StringRef &Err) const override;
bool isValidCPUName(StringRef Name) const override; bool isValidCPUName(StringRef Name) const override;
@@ -181,7 +182,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
std::optional<std::pair<unsigned, unsigned>> std::optional<std::pair<unsigned, unsigned>>
getVScaleRange(const LangOptions &LangOpts, getVScaleRange(const LangOptions &LangOpts,
clang/lib/Basic/Targets/AMDGPU.cpp
@@ -89,13 +89,21 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
} // namespace targets } // namespace targets
} // namespace clang } // namespace clang
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr llvm::StringTable BuiltinStrings =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
#include "clang/Basic/BuiltinsAMDGPU.def" #include "clang/Basic/BuiltinsAMDGPU.def"
-};+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsAMDGPU.def"
+});
const char *const AMDGPUTargetInfo::GCCRegNames[] = { const char *const AMDGPUTargetInfo::GCCRegNames[] = {
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
@@ -267,9 +275,9 @@ void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
!isAMDGCN(getTriple())); !isAMDGCN(getTriple()));
} }
-ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+AMDGPUTargetInfo::getTargetBuiltins() const {
- clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts, void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
clang/lib/Basic/Targets/AMDGPU.h
@@ -257,7 +257,7 @@ public:
StringRef CPU, StringRef CPU,
const std::vector<std::string> &FeatureVec) const override; const std::vector<std::string> &FeatureVec) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool useFP16ConversionIntrinsics() const override { return false; } bool useFP16ConversionIntrinsics() const override { return false; }
clang/lib/Basic/Targets/ARC.h
@@ -40,7 +40,9 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList; return TargetInfo::VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/ARM.cpp
@@ -405,6 +405,7 @@ bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {
bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch, bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,
BranchProtectionInfo &BPI, BranchProtectionInfo &BPI,
+ const LangOptions &LO,
StringRef &Err) const { StringRef &Err) const {
llvm::ARM::ParsedBranchProtection PBP; llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err)) if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
@@ -1074,31 +1075,99 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
} }
} }
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins = ARM::LastTSBuiltin - Builtin::FirstTSBuiltin;
-#define BUILTIN(ID, TYPE, ATTRS) \+static constexpr int NumNeonBuiltins =
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ NEON::FirstFp16Builtin - Builtin::FirstTSBuiltin;
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+static constexpr int NumFp16Builtins =
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},+ NEON::FirstTSBuiltin - NEON::FirstFp16Builtin;
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr int NumMVEBuiltins =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ ARM::FirstCDEBuiltin - NEON::FirstTSBuiltin;
-#include "clang/Basic/BuiltinsNEON.def"+static constexpr int NumCDEBuiltins =
-+ ARM::FirstARMBuiltin - ARM::FirstCDEBuiltin;
-#define BUILTIN(ID, TYPE, ATTRS) \+static constexpr int NumARMBuiltins = ARM::LastTSBuiltin - ARM::FirstARMBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static_assert(NumBuiltins ==
-#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \+ (NumNeonBuiltins + NumFp16Builtins + NumMVEBuiltins +
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG},+ NumCDEBuiltins + NumARMBuiltins));
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},+namespace clang {
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+namespace NEON {
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+#define GET_NEON_BUILTIN_STR_TABLE
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \+#include "clang/Basic/arm_neon.inc"
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},+#undef GET_NEON_BUILTIN_STR_TABLE
-#include "clang/Basic/BuiltinsARM.def"+
+static constexpr std::array<Builtin::Info, NumNeonBuiltins> BuiltinInfos = {
+#define GET_NEON_BUILTIN_INFOS
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_BUILTIN_INFOS
+};
+
+namespace FP16 {
+#define GET_NEON_BUILTIN_STR_TABLE
+#include "clang/Basic/arm_fp16.inc"
+#undef GET_NEON_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumFp16Builtins> BuiltinInfos = {
+#define GET_NEON_BUILTIN_INFOS
+#include "clang/Basic/arm_fp16.inc"
+#undef GET_NEON_BUILTIN_INFOS
+};
+} // namespace FP16
+} // namespace NEON
+} // namespace clang
+
+namespace {
+namespace MVE {
+#define GET_MVE_BUILTIN_STR_TABLE
+#include "clang/Basic/arm_mve_builtins.inc"
+#undef GET_MVE_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumMVEBuiltins> BuiltinInfos = {
+#define GET_MVE_BUILTIN_INFOS
+#include "clang/Basic/arm_mve_builtins.inc"
+#undef GET_MVE_BUILTIN_INFOS
}; };
+} // namespace MVE
-ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {+namespace CDE {
- return llvm::ArrayRef(BuiltinInfo,+#define GET_CDE_BUILTIN_STR_TABLE
- clang::ARM::LastTSBuiltin - Builtin::FirstTSBuiltin);+#include "clang/Basic/arm_cde_builtins.inc"
+#undef GET_CDE_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumCDEBuiltins> BuiltinInfos = {
+#define GET_CDE_BUILTIN_INFOS
+#include "clang/Basic/arm_cde_builtins.inc"
+#undef GET_CDE_BUILTIN_INFOS
+};
+} // namespace CDE
+} // namespace
+
+static constexpr llvm::StringTable BuiltinStrings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsARM.def"
+ ; // namespace clang
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumARMBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY
+#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsARM.def"
+});
+
+llvm::SmallVector<Builtin::InfosShard>
+ARMTargetInfo::getTargetBuiltins() const {
+ return {
+ {&NEON::BuiltinStrings, NEON::BuiltinInfos, "__builtin_neon_"},
+ {&NEON::FP16::BuiltinStrings, NEON::FP16::BuiltinInfos,
+ "__builtin_neon_"},
+ {&MVE::BuiltinStrings, MVE::BuiltinInfos, "__builtin_arm_mve_"},
+ {&CDE::BuiltinStrings, CDE::BuiltinInfos, "__builtin_arm_cde_"},
+ {&BuiltinStrings, BuiltinInfos},
+ };
} }
bool ARMTargetInfo::isCLZForZeroUndef() const { return false; } bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
clang/lib/Basic/Targets/ARM.h
@@ -155,6 +155,7 @@ public:
bool isBranchProtectionSupportedArch(StringRef Arch) const override; bool isBranchProtectionSupportedArch(StringRef Arch) const override;
bool validateBranchProtection(StringRef Spec, StringRef Arch, bool validateBranchProtection(StringRef Spec, StringRef Arch,
BranchProtectionInfo &BPI, BranchProtectionInfo &BPI,
+ const LangOptions &LO,
StringRef &Err) const override; StringRef &Err) const override;
// FIXME: This should be based on Arch attributes, not CPU names. // FIXME: This should be based on Arch attributes, not CPU names.
@@ -196,7 +197,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool isCLZForZeroUndef() const override; bool isCLZForZeroUndef() const override;
BuiltinVaListKind getBuiltinVaListKind() const override; BuiltinVaListKind getBuiltinVaListKind() const override;
clang/lib/Basic/Targets/AVR.h
@@ -63,7 +63,9 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
bool allowsLargerPreferedTypeAlignment() const override { return false; } bool allowsLargerPreferedTypeAlignment() const override { return false; }
clang/lib/Basic/Targets/BPF.cpp
@@ -19,11 +19,19 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
+#define GET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsBPF.inc"
+#undef GET_BUILTIN_STR_TABLE
+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
#include "clang/Basic/BuiltinsBPF.inc" #include "clang/Basic/BuiltinsBPF.inc"
+#undef GET_BUILTIN_INFOS
}; };
+static_assert(std::size(BuiltinInfos) == NumBuiltins);
void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const { MacroBuilder &Builder) const {
@@ -81,9 +89,9 @@ void BPFTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames)); Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
} }
-ArrayRef<Builtin::Info> BPFTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+BPFTargetInfo::getTargetBuiltins() const {
- clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
bool BPFTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, bool BPFTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
clang/lib/Basic/Targets/BPF.h
@@ -58,7 +58,7 @@ public:
bool handleTargetFeatures(std::vector<std::string> &Features, bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override; DiagnosticsEngine &Diags) override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
std::string_view getClobbers() const override { return ""; } std::string_view getClobbers() const override { return ""; }
clang/lib/Basic/Targets/CSKY.cpp
@@ -139,10 +139,6 @@ bool CSKYTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
return true; return true;
} }
-ArrayRef<Builtin::Info> CSKYTargetInfo::getTargetBuiltins() const {
- return ArrayRef<Builtin::Info>();
-}
-
ArrayRef<const char *> CSKYTargetInfo::getGCCRegNames() const { ArrayRef<const char *> CSKYTargetInfo::getGCCRegNames() const {
static const char *const GCCRegNames[] = { static const char *const GCCRegNames[] = {
// Integer registers // Integer registers
clang/lib/Basic/Targets/CSKY.h
@@ -73,7 +73,9 @@ public:
unsigned getMinGlobalAlign(uint64_t, bool HasNonWeakDef) const override; unsigned getMinGlobalAlign(uint64_t, bool HasNonWeakDef) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return VoidPtrBuiltinVaList; return VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/DirectX.h
@@ -73,7 +73,9 @@ public:
return Feature == "directx"; return Feature == "directx";
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
std::string_view getClobbers() const override { return ""; } std::string_view getClobbers() const override { return ""; }
clang/lib/Basic/Targets/Hexagon.cpp
@@ -204,15 +204,26 @@ ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
return llvm::ArrayRef(GCCRegAliases); return llvm::ArrayRef(GCCRegAliases);
} }
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::Hexagon::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+#define GET_BUILTIN_STR_TABLE
- {#ID, TYPE, ATTRS, nullptr, HEADER, ALL_LANGUAGES},+#include "clang/Basic/BuiltinsHexagon.inc"
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+#undef GET_BUILTIN_STR_TABLE
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
+#include "clang/Basic/BuiltinsHexagon.inc"
+#undef GET_BUILTIN_INFOS
+};
+
+static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
+#define GET_BUILTIN_PREFIXED_INFOS
#include "clang/Basic/BuiltinsHexagon.inc" #include "clang/Basic/BuiltinsHexagon.inc"
+#undef GET_BUILTIN_PREFIXED_INFOS
}; };
+static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
+ NumBuiltins);
bool HexagonTargetInfo::hasFeature(StringRef Feature) const { bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
std::string VS = "hvxv" + HVXVersion; std::string VS = "hvxv" + HVXVersion;
@@ -271,7 +282,8 @@ void HexagonTargetInfo::fillValidCPUList(
Values.push_back(Suffix.Name); Values.push_back(Suffix.Name);
} }
-ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -+HexagonTargetInfo::getTargetBuiltins() const {
- Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos},
+ {&BuiltinStrings, PrefixedBuiltinInfos, "__builtin_HEXAGON_"}};
} }
clang/lib/Basic/Targets/Hexagon.h
@@ -66,7 +66,7 @@ public:
BoolWidth = BoolAlign = 8; BoolWidth = BoolAlign = 8;
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool validateAsmConstraint(const char *&Name, bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override { TargetInfo::ConstraintInfo &Info) const override {
clang/lib/Basic/Targets/Lanai.h
@@ -78,7 +78,9 @@ public:
return TargetInfo::VoidPtrBuiltinVaList; return TargetInfo::VoidPtrBuiltinVaList;
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
bool validateAsmConstraint(const char *&Name, bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override { TargetInfo::ConstraintInfo &info) const override {
clang/lib/Basic/Targets/LoongArch.cpp
@@ -273,13 +273,55 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
} }
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBaseBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ LoongArch::FirstLSXBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumLSXBuiltins =
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+ LoongArch::FirstLASXBuiltin - LoongArch::FirstLSXBuiltin;
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumLASXBuiltins =
-#include "clang/Basic/BuiltinsLoongArch.def"+ LoongArch::LastTSBuiltin - LoongArch::FirstLASXBuiltin;
-};+static constexpr int NumBuiltins =
+ LoongArch::LastTSBuiltin - Builtin::FirstTSBuiltin;
+static_assert(NumBuiltins ==
+ (NumBaseBuiltins + NumLSXBuiltins + NumLASXBuiltins));
+
+static constexpr llvm::StringTable BuiltinBaseStrings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsLoongArchBase.def"
+#undef TARGET_BUILTIN
+ ;
+
+static constexpr auto BuiltinBaseInfos = Builtin::MakeInfos<NumBaseBuiltins>({
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsLoongArchBase.def"
+#undef TARGET_BUILTIN
+});
+
+static constexpr llvm::StringTable BuiltinLSXStrings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsLoongArchLSX.def"
+#undef TARGET_BUILTIN
+ ;
+
+static constexpr auto BuiltinLSXInfos = Builtin::MakeInfos<NumLSXBuiltins>({
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsLoongArchLSX.def"
+#undef TARGET_BUILTIN
+});
+
+static constexpr llvm::StringTable BuiltinLASXStrings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsLoongArchLASX.def"
+#undef TARGET_BUILTIN
+ ;
+
+static constexpr auto BuiltinLASXInfos = Builtin::MakeInfos<NumLASXBuiltins>({
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsLoongArchLASX.def"
+#undef TARGET_BUILTIN
+});
bool LoongArchTargetInfo::initFeatureMap( bool LoongArchTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
@@ -306,9 +348,13 @@ bool LoongArchTargetInfo::hasFeature(StringRef Feature) const {
.Default(false); .Default(false);
} }
-ArrayRef<Builtin::Info> LoongArchTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo, clang::LoongArch::LastTSBuiltin -+LoongArchTargetInfo::getTargetBuiltins() const {
- Builtin::FirstTSBuiltin);+ return {
+ {&BuiltinBaseStrings, BuiltinBaseInfos},
+ {&BuiltinLSXStrings, BuiltinLSXInfos},
+ {&BuiltinLASXStrings, BuiltinLASXInfos},
+ };
} }
bool LoongArchTargetInfo::handleTargetFeatures( bool LoongArchTargetInfo::handleTargetFeatures(
clang/lib/Basic/Targets/LoongArch.h
@@ -72,7 +72,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList; return TargetInfo::VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/M68k.cpp
@@ -115,7 +115,8 @@ void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__HAVE_68881__"); Builder.defineMacro("__HAVE_68881__");
} }
-ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
+M68kTargetInfo::getTargetBuiltins() const {
// FIXME: Implement. // FIXME: Implement.
return {}; return {};
} }
clang/lib/Basic/Targets/M68k.h
@@ -44,7 +44,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool hasFeature(StringRef Feature) const override; bool hasFeature(StringRef Feature) const override;
ArrayRef<const char *> getGCCRegNames() const override; ArrayRef<const char *> getGCCRegNames() const override;
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
clang/lib/Basic/Targets/MSP430.h
@@ -50,7 +50,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
// FIXME: Implement. // FIXME: Implement.
return {}; return {};
} }
clang/lib/Basic/Targets/Mips.cpp
@@ -20,13 +20,20 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+static constexpr llvm::StringTable BuiltinStrings =
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsMips.def"
+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
#include "clang/Basic/BuiltinsMips.def" #include "clang/Basic/BuiltinsMips.def"
-};+});
bool MipsTargetInfo::processorSupportsGPR64() const { bool MipsTargetInfo::processorSupportsGPR64() const {
return llvm::StringSwitch<bool>(CPU) return llvm::StringSwitch<bool>(CPU)
@@ -223,9 +230,9 @@ bool MipsTargetInfo::hasFeature(StringRef Feature) const {
.Default(false); .Default(false);
} }
-ArrayRef<Builtin::Info> MipsTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+MipsTargetInfo::getTargetBuiltins() const {
- clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
unsigned MipsTargetInfo::getUnwindWordWidth() const { unsigned MipsTargetInfo::getUnwindWordWidth() const {
clang/lib/Basic/Targets/Mips.h
@@ -198,7 +198,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool hasFeature(StringRef Feature) const override; bool hasFeature(StringRef Feature) const override;
clang/lib/Basic/Targets/NVPTX.cpp
@@ -20,11 +20,19 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+ clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
+#define GET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsNVPTX.inc"
+#undef GET_BUILTIN_STR_TABLE
+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
#include "clang/Basic/BuiltinsNVPTX.inc" #include "clang/Basic/BuiltinsNVPTX.inc"
+#undef GET_BUILTIN_INFOS
}; };
+static_assert(std::size(BuiltinInfos) == NumBuiltins);
const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"}; const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
@@ -62,12 +70,13 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
HasFloat16 = true; HasFloat16 = true;
if (TargetPointerWidth == 32) if (TargetPointerWidth == 32)
- resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
- else if (Opts.NVPTXUseShortPointers)
resetDataLayout( resetDataLayout(
- "e-p3:32:32-p4:32:32-p5:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");+ "e-p:32:32-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
+ else if (Opts.NVPTXUseShortPointers)
+ resetDataLayout("e-p3:32:32-p4:32:32-p5:32:32-p6:32:32-i64:64-i128:128-v16:"
+ "16-v32:32-n16:32:64");
else else
- resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");+ resetDataLayout("e-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
// If possible, get a TargetInfo for our host triple, so we can match its // If possible, get a TargetInfo for our host triple, so we can match its
// types. // types.
@@ -294,7 +303,7 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
} }
} }
-ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+NVPTXTargetInfo::getTargetBuiltins() const {
- clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
clang/lib/Basic/Targets/NVPTX.h
@@ -75,7 +75,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool useFP16ConversionIntrinsics() const override { return false; } bool useFP16ConversionIntrinsics() const override { return false; }
clang/lib/Basic/Targets/PNaCl.h
@@ -52,7 +52,9 @@ public:
return Feature == "pnacl"; return Feature == "pnacl";
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::PNaClABIBuiltinVaList; return TargetInfo::PNaClABIBuiltinVaList;
clang/lib/Basic/Targets/PPC.cpp
@@ -19,15 +19,22 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr llvm::StringTable BuiltinStrings =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ CLANG_BUILTIN_STR_TABLE_START
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+#define BUILTIN CLANG_BUILTIN_STR_TABLE
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
#include "clang/Basic/BuiltinsPPC.def" #include "clang/Basic/BuiltinsPPC.def"
-};+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
+#include "clang/Basic/BuiltinsPPC.def"
+});
/// handleTargetFeatures - Perform initialization based on the user /// handleTargetFeatures - Perform initialization based on the user
/// configured set of features. /// configured set of features.
@@ -927,9 +934,9 @@ void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
MaxAtomicInlineWidth = 128; MaxAtomicInlineWidth = 128;
} }
-ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+PPCTargetInfo::getTargetBuiltins() const {
- clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const { bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
clang/lib/Basic/Targets/PPC.h
@@ -187,7 +187,7 @@ public:
StringRef getABI() const override { return ABI; } StringRef getABI() const override { return ABI; }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool isCLZForZeroUndef() const override { return false; } bool isCLZForZeroUndef() const override { return false; }
clang/lib/Basic/Targets/RISCV.cpp
@@ -240,22 +240,61 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
} }
} }
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumRVVBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ RISCVVector::FirstSiFiveBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumRVVSiFiveBuiltins =
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+ RISCVVector::FirstTSBuiltin - RISCVVector::FirstSiFiveBuiltin;
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+static constexpr int NumRISCVBuiltins =
-#include "clang/Basic/BuiltinsRISCVVector.def"+ RISCV::LastTSBuiltin - RISCVVector::FirstTSBuiltin;
-#define BUILTIN(ID, TYPE, ATTRS) \+static constexpr int NumBuiltins =
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin;
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static_assert(NumBuiltins ==
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ (NumRVVBuiltins + NumRVVSiFiveBuiltins + NumRISCVBuiltins));
-#include "clang/Basic/BuiltinsRISCV.inc"+
+namespace RVV {
+#define GET_RISCVV_BUILTIN_STR_TABLE
+#include "clang/Basic/riscv_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_STR_TABLE
+static_assert(BuiltinStrings.size() < 100'000);
+
+static constexpr std::array<Builtin::Info, NumRVVBuiltins> BuiltinInfos = {
+#define GET_RISCVV_BUILTIN_INFOS
+#include "clang/Basic/riscv_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_INFOS
+};
+} // namespace RVV
+
+namespace RVVSiFive {
+#define GET_RISCVV_BUILTIN_STR_TABLE
+#include "clang/Basic/riscv_sifive_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos =
+ {
+#define GET_RISCVV_BUILTIN_INFOS
+#include "clang/Basic/riscv_sifive_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_INFOS
}; };
+} // namespace RVVSiFive
+
+#define GET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsRISCV.inc"
+#undef GET_BUILTIN_STR_TABLE
-ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {+static constexpr Builtin::Info BuiltinInfos[] = {
- return llvm::ArrayRef(BuiltinInfo,+#define GET_BUILTIN_INFOS
- clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);+#include "clang/Basic/BuiltinsRISCV.inc"
+#undef GET_BUILTIN_INFOS
+};
+static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins);
+
+llvm::SmallVector<Builtin::InfosShard>
+RISCVTargetInfo::getTargetBuiltins() const {
+ return {
+ {&RVV::BuiltinStrings, RVV::BuiltinInfos, "__builtin_rvv_"},
+ {&RVVSiFive::BuiltinStrings, RVVSiFive::BuiltinInfos, "__builtin_rvv_"},
+ {&BuiltinStrings, BuiltinInfos},
+ };
} }
bool RISCVTargetInfo::initFeatureMap( bool RISCVTargetInfo::initFeatureMap(
clang/lib/Basic/Targets/RISCV.h
@@ -62,7 +62,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList; return TargetInfo::VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/SPIR.cpp
@@ -20,15 +20,23 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
+#define GET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsSPIRV.inc"
+#undef GET_BUILTIN_STR_TABLE
+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
#include "clang/Basic/BuiltinsSPIRV.inc" #include "clang/Basic/BuiltinsSPIRV.inc"
+#undef GET_BUILTIN_INFOS
}; };
+static_assert(std::size(BuiltinInfos) == NumBuiltins);
-ArrayRef<Builtin::Info> SPIRVTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+SPIRVTargetInfo::getTargetBuiltins() const {
- clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts, void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,
@@ -94,7 +102,8 @@ SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const {
return AMDGPUTI.convertConstraint(Constraint); return AMDGPUTI.convertConstraint(Constraint);
} }
-ArrayRef<Builtin::Info> SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
+SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const {
return AMDGPUTI.getTargetBuiltins(); return AMDGPUTI.getTargetBuiltins();
} }
clang/lib/Basic/Targets/SPIR.h
@@ -161,7 +161,9 @@ public:
// memcpy as per section 3 of the SPIR spec. // memcpy as per section 3 of the SPIR spec.
bool useFP16ConversionIntrinsics() const override { return false; } bool useFP16ConversionIntrinsics() const override { return false; }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
std::string_view getClobbers() const override { return ""; } std::string_view getClobbers() const override { return ""; }
@@ -315,7 +317,9 @@ public:
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); "v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+
+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
+
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
}; };
@@ -410,7 +414,7 @@ public:
std::string convertConstraint(const char *&Constraint) const override; std::string convertConstraint(const char *&Constraint) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
clang/lib/Basic/Targets/Sparc.h
@@ -48,7 +48,7 @@ public:
bool hasFeature(StringRef Feature) const override; bool hasFeature(StringRef Feature) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
// FIXME: Implement! // FIXME: Implement!
return {}; return {};
} }
clang/lib/Basic/Targets/SystemZ.cpp
@@ -20,13 +20,21 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::SystemZ::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr llvm::StringTable BuiltinStrings =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
#include "clang/Basic/BuiltinsSystemZ.def" #include "clang/Basic/BuiltinsSystemZ.def"
-};+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#include "clang/Basic/BuiltinsSystemZ.def"
+});
const char *const SystemZTargetInfo::GCCRegNames[] = { const char *const SystemZTargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -172,7 +180,7 @@ void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__VEC__", "10305"); Builder.defineMacro("__VEC__", "10305");
} }
-ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo, clang::SystemZ::LastTSBuiltin -+SystemZTargetInfo::getTargetBuiltins() const {
- Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
clang/lib/Basic/Targets/SystemZ.h
@@ -100,7 +100,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
ArrayRef<const char *> getGCCRegNames() const override; ArrayRef<const char *> getGCCRegNames() const override;
clang/lib/Basic/Targets/TCE.h
@@ -96,7 +96,9 @@ public:
bool hasFeature(StringRef Feature) const override { return Feature == "tce"; } bool hasFeature(StringRef Feature) const override { return Feature == "tce"; }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return {}; }+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
std::string_view getClobbers() const override { return ""; } std::string_view getClobbers() const override { return ""; }
clang/lib/Basic/Targets/VE.cpp
@@ -18,11 +18,19 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::VE::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
+static constexpr llvm::StringTable BuiltinStrings =
+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsVE.def"
+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
#include "clang/Basic/BuiltinsVE.def" #include "clang/Basic/BuiltinsVE.def"
-};+});
void VETargetInfo::getTargetDefines(const LangOptions &Opts, void VETargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const { MacroBuilder &Builder) const {
@@ -39,7 +47,6 @@ void VETargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
} }
-ArrayRef<Builtin::Info> VETargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard> VETargetInfo::getTargetBuiltins() const {
- return llvm::ArrayRef(BuiltinInfo,+ return {{&BuiltinStrings, BuiltinInfos}};
- clang::VE::LastTSBuiltin - Builtin::FirstTSBuiltin);
} }
clang/lib/Basic/Targets/VE.h
@@ -55,7 +55,7 @@ public:
bool hasSjLjLowering() const override { return true; } bool hasSjLjLowering() const override { return true; }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList; return TargetInfo::VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/WebAssembly.cpp
@@ -20,15 +20,22 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr llvm::StringTable BuiltinStrings =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ CLANG_BUILTIN_STR_TABLE_START
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+#define BUILTIN CLANG_BUILTIN_STR_TABLE
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsWebAssembly.def"
+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
+#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
#include "clang/Basic/BuiltinsWebAssembly.def" #include "clang/Basic/BuiltinsWebAssembly.def"
-};+});
static constexpr llvm::StringLiteral ValidCPUNames[] = { static constexpr llvm::StringLiteral ValidCPUNames[] = {
{"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime1"}}; {"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime1"}};
@@ -360,9 +367,9 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
return true; return true;
} }
-ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -+WebAssemblyTargetInfo::getTargetBuiltins() const {
- Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
clang/lib/Basic/Targets/WebAssembly.h
@@ -121,7 +121,7 @@ private:
bool setCPU(const std::string &Name) final { return isValidCPUName(Name); } bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
- ArrayRef<Builtin::Info> getTargetBuiltins() const final;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const final;
BuiltinVaListKind getBuiltinVaListKind() const final { BuiltinVaListKind getBuiltinVaListKind() const final {
return VoidPtrBuiltinVaList; return VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/X86.cpp
@@ -23,23 +23,53 @@
namespace clang { namespace clang {
namespace targets { namespace targets {
-static constexpr Builtin::Info BuiltinInfoX86[] = {+// The x86-32 builtins are a subset and prefix of the x86-64 builtins.
-#define BUILTIN(ID, TYPE, ATTRS) \+static constexpr int NumX86Builtins =
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ X86::LastX86CommonBuiltin - Builtin::FirstTSBuiltin + 1;
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+static constexpr int NumX86_64Builtins =
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+ X86::LastTSBuiltin - X86::FirstX86_64Builtin;
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \+static constexpr int NumBuiltins = X86::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},+static_assert(NumBuiltins == (NumX86Builtins + NumX86_64Builtins));
+
+namespace X86 {
+#define GET_BUILTIN_STR_TABLE
#include "clang/Basic/BuiltinsX86.inc" #include "clang/Basic/BuiltinsX86.inc"
+#undef GET_BUILTIN_STR_TABLE
-#define BUILTIN(ID, TYPE, ATTRS) \+static constexpr Builtin::Info BuiltinInfos[] = {
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+#define GET_BUILTIN_INFOS
-#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \+#include "clang/Basic/BuiltinsX86.inc"
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+#undef GET_BUILTIN_INFOS
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \+};
- {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},+
+static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
+#define GET_BUILTIN_PREFIXED_INFOS
+#include "clang/Basic/BuiltinsX86.inc"
+#undef GET_BUILTIN_PREFIXED_INFOS
+};
+static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
+ NumX86Builtins);
+} // namespace X86
+
+namespace X86_64 {
+#define GET_BUILTIN_STR_TABLE
#include "clang/Basic/BuiltinsX86_64.inc" #include "clang/Basic/BuiltinsX86_64.inc"
+#undef GET_BUILTIN_STR_TABLE
+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
+#include "clang/Basic/BuiltinsX86_64.inc"
+#undef GET_BUILTIN_INFOS
+};
+
+static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
+#define GET_BUILTIN_PREFIXED_INFOS
+#include "clang/Basic/BuiltinsX86_64.inc"
+#undef GET_BUILTIN_PREFIXED_INFOS
}; };
+static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
+ NumX86_64Builtins);
+} // namespace X86_64
static const char *const GCCRegNames[] = { static const char *const GCCRegNames[] = {
"ax", "dx", "cx", "bx", "si", "di", "bp", "sp", "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
@@ -1856,12 +1886,21 @@ ArrayRef<TargetInfo::AddlRegName> X86TargetInfo::getGCCAddlRegNames() const {
return llvm::ArrayRef(AddlRegNames); return llvm::ArrayRef(AddlRegNames);
} }
-ArrayRef<Builtin::Info> X86_32TargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -+X86_32TargetInfo::getTargetBuiltins() const {
- Builtin::FirstTSBuiltin + 1);+ return {
+ {&X86::BuiltinStrings, X86::BuiltinInfos},
+ {&X86::BuiltinStrings, X86::PrefixedBuiltinInfos, "__builtin_ia32_"},
+ };
} }
-ArrayRef<Builtin::Info> X86_64TargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfoX86,+X86_64TargetInfo::getTargetBuiltins() const {
- X86::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {
+ {&X86::BuiltinStrings, X86::BuiltinInfos},
+ {&X86::BuiltinStrings, X86::PrefixedBuiltinInfos, "__builtin_ia32_"},
+ {&X86_64::BuiltinStrings, X86_64::BuiltinInfos},
+ {&X86_64::BuiltinStrings, X86_64::PrefixedBuiltinInfos,
+ "__builtin_ia32_"},
+ };
} }
clang/lib/Basic/Targets/X86.h
@@ -509,7 +509,7 @@ public:
MaxAtomicInlineWidth = 64; MaxAtomicInlineWidth = 64;
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool hasBitIntType() const override { return true; } bool hasBitIntType() const override { return true; }
size_t getMaxBitIntWidth() const override { size_t getMaxBitIntWidth() const override {
@@ -821,7 +821,7 @@ public:
MaxAtomicInlineWidth = 128; MaxAtomicInlineWidth = 128;
} }
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
bool hasBitIntType() const override { return true; } bool hasBitIntType() const override { return true; }
size_t getMaxBitIntWidth() const override { size_t getMaxBitIntWidth() const override {
clang/lib/Basic/Targets/XCore.cpp
@@ -18,13 +18,20 @@
using namespace clang; using namespace clang;
using namespace clang::targets; using namespace clang::targets;
-static constexpr Builtin::Info BuiltinInfo[] = {+static constexpr int NumBuiltins =
-#define BUILTIN(ID, TYPE, ATTRS) \+ XCore::LastTSBuiltin - Builtin::FirstTSBuiltin;
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},+
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \+static constexpr llvm::StringTable BuiltinStrings =
- {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},+ CLANG_BUILTIN_STR_TABLE_START
+#define BUILTIN CLANG_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsXCore.def"
+ ;
+
+static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
+#define BUILTIN CLANG_BUILTIN_ENTRY
+#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
#include "clang/Basic/BuiltinsXCore.def" #include "clang/Basic/BuiltinsXCore.def"
-};+});
void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts, void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const { MacroBuilder &Builder) const {
@@ -32,7 +39,7 @@ void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__XS1B__"); Builder.defineMacro("__XS1B__");
} }
-ArrayRef<Builtin::Info> XCoreTargetInfo::getTargetBuiltins() const {+llvm::SmallVector<Builtin::InfosShard>
- return llvm::ArrayRef(BuiltinInfo,+XCoreTargetInfo::getTargetBuiltins() const {
- clang::XCore::LastTSBuiltin - Builtin::FirstTSBuiltin);+ return {{&BuiltinStrings, BuiltinInfos}};
} }
clang/lib/Basic/Targets/XCore.h
@@ -43,7 +43,7 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override;+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList; return TargetInfo::VoidPtrBuiltinVaList;
clang/lib/Basic/Targets/Xtensa.h
@@ -56,8 +56,8 @@ public:
void getTargetDefines(const LangOptions &Opts, void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override; MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
- return std::nullopt;+ return {};
} }
BuiltinVaListKind getBuiltinVaListKind() const override { BuiltinVaListKind getBuiltinVaListKind() const override {
clang/lib/Basic/Warnings.cpp
@@ -73,16 +73,6 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
else else
Diags.setExtensionHandlingBehavior(diag::Severity::Ignored); Diags.setExtensionHandlingBehavior(diag::Severity::Ignored);
- if (!Opts.DiagnosticSuppressionMappingsFile.empty()) {
- if (auto FileContents =
- VFS.getBufferForFile(Opts.DiagnosticSuppressionMappingsFile)) {
- Diags.setDiagSuppressionMapping(**FileContents);
- } else if (ReportDiags) {
- Diags.Report(diag::err_drv_no_such_file)
- << Opts.DiagnosticSuppressionMappingsFile;
- }
- }
-
SmallVector<diag::kind, 10> _Diags; SmallVector<diag::kind, 10> _Diags;
const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs =
Diags.getDiagnosticIDs(); Diags.getDiagnosticIDs();
@@ -237,4 +227,17 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
} }
} }
} }
+
+ // Process suppression mappings file after processing other warning flags
+ // (like -Wno-unknown-warning-option) as we can emit extra warnings during
+ // processing.
+ if (!Opts.DiagnosticSuppressionMappingsFile.empty()) {
+ if (auto FileContents =
+ VFS.getBufferForFile(Opts.DiagnosticSuppressionMappingsFile)) {
+ Diags.setDiagSuppressionMapping(**FileContents);
+ } else if (ReportDiags) {
+ Diags.Report(diag::err_drv_no_such_file)
+ << Opts.DiagnosticSuppressionMappingsFile;
+ }
+ }
} }
clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
@@ -3,9 +3,15 @@ set(LLVM_LINK_COMPONENTS
Support Support
) )
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
add_clang_library(clangCIRLoweringDirectToLLVM add_clang_library(clangCIRLoweringDirectToLLVM
LowerToLLVM.cpp LowerToLLVM.cpp
LINK_LIBS LINK_LIBS
MLIRIR MLIRIR
+ ${dialect_libs}
+ MLIRCIR
+ MLIRBuiltinToLLVMIRTranslation
+ MLIRLLVMToLLVMIRTranslation
) )
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -10,9 +10,23 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
-#include "clang/CIR/LowerToLLVM.h"+#include "LowerToLLVM.h"
+#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/BuiltinDialect.h"
#include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinOps.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Pass/PassManager.h"
+#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Export.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "clang/CIR/Dialect/IR/CIRAttrVisitor.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/MissingFeatures.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/TimeProfiler.h"
@@ -22,16 +36,299 @@ using namespace llvm;
namespace cir { namespace cir {
namespace direct { namespace direct {
+class CIRAttrToValue : public CirAttrVisitor<CIRAttrToValue, mlir::Value> {
[diff truncated]