.ci/metrics/metrics.py
@@ -12,7 +12,7 @@ GRAFANA_URL = (
"https://influx-prod-13-prod-us-east-0.grafana.net/api/v1/push/influx/write" "https://influx-prod-13-prod-us-east-0.grafana.net/api/v1/push/influx/write"
) )
GITHUB_PROJECT = "llvm/llvm-project" GITHUB_PROJECT = "llvm/llvm-project"
-WORKFLOWS_TO_TRACK = ["Check code formatting"]+WORKFLOWS_TO_TRACK = ["Check code formatting", "LLVM Premerge Checks"]
SCRAPE_INTERVAL_SECONDS = 5 * 60 SCRAPE_INTERVAL_SECONDS = 5 * 60
.ci/monolithic-linux.sh
@@ -34,8 +34,11 @@ function at-exit {
# If building fails there will be no results files. # If building fails there will be no results files.
shopt -s nullglob shopt -s nullglob
- python3 "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":linux: Linux x64 Test Results" \+ if command -v buildkite-agent 2>&1 >/dev/null
- "linux-x64-test-results" "${BUILD_DIR}"/test-results.*.xml+ then
+ python3 "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":linux: Linux x64 Test Results" \
+ "linux-x64-test-results" "${BUILD_DIR}"/test-results.*.xml
+ fi
} }
trap at-exit EXIT trap at-exit EXIT
.ci/monolithic-windows.sh
@@ -33,8 +33,11 @@ function at-exit {
# If building fails there will be no results files. # If building fails there will be no results files.
shopt -s nullglob shopt -s nullglob
- python "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":windows: Windows x64 Test Results" \+ if command -v buildkite-agent 2>&1 >/dev/null
- "windows-x64-test-results" "${BUILD_DIR}"/test-results.*.xml+ then
+ python "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":windows: Windows x64 Test Results" \
+ "windows-x64-test-results" "${BUILD_DIR}"/test-results.*.xml
+ fi
} }
trap at-exit EXIT trap at-exit EXIT
.git-blame-ignore-revs
@@ -94,3 +94,9 @@ b6262880b34629e9d7a72b5a42f315a3c9ed8139
39c7dc7207e76e72da21cf4fedda21b5311bf62d 39c7dc7207e76e72da21cf4fedda21b5311bf62d
e80bc777749331e9519575f416c342f7626dd14d e80bc777749331e9519575f416c342f7626dd14d
7e5cd8f1b6c5263ed5e2cc03d60c8779a8d3e9f7 7e5cd8f1b6c5263ed5e2cc03d60c8779a8d3e9f7
+
+# NFC: clang-format test_demangle.pass.cpp but keep test "lines"
+d33bf2e9df578ff7e44fd22504d6ad5a122b7ee6
+
+# [lldb][NFC] clang-format MainLoopPosix.cpp
+66bdbfbaa08fa3d8e64a7fe136a8fb717f5cdbb7
.github/CODEOWNERS
@@ -129,7 +129,7 @@
/mlir/**/Transforms/SROA.* @moxinilian /mlir/**/Transforms/SROA.* @moxinilian
# BOLT # BOLT
-/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci+/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci @yota9
# Bazel build system. # Bazel build system.
/utils/bazel/ @rupprecht @keith /utils/bazel/ @rupprecht @keith
.github/new-prs-labeler.yml
@@ -747,6 +747,12 @@ backend:RISC-V:
- llvm/**/*riscv* - llvm/**/*riscv*
- llvm/**/*RISCV* - llvm/**/*RISCV*
+backend:Xtensa:
+ - clang/**/*xtensa*
+ - clang/**/*Xtensa*
+ - llvm/**/*xtensa*
+ - llvm/**/*Xtensa*
+
lld:coff: lld:coff:
- lld/**/COFF/** - lld/**/COFF/**
- lld/Common/** - lld/Common/**
.github/workflows/build-ci-container.yml
@@ -60,7 +60,7 @@ jobs:
- name: Test Container - name: Test Container
run: | run: |
for image in ${{ steps.vars.outputs.container-name-tag }} ${{ steps.vars.outputs.container-name }}; do for image in ${{ steps.vars.outputs.container-name-tag }} ${{ steps.vars.outputs.container-name }}; do
- podman run --rm -it $image /usr/bin/bash -x -c 'printf '\''#include <iostream>\nint main(int argc, char **argv) { std::cout << "Hello\\n"; }'\'' | clang++ -x c++ - && ./a.out | grep Hello'+ podman run --rm -it $image /usr/bin/bash -x -c 'cd $HOME && printf '\''#include <iostream>\nint main(int argc, char **argv) { std::cout << "Hello\\n"; }'\'' | clang++ -x c++ - && ./a.out | grep Hello'
done done
push-ci-container: push-ci-container:
.github/workflows/containers/github-action-ci/Dockerfile
@@ -41,13 +41,13 @@ RUN ninja -C ./build stage2-clang-bolt stage2-install-distribution && ninja -C .
FROM base FROM base
COPY --from=stage1-toolchain $LLVM_SYSROOT $LLVM_SYSROOT COPY --from=stage1-toolchain $LLVM_SYSROOT $LLVM_SYSROOT
- +
# Need to install curl for hendrikmuhs/ccache-action # Need to install curl for hendrikmuhs/ccache-action
# Need nodejs for some of the GitHub actions. # Need nodejs for some of the GitHub actions.
# Need perl-modules for clang analyzer tests. # Need perl-modules for clang analyzer tests.
# Need git for SPIRV-Tools tests. # Need git for SPIRV-Tools tests.
RUN apt-get update && \ RUN apt-get update && \
- apt-get install -y \+ DEBIAN_FRONTEND=noninteractive apt-get install -y \
binutils \ binutils \
cmake \ cmake \
curl \ curl \
@@ -56,7 +56,22 @@ RUN apt-get update && \
ninja-build \ ninja-build \
nodejs \ nodejs \
perl-modules \ perl-modules \
- python3-psutil+ python3-psutil \
+
+ # These are needed by the premerge pipeline. Pip is used to install
+ # dependent python packages and ccache is used for build caching. File and
+ # tzdata are used for tests.
+ python3-pip \
+ ccache \
+ file \
+ tzdata
ENV LLVM_SYSROOT=$LLVM_SYSROOT ENV LLVM_SYSROOT=$LLVM_SYSROOT
ENV PATH=${LLVM_SYSROOT}/bin:${PATH} ENV PATH=${LLVM_SYSROOT}/bin:${PATH}
+
+# Create a new user to avoid test failures related to a lack of expected
+# permissions issues in some tests. Set the user id to 1001 as that is the
+# user id that Github Actions uses to perform the checkout action.
+RUN useradd gha -u 1001 -m -s /bin/bash
+USER gha
+
.github/workflows/docs.yml
@@ -106,9 +106,9 @@ jobs:
with: with:
python-version: '3.11' python-version: '3.11'
cache: 'pip' cache: 'pip'
- cache-dependency-path: 'llvm/docs/requirements.txt'+ cache-dependency-path: 'llvm/docs/requirements-hashed.txt'
- name: Install python dependencies - name: Install python dependencies
- run: pip install -r llvm/docs/requirements.txt+ run: pip install -r llvm/docs/requirements-hashed.txt
- name: Install system dependencies - name: Install system dependencies
run: | run: |
sudo apt-get update sudo apt-get update
.github/workflows/premerge.yaml
@@ -0,0 +1,69 @@
+name: LLVM Premerge Checks
+
+permissions:
+ contents: read
+
+on:
+ pull_request:
+ paths:
+ - .github/workflows/premerge.yaml
+ push:
+ branches:
+ - 'main'
+
+jobs:
+ premerge-checks-linux:
+ if: github.repository_owner == 'llvm'
+ runs-on: llvm-premerge-linux-runners
+ concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+ container:
+ image: ghcr.io/llvm/ci-ubuntu-22.04:latest
+ defaults:
+ run:
+ shell: bash
+ steps:
+ - name: Checkout LLVM
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+ - name: Setup ccache
+ uses: hendrikmuhs/ccache-action@v1.2.14
+ - name: Build and Test
+ run: |
+ git config --global --add safe.directory '*'
+
+ modified_files=$(git diff --name-only HEAD~1...HEAD)
+ modified_dirs=$(echo "$modified_files" | cut -d'/' -f1 | sort -u)
+
+ echo $modified_files
+ echo $modified_dirs
+
+ . ./.ci/compute-projects.sh
+
+ all_projects="bolt clang clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl"
+ modified_projects="$(keep-modified-projects ${all_projects})"
+
+ linux_projects_to_test=$(exclude-linux $(compute-projects-to-test 0 ${modified_projects}))
+ linux_check_targets=$(check-targets ${linux_projects_to_test} | sort | uniq)
+ linux_projects=$(add-dependencies ${linux_projects_to_test} | sort | uniq)
+
+ linux_runtimes_to_test=$(compute-runtimes-to-test ${linux_projects_to_test})
+ linux_runtime_check_targets=$(check-targets ${linux_runtimes_to_test} | sort | uniq)
+ linux_runtimes=$(echo ${linux_runtimes_to_test} | sort | uniq)
+
+ if [[ "${linux_projects}" == "" ]]; then
+ echo "No projects to build"
+ exit 0
+ fi
+
+ echo "Building projects: ${linux_projects}"
+ echo "Running project checks targets: ${linux_check_targets}"
+ echo "Building runtimes: ${linux_runtimes}"
+ echo "Running runtimes checks targets: ${linux_runtime_check_targets}"
+
+ export CC=/opt/llvm/bin/clang
+ export CXX=/opt/llvm/bin/clang++
+
+ ./.ci/monolithic-linux.sh "$(echo ${linux_projects} | tr ' ' ';')" "$(echo ${linux_check_targets})" "$(echo ${linux_runtimes} | tr ' ' ';')" "$(echo ${linux_runtime_check_targets})"
bolt/docs/CommandLineArgumentReference.md
@@ -498,9 +498,12 @@
Automatically put hot code on 2MB page(s) (hugify) at runtime. No manual call Automatically put hot code on 2MB page(s) (hugify) at runtime. No manual call
to hugify is needed in the binary (which is what --hot-text relies on). to hugify is needed in the binary (which is what --hot-text relies on).
-- `--icf`+- `--icf=<value>`
Fold functions with identical code Fold functions with identical code
+ - `all`: Enable identical code folding
+ - `none`: Disable identical code folding (default)
+ - `safe`: Enable safe identical code folding
- `--icp` - `--icp`
bolt/include/bolt/Core/BinaryFunction.h
@@ -428,6 +428,9 @@ private:
/// Function order for streaming into the destination binary. /// Function order for streaming into the destination binary.
uint32_t Index{-1U}; uint32_t Index{-1U};
+ /// Function is referenced by a non-control flow instruction.
+ bool HasAddressTaken{false};
+
/// Get basic block index assuming it belongs to this function. /// Get basic block index assuming it belongs to this function.
unsigned getIndex(const BinaryBasicBlock *BB) const { unsigned getIndex(const BinaryBasicBlock *BB) const {
assert(BB->getIndex() < BasicBlocks.size()); assert(BB->getIndex() < BasicBlocks.size());
@@ -822,6 +825,14 @@ public:
return nullptr; return nullptr;
} }
+ /// Return true if function is referenced in a non-control flow instruction.
+ /// This flag is set when the code and relocation analyses are being
+ /// performed, which occurs when safe ICF (Identical Code Folding) is enabled.
+ bool hasAddressTaken() const { return HasAddressTaken; }
+
+ /// Set whether function is referenced in a non-control flow instruction.
+ void setHasAddressTaken(bool AddressTaken) { HasAddressTaken = AddressTaken; }
+
/// Returns the raw binary encoding of this function. /// Returns the raw binary encoding of this function.
ErrorOr<ArrayRef<uint8_t>> getData() const; ErrorOr<ArrayRef<uint8_t>> getData() const;
@@ -2135,6 +2146,9 @@ public:
// adjustments. // adjustments.
void handleAArch64IndirectCall(MCInst &Instruction, const uint64_t Offset); void handleAArch64IndirectCall(MCInst &Instruction, const uint64_t Offset);
+ /// Analyze instruction to identify a function reference.
+ void analyzeInstructionForFuncReference(const MCInst &Inst);
+
/// Scan function for references to other functions. In relocation mode, /// Scan function for references to other functions. In relocation mode,
/// add relocations for external references. In non-relocation mode, detect /// add relocations for external references. In non-relocation mode, detect
/// and mark new entry points. /// and mark new entry points.
bolt/include/bolt/Passes/ADRRelaxationPass.h
@@ -25,7 +25,8 @@ namespace bolt {
class ADRRelaxationPass : public BinaryFunctionPass { class ADRRelaxationPass : public BinaryFunctionPass {
public: public:
- explicit ADRRelaxationPass() : BinaryFunctionPass(false) {}+ explicit ADRRelaxationPass(const cl::opt<bool> &PrintPass)
+ : BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "adr-relaxation"; } const char *getName() const override { return "adr-relaxation"; }
bolt/include/bolt/Passes/IdenticalCodeFolding.h
@@ -11,6 +11,7 @@
#include "bolt/Core/BinaryFunction.h" #include "bolt/Core/BinaryFunction.h"
#include "bolt/Passes/BinaryPasses.h" #include "bolt/Passes/BinaryPasses.h"
+#include "llvm/ADT/SparseBitVector.h"
namespace llvm { namespace llvm {
namespace bolt { namespace bolt {
@@ -20,22 +21,72 @@ namespace bolt {
/// ///
class IdenticalCodeFolding : public BinaryFunctionPass { class IdenticalCodeFolding : public BinaryFunctionPass {
protected: protected:
- bool shouldOptimize(const BinaryFunction &BF) const override {+ /// Return true if the function is safe to fold.
- if (BF.hasUnknownControlFlow())+ bool shouldOptimize(const BinaryFunction &BF) const override;
- return false;
- if (BF.isFolded())
- return false;
- if (BF.hasSDTMarker())
- return false;
- return BinaryFunctionPass::shouldOptimize(BF);
- }
public: public:
+ enum class ICFLevel {
+ None, /// No ICF. (Default)
+ Safe, /// Safe ICF.
+ All, /// Aggressive ICF.
+ };
explicit IdenticalCodeFolding(const cl::opt<bool> &PrintPass) explicit IdenticalCodeFolding(const cl::opt<bool> &PrintPass)
: BinaryFunctionPass(PrintPass) {} : BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "identical-code-folding"; } const char *getName() const override { return "identical-code-folding"; }
Error runOnFunctions(BinaryContext &BC) override; Error runOnFunctions(BinaryContext &BC) override;
+
+private:
+ /// Bit vector of memory addresses of vtables.
+ llvm::SparseBitVector<> VTableBitVector;
+
+ /// Return true if the memory address is in a vtable.
+ bool isAddressInVTable(uint64_t Address) const {
+ return VTableBitVector.test(Address / 8);
+ }
+
+ /// Mark memory address of a vtable as used.
+ void setAddressUsedInVTable(uint64_t Address) {
+ VTableBitVector.set(Address / 8);
+ }
+
+ /// Scan symbol table and mark memory addresses of
+ /// vtables.
+ void initVTableReferences(const BinaryContext &BC);
+
+ /// Analyze code section and relocations and mark functions that are not
+ /// safe to fold.
+ void markFunctionsUnsafeToFold(BinaryContext &BC);
+
+ /// Process static and dynamic relocations in the data sections to identify
+ /// function references, and mark them as unsafe to fold. It filters out
+ /// symbol references that are in vtables.
+ void analyzeDataRelocations(BinaryContext &BC);
+
+ /// Process functions that have been disassembled and mark functions that are
+ /// used in non-control flow instructions as unsafe to fold.
+ void analyzeFunctions(BinaryContext &BC);
+};
+
+class DeprecatedICFNumericOptionParser
+ : public cl::parser<IdenticalCodeFolding::ICFLevel> {
+public:
+ explicit DeprecatedICFNumericOptionParser(cl::Option &O)
+ : cl::parser<IdenticalCodeFolding::ICFLevel>(O) {}
+
+ bool parse(cl::Option &O, StringRef ArgName, StringRef Arg,
+ IdenticalCodeFolding::ICFLevel &Value) {
+ if (Arg == "0" || Arg == "1") {
+ Value = (Arg == "0") ? IdenticalCodeFolding::ICFLevel::None
+ : IdenticalCodeFolding::ICFLevel::All;
+ errs() << formatv("BOLT-WARNING: specifying numeric value \"{0}\" "
+ "for option -{1} is deprecated\n",
+ Arg, ArgName);
+ return false;
+ }
+ return cl::parser<IdenticalCodeFolding::ICFLevel>::parse(O, ArgName, Arg,
+ Value);
+ }
}; };
} // namespace bolt } // namespace bolt
bolt/lib/Core/BinaryFunction.cpp
@@ -1504,6 +1504,20 @@ MCSymbol *BinaryFunction::registerBranch(uint64_t Src, uint64_t Dst) {
return Target; return Target;
} }
+void BinaryFunction::analyzeInstructionForFuncReference(const MCInst &Inst) {
+ for (const MCOperand &Op : MCPlus::primeOperands(Inst)) {
+ if (!Op.isExpr())
+ continue;
+ const MCExpr &Expr = *Op.getExpr();
+ if (Expr.getKind() != MCExpr::SymbolRef)
+ continue;
+ const MCSymbol &Symbol = cast<MCSymbolRefExpr>(Expr).getSymbol();
+ // Set HasAddressTaken for a function regardless of the ICF level.
+ if (BinaryFunction *BF = BC.getFunctionForSymbol(&Symbol))
+ BF->setHasAddressTaken(true);
+ }
+}
+
bool BinaryFunction::scanExternalRefs() { bool BinaryFunction::scanExternalRefs() {
bool Success = true; bool Success = true;
bool DisassemblyFailed = false; bool DisassemblyFailed = false;
@@ -1624,6 +1638,8 @@ bool BinaryFunction::scanExternalRefs() {
[](const MCOperand &Op) { return Op.isExpr(); })) { [](const MCOperand &Op) { return Op.isExpr(); })) {
// Skip assembly if the instruction may not have any symbolic operands. // Skip assembly if the instruction may not have any symbolic operands.
continue; continue;
+ } else {
+ analyzeInstructionForFuncReference(Instruction);
} }
// Emit the instruction using temp emitter and generate relocations. // Emit the instruction using temp emitter and generate relocations.
bolt/lib/Passes/IdenticalCodeFolding.cpp
@@ -15,6 +15,7 @@
#include "bolt/Core/ParallelUtilities.h" #include "bolt/Core/ParallelUtilities.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ThreadPool.h" #include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Timer.h" #include "llvm/Support/Timer.h"
#include <atomic> #include <atomic>
@@ -42,8 +43,41 @@ TimeICF("time-icf",
cl::ReallyHidden, cl::ReallyHidden,
cl::ZeroOrMore, cl::ZeroOrMore,
cl::cat(BoltOptCategory)); cl::cat(BoltOptCategory));
+
+cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
+ DeprecatedICFNumericOptionParser>
+ ICF("icf", cl::desc("fold functions with identical code"),
+ cl::init(bolt::IdenticalCodeFolding::ICFLevel::None),
+ cl::values(clEnumValN(bolt::IdenticalCodeFolding::ICFLevel::All, "all",
+ "Enable identical code folding"),
+ clEnumValN(bolt::IdenticalCodeFolding::ICFLevel::All, "1",
+ "Enable identical code folding"),
+ clEnumValN(bolt::IdenticalCodeFolding::ICFLevel::All, "",
+ "Enable identical code folding"),
+ clEnumValN(bolt::IdenticalCodeFolding::ICFLevel::None,
+ "none",
+ "Disable identical code folding (default)"),
+ clEnumValN(bolt::IdenticalCodeFolding::ICFLevel::None, "0",
+ "Disable identical code folding (default)"),
+ clEnumValN(bolt::IdenticalCodeFolding::ICFLevel::Safe,
+ "safe", "Enable safe identical code folding")),
+ cl::ZeroOrMore, cl::ValueOptional, cl::cat(BoltOptCategory));
} // namespace opts } // namespace opts
+bool IdenticalCodeFolding::shouldOptimize(const BinaryFunction &BF) const {
+ if (BF.hasUnknownControlFlow())
+ return false;
+ if (BF.isFolded())
+ return false;
+ if (BF.hasSDTMarker())
+ return false;
+ if (BF.isPseudo())
+ return false;
+ if (opts::ICF == ICFLevel::Safe && BF.hasAddressTaken())
+ return false;
+ return BinaryFunctionPass::shouldOptimize(BF);
+}
+
/// Compare two jump tables in 2 functions. The function relies on consistent /// Compare two jump tables in 2 functions. The function relies on consistent
/// ordering of basic blocks in both binary functions (e.g. DFS). /// ordering of basic blocks in both binary functions (e.g. DFS).
static bool equalJumpTables(const JumpTable &JumpTableA, static bool equalJumpTables(const JumpTable &JumpTableA,
@@ -340,6 +374,74 @@ typedef std::unordered_map<BinaryFunction *, std::vector<BinaryFunction *>,
namespace llvm { namespace llvm {
namespace bolt { namespace bolt {
+void IdenticalCodeFolding::initVTableReferences(const BinaryContext &BC) {
+ for (const auto &[Address, Data] : BC.getBinaryData()) {
+ // Filter out all symbols that are not vtables.
+ if (!Data->getName().starts_with("_ZTV"))
+ continue;
+ for (uint64_t I = Address, End = I + Data->getSize(); I < End; I += 8)
+ setAddressUsedInVTable(I);
+ }
+}
+
+void IdenticalCodeFolding::analyzeDataRelocations(BinaryContext &BC) {
+ initVTableReferences(BC);
+ // For static relocations there should be a symbol for function references.
+ for (const BinarySection &Sec : BC.sections()) {
+ if (!Sec.hasSectionRef() || !Sec.isData())
+ continue;
+ for (const auto &Rel : Sec.relocations()) {
+ const uint64_t RelAddr = Rel.Offset + Sec.getAddress();
+ if (isAddressInVTable(RelAddr))
+ continue;
+ if (BinaryFunction *BF = BC.getFunctionForSymbol(Rel.Symbol))
+ BF->setHasAddressTaken(true);
+ }
+ // For dynamic relocations there are two cases:
+ // 1: No symbol and only addend.
+ // 2: There is a symbol, but it does not references a function in a binary.
+ for (const auto &Rel : Sec.dynamicRelocations()) {
+ const uint64_t RelAddr = Rel.Offset + Sec.getAddress();
+ if (isAddressInVTable(RelAddr))
+ continue;
+ if (BinaryFunction *BF = BC.getBinaryFunctionAtAddress(Rel.Addend))
+ BF->setHasAddressTaken(true);
+ }
+ }
+}
+
+void IdenticalCodeFolding::analyzeFunctions(BinaryContext &BC) {
+ ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
+ for (const BinaryBasicBlock &BB : BF)
+ for (const MCInst &Inst : BB)
+ if (!(BC.MIB->isCall(Inst) || BC.MIB->isBranch(Inst)))
+ BF.analyzeInstructionForFuncReference(Inst);
+ };
+ ParallelUtilities::PredicateTy SkipFunc =
+ [&](const BinaryFunction &BF) -> bool { return !BF.hasCFG(); };
+ ParallelUtilities::runOnEachFunction(
+ BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
+ SkipFunc, "markUnsafe");
+
+ LLVM_DEBUG({
+ for (const auto &BFIter : BC.getBinaryFunctions()) {
+ if (!BFIter.second.hasAddressTaken())
+ continue;
+ dbgs() << "BOLT-DEBUG: skipping function with reference taken "
+ << BFIter.second.getOneName() << '\n';
+ }
+ });
+}
+
+void IdenticalCodeFolding::markFunctionsUnsafeToFold(BinaryContext &BC) {
+ NamedRegionTimer MarkFunctionsUnsafeToFoldTimer(
+ "markFunctionsUnsafeToFold", "markFunctionsUnsafeToFold", "ICF breakdown",
+ "ICF breakdown", opts::TimeICF);
+ if (!BC.isX86())
+ BC.outs() << "BOLT-WARNING: safe ICF is only supported for x86\n";
+ analyzeDataRelocations(BC);
+ analyzeFunctions(BC);
+}
Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) { Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
const size_t OriginalFunctionCount = BC.getBinaryFunctions().size(); const size_t OriginalFunctionCount = BC.getBinaryFunctions().size();
@@ -385,7 +487,7 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
"ICF breakdown", opts::TimeICF); "ICF breakdown", opts::TimeICF);
for (auto &BFI : BC.getBinaryFunctions()) { for (auto &BFI : BC.getBinaryFunctions()) {
BinaryFunction &BF = BFI.second; BinaryFunction &BF = BFI.second;
- if (!this->shouldOptimize(BF))+ if (!shouldOptimize(BF))
continue; continue;
CongruentBuckets[&BF].emplace(&BF); CongruentBuckets[&BF].emplace(&BF);
} }
@@ -475,7 +577,8 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
LLVM_DEBUG(SinglePass.stopTimer()); LLVM_DEBUG(SinglePass.stopTimer());
}; };
-+ if (opts::ICF == ICFLevel::Safe)
+ markFunctionsUnsafeToFold(BC);
hashFunctions(); hashFunctions();
createCongruentBuckets(); createCongruentBuckets();
bolt/lib/Passes/LongJmp.cpp
@@ -138,9 +138,9 @@ BinaryBasicBlock *LongJmpPass::lookupStubFromGroup(
const std::pair<uint64_t, BinaryBasicBlock *> &RHS) { const std::pair<uint64_t, BinaryBasicBlock *> &RHS) {
return LHS.first < RHS.first; return LHS.first < RHS.first;
}); });
- if (Cand == Candidates.end())+ if (Cand == Candidates.end()) {
- return nullptr;+ Cand = std::prev(Cand);
- if (Cand != Candidates.begin()) {+ } else if (Cand != Candidates.begin()) {
const StubTy *LeftCand = std::prev(Cand); const StubTy *LeftCand = std::prev(Cand);
if (Cand->first - DotAddress > DotAddress - LeftCand->first) if (Cand->first - DotAddress > DotAddress - LeftCand->first)
Cand = LeftCand; Cand = LeftCand;
bolt/lib/Rewrite/BinaryPassManager.cpp
@@ -54,6 +54,9 @@ extern cl::opt<bool> PrintDynoStats;
extern cl::opt<bool> DumpDotAll; extern cl::opt<bool> DumpDotAll;
extern cl::opt<std::string> AsmDump; extern cl::opt<std::string> AsmDump;
extern cl::opt<bolt::PLTCall::OptType> PLT; extern cl::opt<bolt::PLTCall::OptType> PLT;
+extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
+ llvm::bolt::DeprecatedICFNumericOptionParser>
+ ICF;
static cl::opt<bool> static cl::opt<bool>
DynoStatsAll("dyno-stats-all", DynoStatsAll("dyno-stats-all",
@@ -65,9 +68,6 @@ static cl::opt<bool>
cl::desc("eliminate unreachable code"), cl::init(true), cl::desc("eliminate unreachable code"), cl::init(true),
cl::cat(BoltOptCategory)); cl::cat(BoltOptCategory));
-cl::opt<bool> ICF("icf", cl::desc("fold functions with identical code"),
- cl::cat(BoltOptCategory));
-
static cl::opt<bool> JTFootprintReductionFlag( static cl::opt<bool> JTFootprintReductionFlag(
"jt-footprint-reduction", "jt-footprint-reduction",
cl::desc("make jump tables size smaller at the cost of using more " cl::desc("make jump tables size smaller at the cost of using more "
@@ -126,6 +126,11 @@ static cl::opt<bool> PrintJTFootprintReduction(
cl::desc("print function after jt-footprint-reduction pass"), cl::Hidden, cl::desc("print function after jt-footprint-reduction pass"), cl::Hidden,
cl::cat(BoltOptCategory)); cl::cat(BoltOptCategory));
+static cl::opt<bool>
+ PrintAdrRelaxation("print-adr-relaxation",
+ cl::desc("print functions after ADR Relaxation pass"),
+ cl::Hidden, cl::cat(BoltOptCategory));
+
static cl::opt<bool> static cl::opt<bool>
PrintLongJmp("print-longjmp", PrintLongJmp("print-longjmp",
cl::desc("print functions after longjmp pass"), cl::Hidden, cl::desc("print functions after longjmp pass"), cl::Hidden,
@@ -398,7 +403,7 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
opts::StripRepRet); opts::StripRepRet);
Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF), Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
- opts::ICF);+ opts::ICF != IdenticalCodeFolding::ICFLevel::None);
Manager.registerPass( Manager.registerPass(
std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1), std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1),
@@ -423,7 +428,7 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
Manager.registerPass(std::make_unique<Inliner>(PrintInline)); Manager.registerPass(std::make_unique<Inliner>(PrintInline));
Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF), Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
- opts::ICF);+ opts::ICF != IdenticalCodeFolding::ICFLevel::None);
Manager.registerPass(std::make_unique<PLTCall>(PrintPLT)); Manager.registerPass(std::make_unique<PLTCall>(PrintPLT));
@@ -493,7 +498,8 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
Manager.registerPass(std::make_unique<ReorderData>()); Manager.registerPass(std::make_unique<ReorderData>());
if (BC.isAArch64()) { if (BC.isAArch64()) {
- Manager.registerPass(std::make_unique<ADRRelaxationPass>());+ Manager.registerPass(
+ std::make_unique<ADRRelaxationPass>(PrintAdrRelaxation));
// Tighten branches according to offset differences between branch and // Tighten branches according to offset differences between branch and
// targets. No extra instructions after this pass, otherwise we may have // targets. No extra instructions after this pass, otherwise we may have
bolt/lib/Rewrite/BoltDiff.cpp
@@ -28,7 +28,9 @@ using namespace bolt;
namespace opts { namespace opts {
extern cl::OptionCategory BoltDiffCategory; extern cl::OptionCategory BoltDiffCategory;
extern cl::opt<bool> NeverPrint; extern cl::opt<bool> NeverPrint;
-extern cl::opt<bool> ICF;+extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
+ llvm::bolt::DeprecatedICFNumericOptionParser>
+ ICF;
static cl::opt<bool> IgnoreLTOSuffix( static cl::opt<bool> IgnoreLTOSuffix(
"ignore-lto-suffix", "ignore-lto-suffix",
@@ -697,7 +699,7 @@ void RewriteInstance::compare(RewriteInstance &RI2) {
} }
// Pre-pass ICF // Pre-pass ICF
- if (opts::ICF) {+ if (opts::ICF != IdenticalCodeFolding::ICFLevel::None) {
IdenticalCodeFolding ICF(opts::NeverPrint); IdenticalCodeFolding ICF(opts::NeverPrint);
outs() << "BOLT-DIFF: Starting ICF pass for binary 1"; outs() << "BOLT-DIFF: Starting ICF pass for binary 1";
BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*BC)); BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*BC));
bolt/lib/Rewrite/RewriteInstance.cpp
@@ -19,6 +19,7 @@
#include "bolt/Core/Relocation.h" #include "bolt/Core/Relocation.h"
#include "bolt/Passes/BinaryPasses.h" #include "bolt/Passes/BinaryPasses.h"
#include "bolt/Passes/CacheMetrics.h" #include "bolt/Passes/CacheMetrics.h"
+#include "bolt/Passes/IdenticalCodeFolding.h"
#include "bolt/Passes/ReorderFunctions.h" #include "bolt/Passes/ReorderFunctions.h"
#include "bolt/Profile/BoltAddressTranslation.h" #include "bolt/Profile/BoltAddressTranslation.h"
#include "bolt/Profile/DataAggregator.h" #include "bolt/Profile/DataAggregator.h"
@@ -85,6 +86,9 @@ extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
extern cl::opt<bool> TerminalTrap; extern cl::opt<bool> TerminalTrap;
extern cl::opt<bool> TimeBuild; extern cl::opt<bool> TimeBuild;
extern cl::opt<bool> TimeRewrite; extern cl::opt<bool> TimeRewrite;
+extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
+ llvm::bolt::DeprecatedICFNumericOptionParser>
+ ICF;
cl::opt<bool> AllowStripped("allow-stripped", cl::opt<bool> AllowStripped("allow-stripped",
cl::desc("allow processing of stripped binaries"), cl::desc("allow processing of stripped binaries"),
@@ -2055,6 +2059,13 @@ void RewriteInstance::adjustCommandLineOptions() {
exit(1); exit(1);
} }
+ if (!BC->HasRelocations &&
+ opts::ICF == IdenticalCodeFolding::ICFLevel::Safe) {
+ BC->errs() << "BOLT-ERROR: binary built without relocations. Safe ICF is "
+ "not supported\n";
+ exit(1);
+ }
+
if (opts::Instrument || if (opts::Instrument ||
(opts::ReorderFunctions != ReorderFunctions::RT_NONE && (opts::ReorderFunctions != ReorderFunctions::RT_NONE &&
!opts::HotText.getNumOccurrences())) { !opts::HotText.getNumOccurrences())) {
bolt/test/AArch64/long-jmp-one-stub.s
@@ -0,0 +1,32 @@
+## This test verifies that no unnecessary stubs are inserted when each DotAddress increases during a lookup.
+
+# REQUIRES: system-linux, asserts
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -O0 %t.o -o %t.exe -Wl,-q
+# RUN: link_fdata %s %t.o %t.fdata
+# RUN: llvm-bolt %t.exe -o %t.bolt \
+# RUN: --data %t.fdata | FileCheck %s
+
+# CHECK: BOLT-INFO: Inserted 1 stubs in the hot area and 0 stubs in the cold area.
+
+ .section .text
+ .global _start
+ .global far_away_func
+
+ .align 4
+ .global _start
+ .type _start, %function
+_start:
+# FDATA: 0 [unknown] 0 1 _start 0 0 100
+ bl far_away_func
+ bl far_away_func
+ ret
+ .space 0x8000000
+ .global far_away_func
+ .type far_away_func, %function
+far_away_func:
+ add x0, x0, #1
+ ret
+
+.reloc 0, R_AARCH64_NONE
bolt/test/X86/dwarf5-debug-names-gnu-push-tls-address.s
@@ -27,71 +27,35 @@
## x = 10; ## x = 10;
## return x; ## return x;
## } ## }
- .text
.file "main.cpp" .file "main.cpp"
.file 0 "gnu_tls_push" "main.cpp" md5 0x551db97d5e23dc6a81abdc5ade4d9d71 .file 0 "gnu_tls_push" "main.cpp" md5 0x551db97d5e23dc6a81abdc5ade4d9d71
- .globl main # -- Begin function main+ .globl main
- .p2align 4, 0x90
.type main,@function .type main,@function
-main: # @main+main:
.Lfunc_begin0: .Lfunc_begin0:
- .loc 0 2 0 # main.cpp:2:0+ .loc 0 2 0
- .cfi_startproc+ .loc 0 3 3 prologue_end
-# %bb.0: # %entry+ .loc 0 3 5 is_stmt 0
- pushq %rbp+ .loc 0 4 10 is_stmt 1
- .cfi_def_cfa_offset 16+ .loc 0 4 3 epilogue_begin is_stmt 0
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
- movl $0, -4(%rbp)
-.Ltmp0:
- .loc 0 3 3 prologue_end # main.cpp:3:3
- movq %fs:0, %rax
- leaq x@TPOFF(%rax), %rax
- .loc 0 3 5 is_stmt 0 # main.cpp:3:5
- movl $10, (%rax)
- .loc 0 4 10 is_stmt 1 # main.cpp:4:10
- movq %fs:0, %rax
- leaq x@TPOFF(%rax), %rax
- movl (%rax), %eax
- .loc 0 4 3 epilogue_begin is_stmt 0 # main.cpp:4:3
- popq %rbp
- .cfi_def_cfa %rsp, 8
retq retq
-.Ltmp1:
.Lfunc_end0: .Lfunc_end0:
.size main, .Lfunc_end0-main .size main, .Lfunc_end0-main
- .cfi_endproc+
- # -- End function+ .hidden _ZTW1x
- .section .text._ZTW1x,"axG",@progbits,_ZTW1x,comdat
- .hidden _ZTW1x # -- Begin function _ZTW1x
.weak _ZTW1x .weak _ZTW1x
- .p2align 4, 0x90
.type _ZTW1x,@function .type _ZTW1x,@function
-_ZTW1x: # @_ZTW1x+_ZTW1x:
.Lfunc_begin1: .Lfunc_begin1:
- .cfi_startproc
-# %bb.0:
- pushq %rbp
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
- movq %fs:0, %rax
- leaq x@TPOFF(%rax), %rax
- popq %rbp
- .cfi_def_cfa %rsp, 8
retq retq
.Lfunc_end1: .Lfunc_end1:
.size _ZTW1x, .Lfunc_end1-_ZTW1x .size _ZTW1x, .Lfunc_end1-_ZTW1x
- .cfi_endproc+
- # -- End function+ .type x,@object
- .type x,@object # @x
.section .tbss,"awT",@nobits .section .tbss,"awT",@nobits
.globl x .globl x
- .p2align 2, 0x0
x: x:
- .long 0 # 0x0+ .long 0
.size x, 4 .size x, 4
.section .debug_abbrev,"",@progbits .section .debug_abbrev,"",@progbits
bolt/test/X86/icf-safe-icp.test
@@ -0,0 +1,148 @@
+## Check that BOLT handles correctly folding functions with --icf=safe
+## that can be referenced through a non control flow instruction when ICP optimization is enabled.
+## This tests also checks that destructors are folded.
+
+# REQUIRES: system-linux, asserts
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt --no-threads %t.exe --icf -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=ICFCHECK %s
+# RUN: llvm-bolt --no-threads %t.exe --icf=safe -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECK %s
+
+# ICFCHECK: ICF iteration 1
+# ICFCHECK-NEXT: folding Derived3Destructor into Derived2Destructor
+# ICFCHECK-NEXT: folding Derived3Func into Derived2Func
+
+# SAFEICFCHECK: skipping function with reference taken Derived3Func
+# SAFEICFCHECK-NEXT: ICF iteration 1
+# SAFEICFCHECK-NEXT: folding Derived3Destructor into Derived2Destructor
+# SAFEICFCHECK-NEXT: ===---------
+
+
+## generate profile
+## clang++ -O2 -fprofile-generate=. main.cpp -c -o mainProf.o
+## PROF=test.profdata
+## clang++ -m64 -fprofile-use=$PROF \
+## -mllvm -disable-icp=true -mllvm -print-after-all \
+## -g0 -flto=thin -fwhole-program-vtables -fno-split-lto-unit -O2 \
+## -fdebug-types-section \
+## main.cpp -c -o mainProfLTO.bc
+## PASS='pgo-icall-prom'
+## clang++ -m64 -fprofile-use=$PROF \
+## -O3 -Rpass=$PASS \
+## -mllvm -print-before=$PASS \
+## -mllvm -print-after=$PASS \
+## -mllvm -filter-print-funcs=main \
+## -mllvm -debug-only=$PASS \
+## -x ir \
+## mainProfLTO.bc -c -o mainProfFinal.o
+
+## class Base {
+## public:
+## virtual int func(int a, int b) const = 0;
+##
+## virtual ~Base() {};
+## };
+##
+## class Derived2 : public Base {
+## int c = 5;
+## public:
+## __attribute__((noinline)) int func(int a, int b)const override { return a * (a - b) + this->c; }
+##
+## ~Derived2() {}
+## };
+##
+## class Derived3 : public Base {
+## int c = 500;
+## public:
+## __attribute__((noinline)) int func(int a, int b) const override { return a * (a - b) + this->c; }
+## ~Derived3() {}
+## };
+##
+## __attribute__((noinline)) Base *createType(int a) {
+## Base *base = nullptr;
+## if (a == 4)
+## base = new Derived2();
+## else
+## base = new Derived3();
+## return base;
+## }
+##
+## extern int returnFive();
+## extern int returnFourOrFive(int val);
+## int main(int argc, char **argv) {
+## int sum = 0;
+## int a = returnFourOrFive(argc);
+## int b = returnFive();
+## Base *ptr = createType(a);
+## Base *ptr2 = createType(b);
+## sum += ptr->func(b, a) + ptr2->func(b, a);
+## return 0;
+## }
+## clang++ -c helper.cpp -o helper.o
+## int FooVar = 1;
+## int BarVar = 2;
+##
+## int fooGlobalFuncHelper(int a, int b) {
+## return 5;
+## }
+## Manually modified to remove "extra" assembly.
+ .globl main
+ .type main,@function
+main:
+ leaq Derived3Func(%rip), %rcx
+ callq Derived3Func
+ .size main, .-main
+
+ .weak Derived2Func
+ .type Derived2Func,@function
+Derived2Func:
+ imull %esi, %eax
+ retq
+ .size Derived2Func, .-Derived2Func
+
+ .weak Derived2Destructor
+ .type Derived2Destructor,@function
+Derived2Destructor:
+ jmp _ZdlPvm@PLT
+ .size Derived2Destructor, .-Derived2Destructor
+
+ .weak Derived3Func
+ .type Derived3Func,@function
+Derived3Func:
+ imull %esi, %eax
+ retq
+ .size Derived3Func, .-Derived3Func
+
+ .weak _ZN4BaseD2Ev
+ .type _ZN4BaseD2Ev,@function
+_ZN4BaseD2Ev:
+ retq
+ .size _ZN4BaseD2Ev, .-_ZN4BaseD2Ev
+
+ .weak Derived3Destructor
+ .type Derived3Destructor,@function
+Derived3Destructor:
+ jmp _ZdlPvm@PLT
+ .size Derived3Destructor, .-Derived3Destructor
+
+ .type _ZTV8Derived2,@object
+ .section .data.rel.ro._ZTV8Derived2,"awG",@progbits,_ZTV8Derived2,comdat
+ .weak _ZTV8Derived2
+_ZTV8Derived2:
+ .quad 0
+ .quad _ZTI8Derived2
+ .quad Derived2Func
+ .quad _ZN4BaseD2Ev
+ .quad Derived2Destructor
+ .size _ZTV8Derived2, 40
+
+ .type _ZTV8Derived3,@object
+ .section .data.rel.ro._ZTV8Derived3,"awG",@progbits,_ZTV8Derived3,comdat
+ .weak _ZTV8Derived3
+_ZTV8Derived3:
+ .quad 0
+ .quad _ZTI8Derived3
+ .quad Derived3Func
+ .quad _ZN4BaseD2Ev
+ .quad Derived3Destructor
+ .size _ZTV8Derived3, 40
bolt/test/X86/icf-safe-process-rela-data.test
@@ -0,0 +1,64 @@
+## Check that BOLT handles correctly folding functions with --icf=safe that are only referenced from a .rela.data section.
+
+# REQUIRES: system-linux, asserts
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags %t1.o -o %t.exe -Wl,-q -no-pie
+# RUN: llvm-bolt --no-threads %t.exe --icf -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=ICFCHECK %s
+# RUN: llvm-bolt --no-threads %t.exe --icf=safe -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECK %s
+
+# ICFCHECK: ICF iteration 1
+# ICFCHECK-NEXT: folding barAddFunc into fooAddFunc
+
+# SAFEICFCHECK: skipping function with reference taken fooAddFunc
+# SAFEICFCHECK-NEXT: skipping function with reference taken barAddFunc
+# SAFEICFCHECK-NEXT: ICF iteration 1
+# SAFEICFCHECK-NEXT: ===---------
+
+## clang++ main.cpp
+## Other functions removed for brevity.
+## int main(int argc, char **argv) {
+## const static int (*const funcGlobalBarAdd)(int, int) = barAddHdlper;
+## const int (* const funcGlobalBarMul)(int, int) = fooGlobalFuncHelper;
+## helper2(funcGlobalBarAdd, funcGlobalFooAdd, 3, 4)
+## }
+## Extra assembly removed.
+
+ .globl fooAddFunc
+ .type fooAddFunc,@function
+fooAddFunc:
+ addl -8(%rbp), %eax
+ retq
+ .size fooAddFunc, .-fooAddFunc
+
+ .globl barAddFunc
+ .type barAddFunc,@function
+barAddFunc:
+ addl -8(%rbp), %eax
+ retq
+ .size barAddFunc, .-barAddFunc
+
+ .globl helperFunc
+ .type helperFunc,@function
+helperFunc:
+ retq
+ .size helperFunc, .-helperFunc
+
+ .globl main
+ .type main,@function
+main:
+ movq localStaticVarBarAdd, %rdi
+ movq localStaticVarFooAdd, %rsi
+ callq helperFunc
+ retq
+ .size main, .-main
+
+ .type localStaticVarBarAdd,@object # @localStaticVarBarAdd
+ .data
+localStaticVarBarAdd:
+ .quad barAddFunc
+ .size localStaticVarBarAdd, 8
+
+ .type localStaticVarFooAdd,@object # @localStaticVarFooAdd
+localStaticVarFooAdd:
+ .quad fooAddFunc
+ .size localStaticVarFooAdd, 8
bolt/test/X86/icf-safe-test1-no-relocs.test
@@ -0,0 +1,20 @@
+## Check that BOLT reports an error for a binary with no relocations with the --icf=safe option.
+
+# REQUIRES: system-linux, asserts
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags %t1.o -o %t.exe
+# RUN: not llvm-bolt --no-threads %t.exe --icf=safe -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECK %s
+
+# SAFEICFCHECK: BOLT-ERROR: binary built without relocations. Safe ICF is not supported
+
+## int main(int argc, char **argv) {
+## return temp;
+## }
+ .globl main
+ .type main,@function
+main:
+ .cfi_startproc
+ retq
+.Lfunc_end8:
+ .size main, .-main
+ .cfi_endproc
bolt/test/X86/icf-safe-test1.test
@@ -0,0 +1,98 @@
+## Check that BOLT handles correctly folding functions with --icf=safe that can be referenced by non-control flow instructions.
+## It invokes BOLT twice first testing CFG path, and second when functions have to be disassembled.
+
+# REQUIRES: system-linux, asserts
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags %t1.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt --no-threads %t.exe --icf -debug-only=bolt-icf \
+# RUN: -o %t.bolt 2>&1 | FileCheck --check-prefix=ICFCHECK %s
+# RUN: llvm-bolt --no-threads %t.exe --icf=safe -debug-only=bolt-icf \
+# RUN: -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECK %s
+# RUN: llvm-bolt --no-threads %t.exe --icf=safe -debug-only=bolt-icf \
+# RUN: --skip-funcs=helper1Func,main -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECKNOCFG %s
+
+# ICFCHECK: ICF iteration 1
+# ICFCHECK-NEXT: folding barAddFunc into fooAddFunc
+# ICFCHECK-NEXT: folding barSubFunc into fooSubFunc
+
+# SAFEICFCHECK: skipping function with reference taken barAddFunc
+# SAFEICFCHECK-NEXT: ICF iteration 1
+# SAFEICFCHECK-NEXT: folding barSubFunc into fooSubFunc
+# SAFEICFCHECK-NEXT: ===---------
+
+# SAFEICFCHECKNOCFG: skipping function with reference taken barAddFunc
+# SAFEICFCHECKNOCFG-NEXT: ICF iteration 1
+# SAFEICFCHECKNOCFG-NEXT: folding barSubFunc into fooSubFunc
+# SAFEICFCHECKNOCFG-NEXT: ===---------
+
+## clang++ -c main.cpp -o main.o
+## extern int FooVar;
+## extern int BarVar;
+## [[clang::noinline]]
+## int fooSub(int a, int b) {
+## return a - b;
+## }
+## [[clang::noinline]]
+## int barSub(int a, int b) {
+## return a - b;
+## }
+## [[clang::noinline]]
+## int fooAdd(int a, int b) {
+## return a + b;
+## }
+## [[clang::noinline]]
+## int barAdd(int a, int b) {
+## return a + b;
+## }
+## int main(int argc, char **argv) {
+## int temp = helper1(barAdd, FooVar, BarVar) +
+## fooSub(FooVar, BarVar) +
+## barSub(FooVar, BarVar) + fooAdd(FooVar, BarVar);
+## return temp;
+## }
+ .globl fooSubFunc
+ .type fooSubFunc,@function
+fooSubFunc:
+ subl -8(%rbp), %eax
+ retq
+ .size fooSubFunc, .-fooSubFunc
+
+ .globl barSubFunc
+ .type barSubFunc,@function
+barSubFunc:
+ subl -8(%rbp), %eax
+ retq
+ .size barSubFunc, .-barSubFunc
+
+ .globl fooAddFunc
+ .type fooAddFunc,@function
+fooAddFunc:
+ addl -8(%rbp), %eax
+ retq
+ .size fooAddFunc, .-fooAddFunc
+
+ .globl barAddFunc
+ .type barAddFunc,@function
+barAddFunc:
+ addl -8(%rbp), %eax
+ retq
+ .size barAddFunc, .-barAddFunc
+
+ .globl helper1Func
+ .type helper1Func,@function
+helper1Func:
+ leaq barAddFunc(%rip), %rax
+ cmpq %rax, -16(%rbp)
+ retq
+ .size helper1Func, .-helper1Func
+
+ .globl main
+ .type main,@function
+main:
+ leaq barAddFunc(%rip), %rdi
+ callq helper1Func
+ callq fooSubFunc
+ callq barSubFunc
+ callq fooAddFunc
+ retq
+ .size main, .-main
bolt/test/X86/icf-safe-test2GlobalConstPtrNoPic.test
@@ -0,0 +1,95 @@
+## Check that BOLT handles correctly folding functions with --icf=safe that can be referenced by non-control flow instructions,
+## when binary is built with -fno-PIC/-fno-PIE.
+
+# REQUIRES: system-linux, asserts
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o
+# RUN: %clang %cflags %t1.o -o %t.exe -Wl,-q -no-pie
+# RUN: llvm-bolt --no-threads %t.exe --icf -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=ICFCHECK %s
+# RUN: llvm-bolt --no-threads %t.exe --icf=safe -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECK %s
+
+# ICFCHECK: ICF iteration 1
+# ICFCHECK-NEXT: folding barAddFunc into fooAddFunc
+# ICFCHECK-NEXT: folding barMulFunc into fooMulFunc
+
+# SAFEICFCHECK: skipping function with reference taken fooMulFunc
+# SAFEICFCHECK-NEXT: skipping function with reference taken barMulFunc
+# SAFEICFCHECK-NEXT: skipping function with reference taken barAddFunc
+# SAFEICFCHECK-NEXT: ICF iteration 1
+# SAFEICFCHECK-NEXT: ===---------
+
+## clang++ main.cpp -c -o -fno-PIC
+## Similar code gets generated for external reference function.
+## Other functions removed for brevity.
+## const static int (*const funcGlobalBarAdd)(int, int) = barAdd;
+## const int (*const funcGlobalBarMul)(int, int) = barMul;
+## int main(int argc, char **argv) {
+## int temp = helper1(funcGlobalBarAdd, FooVar, BarVar)
+## return temp;
+## }
+## Manually modified to remove "extra" assembly.
+ .globl fooMulFunc
+ .type fooMulFunc,@function
+fooMulFunc:
+ imull -8(%rbp), %eax
+ retq
+ .size fooMulFunc, .-fooMulFunc
+
+ .globl barMulFunc
+ .type barMulFunc,@function
+barMulFunc:
+ imull -8(%rbp), %eax
+ retq
+ .size barMulFunc, .-barMulFunc
+
+ .globl fooAddFunc
+ .type fooAddFunc,@function
+fooAddFunc:
+ addl -8(%rbp), %eax
+ retq
+ .size fooAddFunc, .-fooAddFunc
+
+ .globl barAddFunc
+ .type barAddFunc,@function
+barAddFunc:
+ addl -8(%rbp), %eax
+ retq
+ .size barAddFunc, .-barAddFunc
+
+ .globl helperFunc
+ .type helperFunc,@function
+helperFunc:
+ movabsq $barAddFunc, %rax
+ cmpq %rax, -16(%rbp)
+ retq
+ .size helperFunc, .-helperFunc
+
+ .globl main
+ .type main,@function
+main:
+ movl FooVar, %esi
+ movl BarVar, %edx
+ movabsq $barAddFunc, %rdi
+ callq helperFunc
+ movabsq $fooMulFunc, %rdi
+ movabsq $barMulFunc, %rsi
+ retq
+ .size main, .-main
+
+ .type FooVar,@object
+ .data
+ .globl FooVar
+FooVar:
+ .long 1
+ .size FooVar, 4
+
+ .type BarVar,@object
+ .globl BarVar
+BarVar:
+ .long 2
+ .size BarVar, 4
+
+ .type .L.str,@object
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "val: %d\n"
+ .size .L.str, 9
bolt/test/X86/linux-static-keys.s
@@ -35,13 +35,13 @@ _start:
.L0: .L0:
jmp L1 jmp L1
# CHECK: jit # CHECK: jit
-# CHECK-SAME: # ID: 1 {{.*}} # Likely: 0 # InitValue: 1+# CHECK-SAME: # ID: 1 {{.*}} # Likely: 1 # InitValue: 0
nop nop
L1: L1:
.nops 5 .nops 5
- jmp .L0
# CHECK: jit # CHECK: jit
-# CHECK-SAME: # ID: 2 {{.*}} # Likely: 1 # InitValue: 1+# CHECK-SAME: # ID: 2 {{.*}} # Likely: 0 # InitValue: 0
+ jmp .L0
## Check that a branch profile associated with a NOP is handled properly when ## Check that a branch profile associated with a NOP is handled properly when
## dynamic branch is created. ## dynamic branch is created.
@@ -67,18 +67,24 @@ foo:
.type __start___jump_table, %object .type __start___jump_table, %object
__start___jump_table: __start___jump_table:
- .long .L0 - . # Jump address+ .long .L0 - . # Jump address
- .long L1 - . # Target address+ .long L1 - . # Target address
- .quad 1 # Key address+ .quad fake_static_key + 1 - . # Key address; LSB = 1 : likely
- .long L1 - . # Jump address+ .long L1 - . # Jump address
- .long L2 - . # Target address+ .long L2 - . # Target address
- .quad 0 # Key address+ .quad fake_static_key -. # Key address; LSB = 0 : unlikely
.globl __stop___jump_table .globl __stop___jump_table
.type __stop___jump_table, %object .type __stop___jump_table, %object
__stop___jump_table: __stop___jump_table:
+## Staic keys (we just use the label ignoring the format of the keys).
+ .data
+ .align 8
+fake_static_key:
+ .quad 0
+
## Fake Linux Kernel sections. ## Fake Linux Kernel sections.
.section __ksymtab,"a",@progbits .section __ksymtab,"a",@progbits
.section __ksymtab_gpl,"a",@progbits .section __ksymtab_gpl,"a",@progbits
bolt/test/merge-fdata-lbr-mode.test
@@ -7,9 +7,9 @@
# RUN: FileCheck %s --input-file %t/merged.fdata # RUN: FileCheck %s --input-file %t/merged.fdata
# CHECK-NOT: no_lbr # CHECK-NOT: no_lbr
-# CHECK: main 2+# CHECK: 1 main 0 1 main 2 1 3
#--- a.fdata #--- a.fdata
-main 1+1 main 0 1 main 2 0 1
#--- b.fdata #--- b.fdata
-main 1+1 main 0 1 main 2 1 2
bolt/test/merge-fdata-mixed-bat-no-lbr.test
@@ -5,7 +5,7 @@
# RUN: split-file %s %t # RUN: split-file %s %t
# RUN: not merge-fdata %t/a.fdata %t/b.fdata 2>&1 | FileCheck %s # RUN: not merge-fdata %t/a.fdata %t/b.fdata 2>&1 | FileCheck %s
-# CHECK: cannot mix profile collected in BOLT and non-BOLT deployments+# CHECK: cannot mix profile with and without boltedcollection
#--- a.fdata #--- a.fdata
boltedcollection boltedcollection
bolt/test/merge-fdata-mixed-mode.test
@@ -6,7 +6,7 @@
# RUN: split-file %s %t # RUN: split-file %s %t
# RUN: not merge-fdata %t/a.fdata %t/b.fdata 2>&1 | FileCheck %s # RUN: not merge-fdata %t/a.fdata %t/b.fdata 2>&1 | FileCheck %s
-# CHECK: cannot mix 'no_lbr' and 'lbr' profiles.+# CHECK: cannot mix profile with and without no_lbr
#--- a.fdata #--- a.fdata
no_lbr no_lbr
bolt/tools/merge-fdata/merge-fdata.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/Signals.h" #include "llvm/Support/Signals.h"
#include "llvm/Support/ThreadPool.h" #include "llvm/Support/ThreadPool.h"
#include <algorithm> #include <algorithm>
+#include <fstream>
#include <mutex> #include <mutex>
#include <unordered_map> #include <unordered_map>
@@ -267,69 +268,68 @@ void mergeLegacyProfiles(const SmallVectorImpl<std::string> &Filenames) {
std::optional<bool> BoltedCollection; std::optional<bool> BoltedCollection;
std::optional<bool> NoLBRCollection; std::optional<bool> NoLBRCollection;
std::mutex BoltedCollectionMutex; std::mutex BoltedCollectionMutex;
- typedef StringMap<uint64_t> ProfileTy;+ struct CounterTy {
+ uint64_t Exec{0};
+ uint64_t Mispred{0};
+ CounterTy &operator+=(const CounterTy &O) {
+ Exec += O.Exec;
+ Mispred += O.Mispred;
+ return *this;
+ }
+ CounterTy operator+(const CounterTy &O) { return *this += O; }
+ };
+ typedef StringMap<CounterTy> ProfileTy;
auto ParseProfile = [&](const std::string &Filename, auto &Profiles) { auto ParseProfile = [&](const std::string &Filename, auto &Profiles) {
const llvm::thread::id tid = llvm::this_thread::get_id(); const llvm::thread::id tid = llvm::this_thread::get_id();
if (isYAML(Filename)) if (isYAML(Filename))
report_error(Filename, "cannot mix YAML and legacy formats"); report_error(Filename, "cannot mix YAML and legacy formats");
- ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
- MemoryBuffer::getFileOrSTDIN(Filename);
- if (std::error_code EC = MB.getError())
- report_error(Filename, EC);
- StringRef Buf = MB.get()->getBuffer();+ std::ifstream FdataFile(Filename, std::ios::in);
+ std::string FdataLine;
+ std::getline(FdataFile, FdataLine);
+
+ auto checkMode = [&](const std::string &Key, std::optional<bool> &Flag) {
+ const bool KeyIsSet = FdataLine.rfind(Key, 0) == 0;
+
+ if (!Flag.has_value())
+ Flag = KeyIsSet;
+ else if (*Flag != KeyIsSet)
+ report_error(Filename, "cannot mix profile with and without " + Key);
+ if (KeyIsSet)
+ // Advance line
+ std::getline(FdataFile, FdataLine);
+ };
+
ProfileTy *Profile; ProfileTy *Profile;
{ {
std::lock_guard<std::mutex> Lock(BoltedCollectionMutex); std::lock_guard<std::mutex> Lock(BoltedCollectionMutex);
// Check if the string "boltedcollection" is in the first line // Check if the string "boltedcollection" is in the first line
- if (Buf.starts_with("boltedcollection\n")) {+ checkMode("boltedcollection", BoltedCollection);
- if (!BoltedCollection.value_or(true))
- report_error(
- Filename,
- "cannot mix profile collected in BOLT and non-BOLT deployments");
- BoltedCollection = true;
- Buf = Buf.drop_front(17);
- } else {
- if (BoltedCollection.value_or(false))
- report_error(
- Filename,
- "cannot mix profile collected in BOLT and non-BOLT deployments");
- BoltedCollection = false;
- }
// Check if the string "no_lbr" is in the first line // Check if the string "no_lbr" is in the first line
// (or second line if BoltedCollection is true) // (or second line if BoltedCollection is true)
- size_t CheckNoLBRPos = Buf.find('\n');+ checkMode("no_lbr", NoLBRCollection);
- if (CheckNoLBRPos != StringRef::npos) {
- StringRef FirstLine = Buf.substr(0, CheckNoLBRPos);
- if (FirstLine.contains("no_lbr")) {
- if (!NoLBRCollection.value_or(true))
- report_error(Filename, "cannot mix 'no_lbr' and 'lbr' profiles");
- NoLBRCollection = true;
- Buf = Buf.drop_front(CheckNoLBRPos + 1);
- } else {
- if (NoLBRCollection.value_or(false))
- report_error(Filename, "cannot mix 'no_lbr' and 'lbr' profiles");
- NoLBRCollection = false;
- }
- }
Profile = &Profiles[tid]; Profile = &Profiles[tid];
} }
- SmallVector<StringRef> Lines;+ do {
- SplitString(Buf, Lines, "\n");+ StringRef Line(FdataLine);
- for (StringRef Line : Lines) {+ CounterTy Count;
- size_t Pos = Line.rfind(" ");+ auto [Signature, ExecCount] = Line.rsplit(' ');
- if (Pos == StringRef::npos)+ if (ExecCount.getAsInteger(10, Count.Exec))
- report_error(Filename, "Malformed / corrupted profile");+ report_error(Filename, "Malformed / corrupted execution count");
- StringRef Signature = Line.substr(0, Pos);+ // Only LBR profile has misprediction field
- uint64_t Count;+ if (!NoLBRCollection.value_or(false)) {
- if (Line.substr(Pos + 1, Line.size() - Pos).getAsInteger(10, Count))+ auto [SignatureLBR, MispredCount] = Signature.rsplit(' ');
- report_error(Filename, "Malformed / corrupted profile counter");+ Signature = SignatureLBR;
+ if (MispredCount.getAsInteger(10, Count.Mispred))
+ report_error(Filename, "Malformed / corrupted misprediction count");
+ }
+
Count += Profile->lookup(Signature); Count += Profile->lookup(Signature);
Profile->insert_or_assign(Signature, Count); Profile->insert_or_assign(Signature, Count);
- }+ } while (std::getline(FdataFile, FdataLine));
}; };
// The final reduction has non-trivial cost, make sure each thread has at // The final reduction has non-trivial cost, make sure each thread has at
@@ -346,7 +346,7 @@ void mergeLegacyProfiles(const SmallVectorImpl<std::string> &Filenames) {
ProfileTy MergedProfile; ProfileTy MergedProfile;
for (const auto &[Thread, Profile] : ParsedProfiles) for (const auto &[Thread, Profile] : ParsedProfiles)
for (const auto &[Key, Value] : Profile) { for (const auto &[Key, Value] : Profile) {
- uint64_t Count = MergedProfile.lookup(Key) + Value;+ CounterTy Count = MergedProfile.lookup(Key) + Value;
MergedProfile.insert_or_assign(Key, Count); MergedProfile.insert_or_assign(Key, Count);
} }
@@ -354,8 +354,12 @@ void mergeLegacyProfiles(const SmallVectorImpl<std::string> &Filenames) {
output() << "boltedcollection\n"; output() << "boltedcollection\n";
if (NoLBRCollection.value_or(false)) if (NoLBRCollection.value_or(false))
output() << "no_lbr\n"; output() << "no_lbr\n";
- for (const auto &[Key, Value] : MergedProfile)+ for (const auto &[Key, Value] : MergedProfile) {
- output() << Key << " " << Value << "\n";+ output() << Key << " ";
+ if (!NoLBRCollection.value_or(false))
+ output() << Value.Mispred << " ";
+ output() << Value.Exec << "\n";
+ }
errs() << "Profile from " << Filenames.size() << " files merged.\n"; errs() << "Profile from " << Filenames.size() << " files merged.\n";
} }
clang-tools-extra/clang-doc/Serialize.cpp
@@ -236,10 +236,10 @@ static RecordDecl *getRecordDeclForType(const QualType &T) {
return nullptr; return nullptr;
} }
-TypeInfo getTypeInfoForType(const QualType &T) {+TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) {
const TagDecl *TD = getTagDeclForType(T); const TagDecl *TD = getTagDeclForType(T);
if (!TD) if (!TD)
- return TypeInfo(Reference(SymbolID(), T.getAsString()));+ return TypeInfo(Reference(SymbolID(), T.getAsString(Policy)));
InfoType IT; InfoType IT;
if (dyn_cast<EnumDecl>(TD)) { if (dyn_cast<EnumDecl>(TD)) {
@@ -250,7 +250,7 @@ TypeInfo getTypeInfoForType(const QualType &T) {
IT = InfoType::IT_default; IT = InfoType::IT_default;
} }
return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
- T.getAsString(), getInfoRelativePath(TD)));+ T.getAsString(Policy), getInfoRelativePath(TD)));
} }
static bool isPublic(const clang::AccessSpecifier AS, static bool isPublic(const clang::AccessSpecifier AS,
@@ -379,10 +379,11 @@ static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly,
if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F)) if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
continue; continue;
+ auto &LO = F->getLangOpts();
// Use getAccessUnsafe so that we just get the default AS_none if it's not // Use getAccessUnsafe so that we just get the default AS_none if it's not
// valid, as opposed to an assert. // valid, as opposed to an assert.
MemberTypeInfo &NewMember = I.Members.emplace_back( MemberTypeInfo &NewMember = I.Members.emplace_back(
- getTypeInfoForType(F->getTypeSourceInfo()->getType()),+ getTypeInfoForType(F->getTypeSourceInfo()->getType(), LO),
F->getNameAsString(), F->getNameAsString(),
getFinalAccessSpecifier(Access, F->getAccessUnsafe())); getFinalAccessSpecifier(Access, F->getAccessUnsafe()));
populateMemberTypeInfo(NewMember, F); populateMemberTypeInfo(NewMember, F);
@@ -412,9 +413,10 @@ static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
} }
static void parseParameters(FunctionInfo &I, const FunctionDecl *D) { static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
+ auto &LO = D->getLangOpts();
for (const ParmVarDecl *P : D->parameters()) { for (const ParmVarDecl *P : D->parameters()) {
FieldTypeInfo &FieldInfo = I.Params.emplace_back( FieldTypeInfo &FieldInfo = I.Params.emplace_back(
- getTypeInfoForType(P->getOriginalType()), P->getNameAsString());+ getTypeInfoForType(P->getOriginalType(), LO), P->getNameAsString());
FieldInfo.DefaultValue = getSourceCode(D, P->getDefaultArgRange()); FieldInfo.DefaultValue = getSourceCode(D, P->getDefaultArgRange());
} }
} }
@@ -541,7 +543,8 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
bool &IsInAnonymousNamespace) { bool &IsInAnonymousNamespace) {
populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir, populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir,
IsInAnonymousNamespace); IsInAnonymousNamespace);
- I.ReturnType = getTypeInfoForType(D->getReturnType());+ auto &LO = D->getLangOpts();
+ I.ReturnType = getTypeInfoForType(D->getReturnType(), LO);
parseParameters(I, D); parseParameters(I, D);
PopulateTemplateParameters(I.Template, D); PopulateTemplateParameters(I.Template, D);
@@ -783,7 +786,8 @@ emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber,
return {}; return {};
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir); Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir);
- Info.Underlying = getTypeInfoForType(D->getUnderlyingType());+ auto &LO = D->getLangOpts();
+ Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
if (Info.Underlying.Type.Name.empty()) { if (Info.Underlying.Type.Name.empty()) {
// Typedef for an unnamed type. This is like "typedef struct { } Foo;" // Typedef for an unnamed type. This is like "typedef struct { } Foo;"
// The record serializer explicitly checks for this syntax and constructs // The record serializer explicitly checks for this syntax and constructs
@@ -809,7 +813,8 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber,
return {}; return {};
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir); Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir);
- Info.Underlying = getTypeInfoForType(D->getUnderlyingType());+ auto &LO = D->getLangOpts();
+ Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
Info.IsUsing = true; Info.IsUsing = true;
// Info is wrapped in its parent scope so is returned in the second position. // Info is wrapped in its parent scope so is returned in the second position.
clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h
@@ -12,7 +12,6 @@
#include "../ClangTidyCheck.h" #include "../ClangTidyCheck.h"
#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h" #include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
-#include <optional>
namespace clang::tidy::bugprone { namespace clang::tidy::bugprone {
@@ -26,8 +25,7 @@ class UncheckedOptionalAccessCheck : public ClangTidyCheck {
public: public:
UncheckedOptionalAccessCheck(StringRef Name, ClangTidyContext *Context) UncheckedOptionalAccessCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
- ModelOptions{+ ModelOptions{Options.get("IgnoreSmartPointerDereference", false)} {}
- Options.getLocalOrGlobal("IgnoreSmartPointerDereference", false)} {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -277,7 +277,7 @@ ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IgnoreArrays(Options.get("IgnoreArrays", false)), IgnoreArrays(Options.get("IgnoreArrays", false)),
- UseAssignment(Options.getLocalOrGlobal("UseAssignment", false)) {}+ UseAssignment(Options.get("UseAssignment", false)) {}
void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) { void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) {
auto IsUserProvidedNonDelegatingConstructor = auto IsUserProvidedNonDelegatingConstructor =
clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp
@@ -119,11 +119,10 @@ void RvalueReferenceParamNotMovedCheck::check(
RvalueReferenceParamNotMovedCheck::RvalueReferenceParamNotMovedCheck( RvalueReferenceParamNotMovedCheck::RvalueReferenceParamNotMovedCheck(
StringRef Name, ClangTidyContext *Context) StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
- AllowPartialMove(Options.getLocalOrGlobal("AllowPartialMove", false)),+ AllowPartialMove(Options.get("AllowPartialMove", false)),
- IgnoreUnnamedParams(+ IgnoreUnnamedParams(Options.get("IgnoreUnnamedParams", false)),
- Options.getLocalOrGlobal("IgnoreUnnamedParams", false)),
IgnoreNonDeducedTemplateTypes( IgnoreNonDeducedTemplateTypes(
- Options.getLocalOrGlobal("IgnoreNonDeducedTemplateTypes", false)) {}+ Options.get("IgnoreNonDeducedTemplateTypes", false)) {}
void RvalueReferenceParamNotMovedCheck::storeOptions( void RvalueReferenceParamNotMovedCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -57,10 +57,9 @@ struct MissingIncludeInfo {
IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name, IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
- IgnoreHeaders(utils::options::parseStringList(+ IgnoreHeaders(
- Options.getLocalOrGlobal("IgnoreHeaders", ""))),+ utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
- DeduplicateFindings(+ DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
- Options.getLocalOrGlobal("DeduplicateFindings", true)) {
for (const auto &Header : IgnoreHeaders) { for (const auto &Header : IgnoreHeaders) {
if (!llvm::Regex{Header}.isValid()) if (!llvm::Regex{Header}.isValid())
configurationDiag("Invalid ignore headers regex '%0'") << Header; configurationDiag("Invalid ignore headers regex '%0'") << Header;
clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp
@@ -77,7 +77,7 @@ InefficientVectorOperationCheck::InefficientVectorOperationCheck(
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
VectorLikeClasses(utils::options::parseStringList( VectorLikeClasses(utils::options::parseStringList(
Options.get("VectorLikeClasses", "::std::vector"))), Options.get("VectorLikeClasses", "::std::vector"))),
- EnableProto(Options.getLocalOrGlobal("EnableProto", false)) {}+ EnableProto(Options.get("EnableProto", false)) {}
void InefficientVectorOperationCheck::storeOptions( void InefficientVectorOperationCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.h
@@ -26,7 +26,7 @@ public:
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)), IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)),
- Strict(Options.getLocalOrGlobal("Strict", false)) {}+ Strict(Options.get("Strict", false)) {}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override;
clang-tools-extra/clang-tidy/readability/RedundantAccessSpecifiersCheck.h
@@ -21,8 +21,7 @@ class RedundantAccessSpecifiersCheck : public ClangTidyCheck {
public: public:
RedundantAccessSpecifiersCheck(StringRef Name, ClangTidyContext *Context) RedundantAccessSpecifiersCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
- CheckFirstDeclaration(+ CheckFirstDeclaration(Options.get("CheckFirstDeclaration", false)) {}
- Options.getLocalOrGlobal("CheckFirstDeclaration", false)) {}
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus; return LangOpts.CPlusPlus;
} }
clang-tools-extra/clang-tidy/readability/RedundantCastingCheck.cpp
@@ -94,7 +94,7 @@ RedundantCastingCheck::RedundantCastingCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)), IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)),
- IgnoreTypeAliases(Options.getLocalOrGlobal("IgnoreTypeAliases", false)) {}+ IgnoreTypeAliases(Options.get("IgnoreTypeAliases", false)) {}
void RedundantCastingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void RedundantCastingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IgnoreMacros", IgnoreMacros); Options.store(Opts, "IgnoreMacros", IgnoreMacros);
clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
@@ -397,7 +397,7 @@ RenamerClangTidyCheck::RenamerClangTidyCheck(StringRef CheckName,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(CheckName, Context), : ClangTidyCheck(CheckName, Context),
AggressiveDependentMemberLookup( AggressiveDependentMemberLookup(
- Options.getLocalOrGlobal("AggressiveDependentMemberLookup", false)) {}+ Options.get("AggressiveDependentMemberLookup", false)) {}
RenamerClangTidyCheck::~RenamerClangTidyCheck() = default; RenamerClangTidyCheck::~RenamerClangTidyCheck() = default;
void RenamerClangTidyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void RenamerClangTidyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -550,9 +550,14 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
// Avoid indexing internal symbols in protobuf generated headers. // Avoid indexing internal symbols in protobuf generated headers.
if (isPrivateProtoDecl(ND)) if (isPrivateProtoDecl(ND))
return false; return false;
+
+ // System headers that end with `intrin.h` likely contain useful symbols.
if (!Opts.CollectReserved && if (!Opts.CollectReserved &&
(hasReservedName(ND) || hasReservedScope(*ND.getDeclContext())) && (hasReservedName(ND) || hasReservedScope(*ND.getDeclContext())) &&
- ASTCtx.getSourceManager().isInSystemHeader(ND.getLocation()))+ ASTCtx.getSourceManager().isInSystemHeader(ND.getLocation()) &&
+ !ASTCtx.getSourceManager()
+ .getFilename(ND.getLocation())
+ .ends_with("intrin.h"))
return false; return false;
return true; return true;
clang-tools-extra/clangd/unittests/DumpASTTests.cpp
@@ -49,7 +49,7 @@ declaration: Function - root
)"}, )"},
{R"cpp( {R"cpp(
namespace root { namespace root {
-struct S { static const int x = 0; };+struct S { static const int x = 0; ~S(); };
int y = S::x + root::S().x; int y = S::x + root::S().x;
} }
)cpp", )cpp",
@@ -60,10 +60,12 @@ declaration: Namespace - root
type: Qualified - const type: Qualified - const
type: Builtin - int type: Builtin - int
expression: IntegerLiteral - 0 expression: IntegerLiteral - 0
+ declaration: CXXDestructor
+ type: Record - S
+ type: FunctionProto
+ type: Builtin - void
declaration: CXXConstructor declaration: CXXConstructor
declaration: CXXConstructor declaration: CXXConstructor
- declaration: CXXConstructor
- declaration: CXXDestructor
declaration: Var - y declaration: Var - y
type: Builtin - int type: Builtin - int
expression: ExprWithCleanups expression: ExprWithCleanups
@@ -74,7 +76,7 @@ declaration: Namespace - root
type: Record - S type: Record - S
expression: ImplicitCast - LValueToRValue expression: ImplicitCast - LValueToRValue
expression: Member - x expression: Member - x
- expression: MaterializeTemporary - rvalue+ expression: CXXBindTemporary
expression: CXXTemporaryObject - S expression: CXXTemporaryObject - S
type: Elaborated type: Elaborated
specifier: Namespace - root:: specifier: Namespace - root::
@@ -82,6 +84,37 @@ declaration: Namespace - root
)"}, )"},
{R"cpp( {R"cpp(
namespace root { namespace root {
+struct S { static const int x = 0; };
+int y = S::x + root::S().x;
+}
+ )cpp",
+ R"(
+declaration: Namespace - root
+ declaration: CXXRecord - S
+ declaration: Var - x
+ type: Qualified - const
+ type: Builtin - int
+ expression: IntegerLiteral - 0
+ declaration: CXXConstructor
+ declaration: CXXConstructor
+ declaration: CXXConstructor
+ declaration: CXXDestructor
+ declaration: Var - y
+ type: Builtin - int
+ expression: BinaryOperator - +
+ expression: ImplicitCast - LValueToRValue
+ expression: DeclRef - x
+ specifier: TypeSpec
+ type: Record - S
+ expression: ImplicitCast - LValueToRValue
+ expression: Member - x
+ expression: CXXTemporaryObject - S
+ type: Elaborated
+ specifier: Namespace - root::
+ type: Record - S
+ )"},
+ {R"cpp(
+namespace root {
template <typename T> int tmpl() { template <typename T> int tmpl() {
(void)tmpl<unsigned>(); (void)tmpl<unsigned>();
return T::value; return T::value;
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -2111,6 +2111,20 @@ TEST_F(SymbolCollectorTest, Reserved) {
EXPECT_THAT(Symbols, IsEmpty()); EXPECT_THAT(Symbols, IsEmpty());
} }
+TEST_F(SymbolCollectorTest, ReservedSymbolInIntrinsicHeader) {
+ const char *Header = R"cpp(
+ #pragma once
+ void __foo();
+ )cpp";
+
+ TestHeaderName = "xintrin.h";
+ TestHeaderURI = URI::create(testPath(TestHeaderName)).toString();
+ InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem;
+ CollectorOpts.FallbackDir = testRoot();
+ runSymbolCollector("#pragma GCC system_header\n" + std::string(Header), "");
+ EXPECT_THAT(Symbols, UnorderedElementsAre(qName("__foo")));
+}
+
TEST_F(SymbolCollectorTest, Concepts) { TEST_F(SymbolCollectorTest, Concepts) {
const char *Header = R"cpp( const char *Header = R"cpp(
template <class T> template <class T>
clang-tools-extra/docs/ReleaseNotes.rst
@@ -115,6 +115,24 @@ Improvements to clang-tidy
- Improved :program:`run-clang-tidy.py` script. Fixed minor shutdown noise - Improved :program:`run-clang-tidy.py` script. Fixed minor shutdown noise
happening on certain platforms when interrupting the script. happening on certain platforms when interrupting the script.
+- Removed :program:`clang-tidy`'s global options for most of checks. All options
+ are changed to local options except `IncludeStyle`, `StrictMode` and
+ `IgnoreMacros`.
+
+.. csv-table::
+ :header: "Check", "Options removed from global option"
+
+ :doc:`bugprone-reserved-identifier <clang-tidy/checks/bugprone/reserved-identifier>`, AggressiveDependentMemberLookup
+ :doc:`bugprone-unchecked-optional-access <clang-tidy/checks/bugprone/unchecked-optional-access>`, IgnoreSmartPointerDereference
+ :doc:`cppcoreguidelines-pro-type-member-init <clang-tidy/checks/cppcoreguidelines/pro-type-member-init>`, UseAssignment
+ :doc:`cppcoreguidelines-rvalue-reference-param-not-moved <clang-tidy/checks/cppcoreguidelines/rvalue-reference-param-not-moved>`, AllowPartialMove; IgnoreUnnamedParams; IgnoreNonDeducedTemplateTypes
+ :doc:`misc-include-cleaner <clang-tidy/checks/misc/include-cleaner>`, IgnoreHeaders; DeduplicateFindings
+ :doc:`performance-inefficient-vector-operation <clang-tidy/checks/performance/inefficient-vector-operation>`, EnableProto
+ :doc:`readability-identifier-naming <clang-tidy/checks/readability/identifier-naming>`, AggressiveDependentMemberLookup
+ :doc:`readability-inconsistent-declaration-parameter-name <clang-tidy/checks/readability/inconsistent-declaration-parameter-name>`, Strict
+ :doc:`readability-redundant-access-specifiers <clang-tidy/checks/readability/redundant-access-specifiers>`, CheckFirstDeclaration
+ :doc:`readability-redundant-casting <clang-tidy/checks/readability/redundant-casting>`, IgnoreTypeAliases
+
New checks New checks
^^^^^^^^^^ ^^^^^^^^^^
clang-tools-extra/test/clang-doc/builtin_types.cpp
@@ -0,0 +1,136 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/yaml %t/md
+
+// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/yaml
+// RUN: FileCheck %s < %t/yaml/index.yaml --check-prefix=YAML
+
+// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/md --format=md
+// RUN: FileCheck %s < %t/md/GlobalNamespace/index.md --check-prefix=MD
+
+// YAML: ---
+// YAML-NEXT: USR: '0000000000000000000000000000000000000000'
+// YAML-NEXT: ChildFunctions:
+
+// MD: # Global Namespace
+// MD: ## Functions
+
+extern bool b();
+
+// YAML-NEXT: - USR: '88A104C263241E354ECF5B55B04AE8CEAD625B71'
+// YAML-NEXT: Name: 'b'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'bool'
+// YAML-NEXT: QualName: 'bool'
+
+// MD: ### b
+// MD: *bool b()*
+
+char c();
+
+// YAML-NEXT: - USR: 'EA3287837B3F175C8DB154406B4DAD2924F479B5'
+// YAML-NEXT: Name: 'c'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'char'
+// YAML-NEXT: QualName: 'char'
+
+// MD: ### c
+// MD: *char c()*
+
+double d();
+
+// YAML-NEXT: - USR: '60A47E4696CEFC411AB2E1EEFA2DD914E2A7E450'
+// YAML-NEXT: Name: 'd'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'double'
+// YAML-NEXT: QualName: 'double'
+
+// MD: ### d
+// MD: *double d()*
+
+float f();
+
+// YAML-NEXT: - USR: 'B3A9EC6BECD5869CF3ACDFB25153CFE6BBDD5EAB'
+// YAML-NEXT: Name: 'f'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'float'
+// YAML-NEXT: QualName: 'float'
+
+// MD: ### f
+// MD: *float f()*
+
+int i();
+
+// YAML-NEXT: - USR: '307041280A81EB46F949A94AD52587C659FD801C'
+// YAML-NEXT: Name: 'i'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'int'
+// YAML-NEXT: QualName: 'int'
+
+// MD: ### i
+// MD: *int i()*
+
+long l();
+
+// YAML-NEXT: - USR: 'A1CE9AB0064C412F857592E01332C641C1A06F37'
+// YAML-NEXT: Name: 'l'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'long'
+// YAML-NEXT: QualName: 'long'
+
+// MD: ### l
+// MD: *long l()*
+
+long long ll();
+
+// YAML-NEXT: - USR: '5C2C44ED4825C066EF6ED796863586F343C8BCA9'
+// YAML-NEXT: Name: 'll'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'long long'
+// YAML-NEXT: QualName: 'long long'
+
+// MD: ### ll
+// MD: *long long ll()*
+
+short s();
+
+// YAML-NEXT: - USR: '412341570FD3AD2C3A1E9A1DE7B3C01C07BEACFE'
+// YAML-NEXT: Name: 's'
+// YAML-NEXT: Location:
+// YAML-NEXT: - LineNumber: [[# @LINE-5]]
+// YAML-NEXT: Filename: '{{.*}}'
+// YAML-NEXT: ReturnType:
+// YAML-NEXT: Type:
+// YAML-NEXT: Name: 'short'
+// YAML-NEXT: QualName: 'short'
+// YAML-NEXT: ...
+
+// MD: ### s
+// MD: *short s()*
clang-tools-extra/test/clang-doc/templates.cpp
@@ -80,8 +80,8 @@ void function<bool, 0>(bool x) {}
// YAML-NEXT: Filename: '{{.*}}' // YAML-NEXT: Filename: '{{.*}}'
// YAML-NEXT: Params: // YAML-NEXT: Params:
// YAML-NEXT: - Type: // YAML-NEXT: - Type:
-// YAML-NEXT: Name: '_Bool'+// YAML-NEXT: Name: 'bool'
-// YAML-NEXT: QualName: '_Bool'+// YAML-NEXT: QualName: 'bool'
// YAML-NEXT: Name: 'x' // YAML-NEXT: Name: 'x'
// YAML-NEXT: ReturnType: // YAML-NEXT: ReturnType:
// YAML-NEXT: Type: // YAML-NEXT: Type:
@@ -95,7 +95,7 @@ void function<bool, 0>(bool x) {}
// YAML-NEXT: - Contents: '0' // YAML-NEXT: - Contents: '0'
// MD: ### function // MD: ### function
-// MD: *void function(_Bool x)*+// MD: *void function(bool x)*
// MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 26]]* // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 26]]*
/// A Tuple type /// A Tuple type
@@ -136,7 +136,7 @@ tuple<int,int,bool> func_with_tuple_param(tuple<int,int,bool> t){ return t;}
// YAML-NEXT: - Type: // YAML-NEXT: - Type:
// YAML-NEXT: Type: Record // YAML-NEXT: Type: Record
// YAML-NEXT: Name: 'tuple' // YAML-NEXT: Name: 'tuple'
-// YAML-NEXT: QualName: 'tuple<int, int, _Bool>'+// YAML-NEXT: QualName: 'tuple<int, int, bool>'
// YAML-NEXT: USR: '{{([0-9A-F]{40})}}' // YAML-NEXT: USR: '{{([0-9A-F]{40})}}'
// YAML-NEXT: Path: 'GlobalNamespace' // YAML-NEXT: Path: 'GlobalNamespace'
// YAML-NEXT: Name: 't' // YAML-NEXT: Name: 't'
@@ -144,13 +144,13 @@ tuple<int,int,bool> func_with_tuple_param(tuple<int,int,bool> t){ return t;}
// YAML-NEXT: Type: // YAML-NEXT: Type:
// YAML-NEXT: Type: Record // YAML-NEXT: Type: Record
// YAML-NEXT: Name: 'tuple' // YAML-NEXT: Name: 'tuple'
-// YAML-NEXT: QualName: 'tuple<int, int, _Bool>'+// YAML-NEXT: QualName: 'tuple<int, int, bool>'
// YAML-NEXT: USR: '{{([0-9A-F]{40})}}' // YAML-NEXT: USR: '{{([0-9A-F]{40})}}'
// YAML-NEXT: Path: 'GlobalNamespace' // YAML-NEXT: Path: 'GlobalNamespace'
// YAML-NEXT: ... // YAML-NEXT: ...
// MD: ### func_with_tuple_param // MD: ### func_with_tuple_param
-// MD: *tuple<int, int, _Bool> func_with_tuple_param(tuple<int, int, _Bool> t)*+// MD: *tuple<int, int, bool> func_with_tuple_param(tuple<int, int, bool> t)*
// MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 44]]* // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 44]]*
// MD: A function with a tuple parameter // MD: A function with a tuple parameter
// MD: **t** The input to func_with_tuple_param // MD: **t** The input to func_with_tuple_param
clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-strict.cpp
@@ -1,5 +1,5 @@
// RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \ // RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: true}}" --+// RUN: -config="{CheckOptions: {bugprone-argument-comment.StrictMode: true}}" --
void f(int _with_underscores_); void f(int _with_underscores_);
void g(int x_); void g(int x_);
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-const-cast.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy -check-suffix=STRICT %s cppcoreguidelines-pro-type-const-cast %t -- -config="{CheckOptions: {StrictMode: true}}"+// RUN: %check_clang_tidy -check-suffix=STRICT %s cppcoreguidelines-pro-type-const-cast %t -- -config="{CheckOptions: {cppcoreguidelines-pro-type-const-cast.StrictMode: true}}"
// RUN: %check_clang_tidy -check-suffix=NSTRICT %s cppcoreguidelines-pro-type-const-cast %t // RUN: %check_clang_tidy -check-suffix=NSTRICT %s cppcoreguidelines-pro-type-const-cast %t
namespace Const { namespace Const {
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-static-cast-downcast.cpp
@@ -1,5 +1,5 @@
// RUN: %check_clang_tidy -check-suffixes=NSTRICT,STRICT %s cppcoreguidelines-pro-type-static-cast-downcast %t // RUN: %check_clang_tidy -check-suffixes=NSTRICT,STRICT %s cppcoreguidelines-pro-type-static-cast-downcast %t
-// RUN: %check_clang_tidy -check-suffix=NSTRICT %s cppcoreguidelines-pro-type-static-cast-downcast %t -- -config="{CheckOptions: {StrictMode: false}}"+// RUN: %check_clang_tidy -check-suffix=NSTRICT %s cppcoreguidelines-pro-type-static-cast-downcast %t -- -config="{CheckOptions: {cppcoreguidelines-pro-type-static-cast-downcast.StrictMode: false}}"
class Base { class Base {
}; };
clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters-strict.cpp
@@ -1,5 +1,5 @@
// RUN: %check_clang_tidy %s misc-unused-parameters %t -- \ // RUN: %check_clang_tidy %s misc-unused-parameters %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: true}}" --+// RUN: -config="{CheckOptions: {misc-unused-parameters.StrictMode: true}}" --
// Warn on empty function bodies in StrictMode. // Warn on empty function bodies in StrictMode.
namespace strict_mode { namespace strict_mode {
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp
@@ -1,12 +1,12 @@
// RUN: %check_clang_tidy \ // RUN: %check_clang_tidy \
// RUN: -std=c++20 %s modernize-use-std-format %t -- \ // RUN: -std=c++20 %s modernize-use-std-format %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: true}}" \+// RUN: -config="{CheckOptions: {modernize-use-std-format.StrictMode: true}}" \
// RUN: -- -isystem %clang_tidy_headers \ // RUN: -- -isystem %clang_tidy_headers \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \ // RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\"" // RUN: -D__PRI_CMDLINE_MACRO="\"s\""
// RUN: %check_clang_tidy \ // RUN: %check_clang_tidy \
// RUN: -std=c++20 %s modernize-use-std-format %t -- \ // RUN: -std=c++20 %s modernize-use-std-format %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: false}}" \+// RUN: -config="{CheckOptions: {modernize-use-std-format.StrictMode: false}}" \
// RUN: -- -isystem %clang_tidy_headers \ // RUN: -- -isystem %clang_tidy_headers \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \ // RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\"" // RUN: -D__PRI_CMDLINE_MACRO="\"s\""
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
@@ -1,10 +1,10 @@
// RUN: %check_clang_tidy \ // RUN: %check_clang_tidy \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \ // RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: true}}" \+// RUN: -config="{CheckOptions: {modernize-use-std-print.StrictMode: true}}" \
// RUN: -- -isystem %clang_tidy_headers // RUN: -- -isystem %clang_tidy_headers
// RUN: %check_clang_tidy \ // RUN: %check_clang_tidy \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \ // RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: false}}" \+// RUN: -config="{CheckOptions: {modernize-use-std-print.StrictMode: false}}" \
// RUN: -- -isystem %clang_tidy_headers // RUN: -- -isystem %clang_tidy_headers
#include <cstdio> #include <cstdio>
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
@@ -1,12 +1,12 @@
// RUN: %check_clang_tidy -check-suffixes=,STRICT \ // RUN: %check_clang_tidy -check-suffixes=,STRICT \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \ // RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: true}}" \+// RUN: -config="{CheckOptions: {modernize-use-std-print.StrictMode: true}}" \
// RUN: -- -isystem %clang_tidy_headers -fexceptions \ // RUN: -- -isystem %clang_tidy_headers -fexceptions \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \ // RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\"" // RUN: -D__PRI_CMDLINE_MACRO="\"s\""
// RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \ // RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \ // RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: {StrictMode: false}}" \+// RUN: -config="{CheckOptions: {modernize-use-std-print.StrictMode: false}}" \
// RUN: -- -isystem %clang_tidy_headers -fexceptions \ // RUN: -- -isystem %clang_tidy_headers -fexceptions \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \ // RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\"" // RUN: -D__PRI_CMDLINE_MACRO="\"s\""
clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -631,8 +631,8 @@ TEST(SerializeTests, emitTypedefs) {
TEST(SerializeTests, emitFunctionTemplate) { TEST(SerializeTests, emitFunctionTemplate) {
EmittedInfoList Infos; EmittedInfoList Infos;
// A template and a specialization. // A template and a specialization.
- ExtractInfosFromCode("template<typename T = int> void GetFoo(T);\n"+ ExtractInfosFromCode("template<typename T = int> bool GetFoo(T);\n"
- "template<> void GetFoo<bool>(bool);",+ "template<> bool GetFoo<bool>(bool);",
2, 2,
/*Public=*/false, Infos); /*Public=*/false, Infos);
@@ -666,6 +666,8 @@ TEST(SerializeTests, emitFunctionTemplate) {
ASSERT_EQ(1u, Func2.Template->Specialization->Params.size()); ASSERT_EQ(1u, Func2.Template->Specialization->Params.size());
EXPECT_EQ("bool", Func2.Template->Specialization->Params[0].Contents); EXPECT_EQ("bool", Func2.Template->Specialization->Params[0].Contents);
EXPECT_EQ(Func1.USR, Func2.Template->Specialization->SpecializationOf); EXPECT_EQ(Func1.USR, Func2.Template->Specialization->SpecializationOf);
+
+ EXPECT_EQ("bool", Func2.ReturnType.Type.Name);
} }
TEST(SerializeTests, emitClassTemplate) { TEST(SerializeTests, emitClassTemplate) {
clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp
@@ -71,10 +71,12 @@ TEST(IncludeCleanerCheckTest, SuppressUnusedIncludes) {
std::vector<ClangTidyError> Errors; std::vector<ClangTidyError> Errors;
ClangTidyOptions Opts; ClangTidyOptions Opts;
- Opts.CheckOptions["IgnoreHeaders"] = llvm::StringRef{llvm::formatv(+ Opts.CheckOptions["test-check-0.IgnoreHeaders"] = llvm::StringRef{
- "bar.h;{0};{1};vector;<list>;",+ llvm::formatv("bar.h;{0};{1};vector;<list>;",
- llvm::Regex::escape(appendPathFileSystemIndependent({"foo", "qux.h"})),+ llvm::Regex::escape(
- llvm::Regex::escape(appendPathFileSystemIndependent({"baz", "qux"})))};+ appendPathFileSystemIndependent({"foo", "qux.h"})),
+ llvm::Regex::escape(
+ appendPathFileSystemIndependent({"baz", "qux"})))};
EXPECT_EQ( EXPECT_EQ(
PostCode, PostCode,
runCheckOnCode<IncludeCleanerCheck>( runCheckOnCode<IncludeCleanerCheck>(
@@ -139,7 +141,7 @@ int BarResult2 = $diag2^bar();)");
{ {
std::vector<ClangTidyError> Errors; std::vector<ClangTidyError> Errors;
ClangTidyOptions Opts; ClangTidyOptions Opts;
- Opts.CheckOptions.insert({"DeduplicateFindings", "false"});+ Opts.CheckOptions["test-check-0.DeduplicateFindings"] = "false";
runCheckOnCode<IncludeCleanerCheck>(Code.code(), &Errors, "file.cpp", {}, runCheckOnCode<IncludeCleanerCheck>(Code.code(), &Errors, "file.cpp", {},
Opts, Opts,
{{"baz.h", R"(#pragma once {{"baz.h", R"(#pragma once
@@ -170,7 +172,7 @@ std::vector x;
)"; )";
ClangTidyOptions Opts; ClangTidyOptions Opts;
- Opts.CheckOptions["IgnoreHeaders"] = llvm::StringRef{+ Opts.CheckOptions["test-check-0.IgnoreHeaders"] = llvm::StringRef{
"public.h;<vector>;baz.h;" + "public.h;<vector>;baz.h;" +
llvm::Regex::escape(appendPathFileSystemIndependent({"foo", "qux.h"}))}; llvm::Regex::escape(appendPathFileSystemIndependent({"foo", "qux.h"}))};
std::vector<ClangTidyError> Errors; std::vector<ClangTidyError> Errors;
clang/CMakeLists.txt
@@ -362,7 +362,6 @@ if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*")
message(STATUS "Host linker version: ${HOST_LINK_VERSION}") message(STATUS "Host linker version: ${HOST_LINK_VERSION}")
endif() endif()
-include(CMakeParseArguments)
include(AddClang) include(AddClang)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
clang/cmake/caches/Fuchsia-stage2.cmake
@@ -333,7 +333,7 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi;armv8.1m.
foreach(lang C;CXX;ASM) foreach(lang C;CXX;ASM)
# TODO: The preprocessor defines workaround various issues in libc and libc++ integration. # TODO: The preprocessor defines workaround various issues in libc and libc++ integration.
# These should be addressed and removed over time. # These should be addressed and removed over time.
- set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1")+ set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" -D_LIBCPP_PRINT=1")
if(NOT ${target} STREQUAL "aarch64-none-elf") if(NOT ${target} STREQUAL "aarch64-none-elf")
set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mthumb") set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mthumb")
endif() endif()
@@ -394,7 +394,7 @@ foreach(target riscv32-unknown-elf)
foreach(lang C;CXX;ASM) foreach(lang C;CXX;ASM)
# TODO: The preprocessor defines workaround various issues in libc and libc++ integration. # TODO: The preprocessor defines workaround various issues in libc and libc++ integration.
# These should be addressed and removed over time. # These should be addressed and removed over time.
- set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1" CACHE STRING "")+ set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" -D_LIBCPP_PRINT=1" CACHE STRING "")
endforeach() endforeach()
foreach(type SHARED;MODULE;EXE) foreach(type SHARED;MODULE;EXE)
set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "") set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
clang/docs/MatrixTypes.rst
@@ -33,9 +33,10 @@ program is ill-formed.
Currently, the element type of a matrix is only permitted to be one of the Currently, the element type of a matrix is only permitted to be one of the
following types: following types:
-* an integer type (as in C23 6.2.5p22), but excluding enumerated types and ``bool``+* an integer type (as in C23 6.2.5p22), but excluding enumerated types, ``bool``,
-* the standard floating types ``float`` or ``double``+ and ``_BitInt`` types whose width is not a power of 2;
-* a half-precision floating point type, if one is supported on the target+* the standard floating types ``float`` or ``double``;
+* a half-precision floating point type, if one is supported on the target.
Other types may be supported in the future. Other types may be supported in the future.
clang/docs/ReleaseNotes.rst
@@ -272,6 +272,8 @@ C++23 Feature Support
- Extend lifetime of temporaries in mem-default-init for P2718R0. Clang now fully - Extend lifetime of temporaries in mem-default-init for P2718R0. Clang now fully
supports `P2718R0 Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_. supports `P2718R0 Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_.
+
+- ``__cpp_explicit_this_parameter`` is now defined. (#GH82780)
C++20 Feature Support C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
@@ -321,6 +323,11 @@ Resolutions to C++ Defect Reports
- Fix name lookup for a dependent base class that is the current instantiation. - Fix name lookup for a dependent base class that is the current instantiation.
(`CWG591: When a dependent base class is the current instantiation <https://cplusplus.github.io/CWG/issues/591.html>`_). (`CWG591: When a dependent base class is the current instantiation <https://cplusplus.github.io/CWG/issues/591.html>`_).
+- Clang now allows calling explicit object member functions directly with prvalues
+ instead of always materializing a temporary, meaning by-value explicit object parameters
+ do not need to move from a temporary.
+ (`CWG2813: Class member access with prvalues <https://cplusplus.github.io/CWG/issues/2813.html>`_).
+
C Language Changes C Language Changes
------------------ ------------------
@@ -416,6 +423,12 @@ Non-comprehensive list of changes in this release
``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``, ``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
``__builtin_elementwise_sub_sat``. ``__builtin_elementwise_sub_sat``.
+- Clang now rejects ``_BitInt`` matrix element types if the bit width is less than ``CHAR_WIDTH`` or
+ not a power of two, matching preexisting behaviour for vector types.
+
+- Matrix types (a Clang extension) can now be used in pseudo-destructor expressions,
+ which allows them to be stored in STL containers.
+
New Compiler Flags New Compiler Flags
------------------ ------------------
@@ -677,6 +690,16 @@ Improvements to Clang's diagnostics
views.push_back(std::string("123")); // warning views.push_back(std::string("123")); // warning
} }
+- Clang now emits a ``-Wtautological-compare`` diagnostic when a check for
+ pointer addition overflow is always true or false, because overflow would
+ be undefined behavior.
+
+ .. code-block:: c++
+
+ bool incorrect_overflow_check(const char *ptr, size_t index) {
+ return ptr + index < ptr; // warning
+ }
+
Improvements to Clang's time-trace Improvements to Clang's time-trace
---------------------------------- ----------------------------------
@@ -816,6 +839,8 @@ Bug Fixes to C++ Support
missing placeholder return type. (#GH78694) missing placeholder return type. (#GH78694)
- Fixed a bug where bounds of partially expanded pack indexing expressions were checked too early. (#GH116105) - Fixed a bug where bounds of partially expanded pack indexing expressions were checked too early. (#GH116105)
- Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385) - Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385)
+- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
+ friend declarations. (#GH113324)
- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659) - Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072) - Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072)
- Fixed a null pointer dereference issue when heuristically computing ``sizeof...(pack)`` expressions. (#GH81436) - Fixed a null pointer dereference issue when heuristically computing ``sizeof...(pack)`` expressions. (#GH81436)
@@ -1170,6 +1195,10 @@ Sanitizers
<https://clang.llvm.org/docs/SanitizerSpecialCaseList.html>`_. See that link <https://clang.llvm.org/docs/SanitizerSpecialCaseList.html>`_. See that link
for examples. for examples.
+- Introduced an experimental Type Sanitizer, activated by using the
+ ``-fsanitize=type`` flag. This sanitizer detects violations of C/C++ type-based
+ aliasing rules.
+
Python Binding Changes Python Binding Changes
---------------------- ----------------------
- Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``. - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.
clang/include/clang/AST/OpenACCClause.h
@@ -191,8 +191,9 @@ using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
/// an identifier. The 'asterisk' means 'the rest'. /// an identifier. The 'asterisk' means 'the rest'.
class OpenACCDeviceTypeClause final class OpenACCDeviceTypeClause final
: public OpenACCClauseWithParams, : public OpenACCClauseWithParams,
- public llvm::TrailingObjects<OpenACCDeviceTypeClause,+ private llvm::TrailingObjects<OpenACCDeviceTypeClause,
DeviceTypeArgument> { DeviceTypeArgument> {
+ friend TrailingObjects;
// Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
// nullptr IdentifierInfo* represents an asterisk. // nullptr IdentifierInfo* represents an asterisk.
unsigned NumArchs; unsigned NumArchs;
@@ -377,7 +378,8 @@ public:
// Represents the 'devnum' and expressions lists for the 'wait' clause. // Represents the 'devnum' and expressions lists for the 'wait' clause.
class OpenACCWaitClause final class OpenACCWaitClause final
: public OpenACCClauseWithExprs, : public OpenACCClauseWithExprs,
- public llvm::TrailingObjects<OpenACCWaitClause, Expr *> {+ private llvm::TrailingObjects<OpenACCWaitClause, Expr *> {
+ friend TrailingObjects;
SourceLocation QueuesLoc; SourceLocation QueuesLoc;
OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *DevNumExpr, SourceLocation QueuesLoc, Expr *DevNumExpr, SourceLocation QueuesLoc,
@@ -419,7 +421,8 @@ public:
class OpenACCNumGangsClause final class OpenACCNumGangsClause final
: public OpenACCClauseWithExprs, : public OpenACCClauseWithExprs,
- public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {+ private llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
+ friend TrailingObjects;
OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
@@ -449,7 +452,8 @@ public:
class OpenACCTileClause final class OpenACCTileClause final
: public OpenACCClauseWithExprs, : public OpenACCClauseWithExprs,
- public llvm::TrailingObjects<OpenACCTileClause, Expr *> {+ private llvm::TrailingObjects<OpenACCTileClause, Expr *> {
+ friend TrailingObjects;
OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc) ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc)
: OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc, : OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc,
@@ -503,7 +507,8 @@ public:
class OpenACCGangClause final class OpenACCGangClause final
: public OpenACCClauseWithExprs, : public OpenACCClauseWithExprs,
- public llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> {+ private llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> {
+ friend TrailingObjects;
protected: protected:
OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<OpenACCGangKind> GangKinds, ArrayRef<OpenACCGangKind> GangKinds,
@@ -658,7 +663,8 @@ public:
class OpenACCPrivateClause final class OpenACCPrivateClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {+ private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
+ friend TrailingObjects;
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -680,7 +686,8 @@ public:
class OpenACCFirstPrivateClause final class OpenACCFirstPrivateClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {+ private llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {
+ friend TrailingObjects;
OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -702,7 +709,8 @@ public:
class OpenACCDevicePtrClause final class OpenACCDevicePtrClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {+ private llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {
+ friend TrailingObjects;
OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -724,7 +732,8 @@ public:
class OpenACCAttachClause final class OpenACCAttachClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCAttachClause, Expr *> {+ private llvm::TrailingObjects<OpenACCAttachClause, Expr *> {
+ friend TrailingObjects;
OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -746,7 +755,8 @@ public:
class OpenACCDetachClause final class OpenACCDetachClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCDetachClause, Expr *> {+ private llvm::TrailingObjects<OpenACCDetachClause, Expr *> {
+ friend TrailingObjects;
OpenACCDetachClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCDetachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -766,9 +776,56 @@ public:
ArrayRef<Expr *> VarList, SourceLocation EndLoc); ArrayRef<Expr *> VarList, SourceLocation EndLoc);
}; };
+class OpenACCDeleteClause final
+ : public OpenACCClauseWithVarList,
+ private llvm::TrailingObjects<OpenACCDeleteClause, Expr *> {
+ friend TrailingObjects;
+
+ OpenACCDeleteClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc)
+ : OpenACCClauseWithVarList(OpenACCClauseKind::Delete, BeginLoc, LParenLoc,
+ EndLoc) {
+ std::uninitialized_copy(VarList.begin(), VarList.end(),
+ getTrailingObjects<Expr *>());
+ setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
+ }
+
+public:
+ static bool classof(const OpenACCClause *C) {
+ return C->getClauseKind() == OpenACCClauseKind::Delete;
+ }
+ static OpenACCDeleteClause *
+ Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc);
+};
+
+class OpenACCUseDeviceClause final
+ : public OpenACCClauseWithVarList,
+ private llvm::TrailingObjects<OpenACCUseDeviceClause, Expr *> {
+ friend TrailingObjects;
+
+ OpenACCUseDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc)
+ : OpenACCClauseWithVarList(OpenACCClauseKind::UseDevice, BeginLoc,
+ LParenLoc, EndLoc) {
+ std::uninitialized_copy(VarList.begin(), VarList.end(),
+ getTrailingObjects<Expr *>());
+ setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
+ }
+
+public:
+ static bool classof(const OpenACCClause *C) {
+ return C->getClauseKind() == OpenACCClauseKind::UseDevice;
+ }
+ static OpenACCUseDeviceClause *
+ Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc);
+};
+
class OpenACCNoCreateClause final class OpenACCNoCreateClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {+ private llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {
+ friend TrailingObjects;
OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -790,7 +847,8 @@ public:
class OpenACCPresentClause final class OpenACCPresentClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCPresentClause, Expr *> {+ private llvm::TrailingObjects<OpenACCPresentClause, Expr *> {
+ friend TrailingObjects;
OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc) ArrayRef<Expr *> VarList, SourceLocation EndLoc)
@@ -812,7 +870,8 @@ public:
class OpenACCCopyClause final class OpenACCCopyClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCCopyClause, Expr *> {+ private llvm::TrailingObjects<OpenACCCopyClause, Expr *> {
+ friend TrailingObjects;
OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
SourceLocation LParenLoc, ArrayRef<Expr *> VarList, SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
@@ -841,7 +900,8 @@ public:
class OpenACCCopyInClause final class OpenACCCopyInClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {+ private llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {
+ friend TrailingObjects;
bool IsReadOnly; bool IsReadOnly;
OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
@@ -873,7 +933,8 @@ public:
class OpenACCCopyOutClause final class OpenACCCopyOutClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {+ private llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {
+ friend TrailingObjects;
bool IsZero; bool IsZero;
OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
@@ -905,7 +966,8 @@ public:
class OpenACCCreateClause final class OpenACCCreateClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCCreateClause, Expr *> {+ private llvm::TrailingObjects<OpenACCCreateClause, Expr *> {
+ friend TrailingObjects;
bool IsZero; bool IsZero;
OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc, OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
@@ -937,7 +999,8 @@ public:
class OpenACCReductionClause final class OpenACCReductionClause final
: public OpenACCClauseWithVarList, : public OpenACCClauseWithVarList,
- public llvm::TrailingObjects<OpenACCReductionClause, Expr *> {+ private llvm::TrailingObjects<OpenACCReductionClause, Expr *> {
+ friend TrailingObjects;
OpenACCReductionOperator Op; OpenACCReductionOperator Op;
OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
clang/include/clang/AST/StmtOpenACC.h
@@ -127,11 +127,12 @@ public:
/// the 'Kind'. /// the 'Kind'.
class OpenACCComputeConstruct final class OpenACCComputeConstruct final
: public OpenACCAssociatedStmtConstruct, : public OpenACCAssociatedStmtConstruct,
- public llvm::TrailingObjects<OpenACCComputeConstruct,+ private llvm::TrailingObjects<OpenACCComputeConstruct,
- const OpenACCClause *> {+ const OpenACCClause *> {
friend class ASTStmtWriter; friend class ASTStmtWriter;
friend class ASTStmtReader; friend class ASTStmtReader;
friend class ASTContext; friend class ASTContext;
+ friend TrailingObjects;
OpenACCComputeConstruct(unsigned NumClauses) OpenACCComputeConstruct(unsigned NumClauses)
: OpenACCAssociatedStmtConstruct( : OpenACCAssociatedStmtConstruct(
OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid, OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
@@ -189,7 +190,7 @@ public:
/// Construct. /// Construct.
class OpenACCLoopConstruct final class OpenACCLoopConstruct final
: public OpenACCAssociatedStmtConstruct, : public OpenACCAssociatedStmtConstruct,
- public llvm::TrailingObjects<OpenACCLoopConstruct,+ private llvm::TrailingObjects<OpenACCLoopConstruct,
const OpenACCClause *> { const OpenACCClause *> {
// The compute/combined construct kind this loop is associated with, or // The compute/combined construct kind this loop is associated with, or
// invalid if this is an orphaned loop construct. // invalid if this is an orphaned loop construct.
@@ -202,6 +203,7 @@ class OpenACCLoopConstruct final
friend class OpenACCAssociatedStmtConstruct; friend class OpenACCAssociatedStmtConstruct;
friend class OpenACCCombinedConstruct; friend class OpenACCCombinedConstruct;
friend class OpenACCComputeConstruct; friend class OpenACCComputeConstruct;
+ friend TrailingObjects;
OpenACCLoopConstruct(unsigned NumClauses); OpenACCLoopConstruct(unsigned NumClauses);
@@ -245,8 +247,9 @@ public:
// shared with both loop and compute constructs. // shared with both loop and compute constructs.
class OpenACCCombinedConstruct final class OpenACCCombinedConstruct final
: public OpenACCAssociatedStmtConstruct, : public OpenACCAssociatedStmtConstruct,
- public llvm::TrailingObjects<OpenACCCombinedConstruct,+ private llvm::TrailingObjects<OpenACCCombinedConstruct,
const OpenACCClause *> { const OpenACCClause *> {
+ friend TrailingObjects;
OpenACCCombinedConstruct(unsigned NumClauses) OpenACCCombinedConstruct(unsigned NumClauses)
: OpenACCAssociatedStmtConstruct( : OpenACCAssociatedStmtConstruct(
OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid, OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid,
@@ -297,8 +300,9 @@ public:
// and clauses, but is otherwise pretty simple. // and clauses, but is otherwise pretty simple.
class OpenACCDataConstruct final class OpenACCDataConstruct final
: public OpenACCAssociatedStmtConstruct, : public OpenACCAssociatedStmtConstruct,
- public llvm::TrailingObjects<OpenACCCombinedConstruct,+ private llvm::TrailingObjects<OpenACCDataConstruct,
const OpenACCClause *> { const OpenACCClause *> {
+ friend TrailingObjects;
OpenACCDataConstruct(unsigned NumClauses) OpenACCDataConstruct(unsigned NumClauses)
: OpenACCAssociatedStmtConstruct( : OpenACCAssociatedStmtConstruct(
OpenACCDataConstructClass, OpenACCDirectiveKind::Data, OpenACCDataConstructClass, OpenACCDirectiveKind::Data,
@@ -345,8 +349,9 @@ public:
// This class represents a 'enter data' construct, which JUST has clauses. // This class represents a 'enter data' construct, which JUST has clauses.
class OpenACCEnterDataConstruct final class OpenACCEnterDataConstruct final
: public OpenACCConstructStmt, : public OpenACCConstructStmt,
- public llvm::TrailingObjects<OpenACCCombinedConstruct,+ private llvm::TrailingObjects<OpenACCEnterDataConstruct,
const OpenACCClause *> { const OpenACCClause *> {
+ friend TrailingObjects;
OpenACCEnterDataConstruct(unsigned NumClauses) OpenACCEnterDataConstruct(unsigned NumClauses)
: OpenACCConstructStmt(OpenACCEnterDataConstructClass, : OpenACCConstructStmt(OpenACCEnterDataConstructClass,
OpenACCDirectiveKind::EnterData, SourceLocation{}, OpenACCDirectiveKind::EnterData, SourceLocation{},
@@ -382,8 +387,9 @@ public:
// This class represents a 'exit data' construct, which JUST has clauses. // This class represents a 'exit data' construct, which JUST has clauses.
class OpenACCExitDataConstruct final class OpenACCExitDataConstruct final
: public OpenACCConstructStmt, : public OpenACCConstructStmt,
- public llvm::TrailingObjects<OpenACCCombinedConstruct,+ private llvm::TrailingObjects<OpenACCExitDataConstruct,
const OpenACCClause *> { const OpenACCClause *> {
+ friend TrailingObjects;
OpenACCExitDataConstruct(unsigned NumClauses) OpenACCExitDataConstruct(unsigned NumClauses)
: OpenACCConstructStmt(OpenACCExitDataConstructClass, : OpenACCConstructStmt(OpenACCExitDataConstructClass,
OpenACCDirectiveKind::ExitData, SourceLocation{}, OpenACCDirectiveKind::ExitData, SourceLocation{},
@@ -420,8 +426,9 @@ public:
// statement and clauses, but is otherwise pretty simple. // statement and clauses, but is otherwise pretty simple.
class OpenACCHostDataConstruct final class OpenACCHostDataConstruct final
: public OpenACCAssociatedStmtConstruct, : public OpenACCAssociatedStmtConstruct,
- public llvm::TrailingObjects<OpenACCCombinedConstruct,+ private llvm::TrailingObjects<OpenACCHostDataConstruct,
const OpenACCClause *> { const OpenACCClause *> {
+ friend TrailingObjects;
OpenACCHostDataConstruct(unsigned NumClauses) OpenACCHostDataConstruct(unsigned NumClauses)
: OpenACCAssociatedStmtConstruct( : OpenACCAssociatedStmtConstruct(
OpenACCHostDataConstructClass, OpenACCDirectiveKind::HostData, OpenACCHostDataConstructClass, OpenACCDirectiveKind::HostData,
clang/include/clang/Basic/Builtins.td
@@ -4762,6 +4762,12 @@ def HLSLAsDouble : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)"; let Prototype = "void(...)";
} }
+def HLSLWaveActiveAllTrue : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_wave_active_all_true"];
+ let Attributes = [NoThrow, Const];
+ let Prototype = "bool(bool)";
+}
+
def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> { def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_wave_active_any_true"]; let Spellings = ["__builtin_hlsl_wave_active_any_true"];
let Attributes = [NoThrow, Const]; let Attributes = [NoThrow, Const];
clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3233,8 +3233,8 @@ def err_attribute_too_few_arguments : Error<
"%0 attribute takes at least %1 argument%s1">; "%0 attribute takes at least %1 argument%s1">;
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
def err_attribute_invalid_bitint_vector_type : Error< def err_attribute_invalid_bitint_vector_type : Error<
- "'_BitInt' vector element width must be %select{a power of 2|"+ "'_BitInt' %select{vector|matrix}0 element width must be %select{a power of 2|"
- "at least as wide as 'CHAR_BIT'}0">;+ "at least as wide as 'CHAR_BIT'}1">;
def err_attribute_invalid_matrix_type : Error<"invalid matrix element type %0">; def err_attribute_invalid_matrix_type : Error<"invalid matrix element type %0">;
def err_attribute_bad_neon_vector_size : Error< def err_attribute_bad_neon_vector_size : Error<
"Neon vector size must be 64 or 128 bits">; "Neon vector size must be 64 or 128 bits">;
@@ -10246,7 +10246,7 @@ def warn_dangling_reference_captured_by_unknown : Warning<
// should result in a warning, since these always evaluate to a constant. // should result in a warning, since these always evaluate to a constant.
// Array comparisons have similar warnings // Array comparisons have similar warnings
def warn_comparison_always : Warning< def warn_comparison_always : Warning<
- "%select{self-|array }0comparison always evaluates to "+ "%select{self-|array |pointer }0comparison always evaluates to "
"%select{a constant|true|false|'std::strong_ordering::equal'}1">, "%select{a constant|true|false|'std::strong_ordering::equal'}1">,
InGroup<TautologicalCompare>; InGroup<TautologicalCompare>;
def warn_comparison_bitwise_always : Warning< def warn_comparison_bitwise_always : Warning<
@@ -12682,6 +12682,9 @@ def err_acc_not_a_var_ref
: Error<"OpenACC variable is not a valid variable name, sub-array, array " : Error<"OpenACC variable is not a valid variable name, sub-array, array "
"element,%select{| member of a composite variable,}0 or composite " "element,%select{| member of a composite variable,}0 or composite "
"variable member">; "variable member">;
+def err_acc_not_a_var_ref_use_device
+ : Error<"OpenACC variable in 'use_device' clause is not a valid variable "
+ "name or array name">;
def err_acc_typecheck_subarray_value def err_acc_typecheck_subarray_value
: Error<"OpenACC sub-array subscripted value is not an array or pointer">; : Error<"OpenACC sub-array subscripted value is not an array or pointer">;
def err_acc_subarray_function_type def err_acc_subarray_function_type
@@ -12801,6 +12804,8 @@ def err_acc_loop_terminating_condition
def err_acc_loop_not_monotonic def err_acc_loop_not_monotonic
: Error<"OpenACC '%0' variable must monotonically increase or decrease " : Error<"OpenACC '%0' variable must monotonically increase or decrease "
"('++', '--', or compound assignment)">; "('++', '--', or compound assignment)">;
+def err_acc_construct_one_clause_of
+ : Error<"OpenACC '%0' construct must have at least one %1 clause">;
// 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/Features.def
@@ -102,6 +102,7 @@ FEATURE(numerical_stability_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Nume
FEATURE(memory_sanitizer, FEATURE(memory_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory | LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
SanitizerKind::KernelMemory)) SanitizerKind::KernelMemory))
+FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
clang/include/clang/Basic/OpenACCClauses.def
@@ -38,6 +38,7 @@ VISIT_CLAUSE(Create)
CLAUSE_ALIAS(PCreate, Create, true) CLAUSE_ALIAS(PCreate, Create, true)
CLAUSE_ALIAS(PresentOrCreate, Create, true) CLAUSE_ALIAS(PresentOrCreate, Create, true)
VISIT_CLAUSE(Default) VISIT_CLAUSE(Default)
+VISIT_CLAUSE(Delete)
VISIT_CLAUSE(Detach) VISIT_CLAUSE(Detach)
VISIT_CLAUSE(DevicePtr) VISIT_CLAUSE(DevicePtr)
VISIT_CLAUSE(DeviceType) VISIT_CLAUSE(DeviceType)
@@ -57,6 +58,7 @@ VISIT_CLAUSE(Reduction)
VISIT_CLAUSE(Self) VISIT_CLAUSE(Self)
VISIT_CLAUSE(Seq) VISIT_CLAUSE(Seq)
VISIT_CLAUSE(Tile) VISIT_CLAUSE(Tile)
+VISIT_CLAUSE(UseDevice)
VISIT_CLAUSE(Vector) VISIT_CLAUSE(Vector)
VISIT_CLAUSE(VectorLength) VISIT_CLAUSE(VectorLength)
VISIT_CLAUSE(Wait) VISIT_CLAUSE(Wait)
clang/include/clang/Basic/Sanitizers.def
@@ -73,6 +73,9 @@ SANITIZER("fuzzer", Fuzzer)
// libFuzzer-required instrumentation, no linking. // libFuzzer-required instrumentation, no linking.
SANITIZER("fuzzer-no-link", FuzzerNoLink) SANITIZER("fuzzer-no-link", FuzzerNoLink)
+// TypeSanitizer
+SANITIZER("type", Type)
+
// ThreadSanitizer // ThreadSanitizer
SANITIZER("thread", Thread) SANITIZER("thread", Thread)
clang/include/clang/Basic/arm_sme.td
@@ -748,11 +748,28 @@ let SMETargetGuard = "sme2" in {
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_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, 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_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, 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 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 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_VG1x4 : Inst<"svdot[_single]_za32[_mf8]_vg1x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, 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_VG1x4 : Inst<"svdot_za32[_mf8]_vg1x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za32_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, 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_fpm", "vm2di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x2", [IsStreaming, IsInOutZA, SetsFPMR, 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_fpm", "vm4di>", "m", MergeNone, "aarch64_sme_fp8_fdot_lane_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, 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 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_VG1x4 : Inst<"svdot[_single]_za16[_mf8]_vg1x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fdot_single_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, 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_VG1x4 : Inst<"svdot_za16[_mf8]_vg1x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fdot_multi_za16_vg1x4", [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -842,11 +859,49 @@ 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_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za32",
[IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>; [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>;
+ // 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
+ // 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ def SVMLA_FP8_SINGLE_ZA32_VG4x2 : Inst<"svmla[_single]_za32[_mf8]_vg4x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x2",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ def SVMLA_FP8_SINGLE_ZA32_VG4x4 : Inst<"svmla[_single]_za32[_mf8]_vg4x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlall_single_za32_vg4x4",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ // FMLALL (multiple)
+ def SVMLA_FP8_MULTI_ZA32_VG4x2 : Inst<"svmla_za32[_mf8]_vg4x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x2",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ def SVMLA_FP8_MULTI_ZA32_VG4x4 : Inst<"svmla_za32[_mf8]_vg4x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlall_multi_za32_vg4x4",
+ [IsStreaming, IsInOutZA, SetsFPMR, 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_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_fmopa_za16",
[IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>; [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>;
+ // 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>;
+ // 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",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ def SVMLA_FP8_SINGLE_ZA16_VG2x2 : Inst<"svmla[_single]_za16[_mf8]_vg2x2_fpm", "vm2d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x2",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ def SVMLA_FP8_SINGLE_ZA16_VG2x4 : Inst<"svmla[_single]_za16[_mf8]_vg2x4_fpm", "vm4d>", "m", MergeNone, "aarch64_sme_fp8_fmlal_single_za16_vg2x4",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ // FMLAL (multiple)
+ def SVMLA_FP8_MULTI_ZA16_VG2x2 : Inst<"svmla_za16[_mf8]_vg2x2_fpm", "vm22>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x2",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
+ def SVMLA_FP8_MULTI_ZA16_VG2x4 : Inst<"svmla_za16[_mf8]_vg2x4_fpm", "vm44>", "m", MergeNone, "aarch64_sme_fp8_fmlal_multi_za16_vg2x4",
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>;
} }
} // let SVETargetGuard = InvalidMode } // let SVETargetGuard = InvalidMode
clang/include/clang/Driver/Options.td
@@ -1056,11 +1056,11 @@ def z : Separate<["-"], "z">, Flags<[LinkerInput]>,
def offload_link : Flag<["--"], "offload-link">, Group<Link_Group>, def offload_link : Flag<["--"], "offload-link">, Group<Link_Group>,
HelpText<"Use the new offloading linker to perform the link job.">; HelpText<"Use the new offloading linker to perform the link job.">;
def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
- Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>,+ Visibility<[ClangOption, CLOption, FlangOption]>,
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">, HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
Group<Link_Group>; Group<Link_Group>;
def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">, def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">,
- Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>,+ Visibility<[ClangOption, FlangOption]>,
HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">, HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">,
MetaVarName<"<triple> <arg>">, Group<Link_Group>; MetaVarName<"<triple> <arg>">, Group<Link_Group>;
def Xpreprocessor : Separate<["-"], "Xpreprocessor">, Group<Preprocessor_Group>, def Xpreprocessor : Separate<["-"], "Xpreprocessor">, Group<Preprocessor_Group>,
@@ -1176,7 +1176,7 @@ def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
def config : Joined<["--"], "config=">, Flags<[NoXarchOption]>, def config : Joined<["--"], "config=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, MetaVarName<"<file>">, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, MetaVarName<"<file>">,
HelpText<"Specify configuration file">; HelpText<"Specify configuration file">;
-def : Separate<["--"], "config">, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias<config>;+def : Separate<["--"], "config">, Visibility<[ClangOption, FlangOption]>, Alias<config>;
def no_default_config : Flag<["--"], "no-default-config">, def no_default_config : Flag<["--"], "no-default-config">,
Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"Disable loading default configuration files">; HelpText<"Disable loading default configuration files">;
@@ -1990,7 +1990,7 @@ def : Flag<["-"], "fno-diagnostics-color">, Group<f_Group>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
Alias<fno_color_diagnostics>; Alias<fno_color_diagnostics>;
def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>, def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>,
- Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,+ Visibility<[ClangOption, FlangOption]>,
Values<"auto,always,never">, Values<"auto,always,never">,
HelpText<"When to use colors in diagnostics">; HelpText<"When to use colors in diagnostics">;
def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>, def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>,
@@ -2016,10 +2016,10 @@ argument are escaped with backslashes. This format differs from the format of
the equivalent section produced by GCC with the -frecord-gcc-switches flag. the equivalent section produced by GCC with the -frecord-gcc-switches flag.
This option is currently only supported on ELF targets.}]>, This option is currently only supported on ELF targets.}]>,
Group<f_Group>, Group<f_Group>,
- Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;+ Visibility<[ClangOption, FlangOption]>;
def fno_record_command_line : Flag<["-"], "fno-record-command-line">, def fno_record_command_line : Flag<["-"], "fno-record-command-line">,
Group<f_Group>, Group<f_Group>,
- Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;+ Visibility<[ClangOption, FlangOption]>;
def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>; def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>;
def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>; def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>, def fcommon : Flag<["-"], "fcommon">, Group<f_Group>,
@@ -3463,6 +3463,9 @@ defm diagnostics_show_line_numbers : BoolFOption<"diagnostics-show-line-numbers"
NegFlag<SetFalse, [], [ClangOption, CC1Option], NegFlag<SetFalse, [], [ClangOption, CC1Option],
"Show line numbers in diagnostic code snippets">, "Show line numbers in diagnostic code snippets">,
PosFlag<SetTrue>>; PosFlag<SetTrue>>;
+def fno_realloc_lhs : Flag<["-"], "fno-realloc-lhs">, Group<f_Group>,
+ HelpText<"An allocatable left-hand side of an intrinsic assignment is assumed to be allocated and match the shape/type of the right-hand side">,
+ Visibility<[FlangOption, FC1Option]>;
def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>, def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>,
HelpText<"Disable the use of stack protectors">; HelpText<"Disable the use of stack protectors">;
def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>, def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>,
@@ -4296,6 +4299,9 @@ defm stack_size_section : BoolFOption<"stack-size-section",
PosFlag<SetTrue, [], [ClangOption, CC1Option], PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Emit section containing metadata on function stack sizes">, "Emit section containing metadata on function stack sizes">,
NegFlag<SetFalse>>; NegFlag<SetFalse>>;
+def frealloc_lhs : Flag<["-"], "frealloc-lhs">, Group<f_Group>,
+ Visibility<[FlangOption, FC1Option]>,
+ HelpText<"If an allocatable left-hand side of an intrinsic assignment is unallocated or its shape/type does not match the right-hand side, then it is automatically (re)allocated">;
def fstack_usage : Flag<["-"], "fstack-usage">, Group<f_Group>, def fstack_usage : Flag<["-"], "fstack-usage">, Group<f_Group>,
HelpText<"Emit .su file containing information on function stack sizes">; HelpText<"Emit .su file containing information on function stack sizes">;
def stack_usage_file : Separate<["-"], "stack-usage-file">, def stack_usage_file : Separate<["-"], "stack-usage-file">,
@@ -5648,7 +5654,7 @@ def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option, FlangO
HelpText<"Link the LLVM C Library for GPUs">; HelpText<"Link the LLVM C Library for GPUs">;
def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>;
def nodefaultlibs : Flag<["-"], "nodefaultlibs">, def nodefaultlibs : Flag<["-"], "nodefaultlibs">,
- Visibility<[ClangOption, FlangOption, CLOption, DXCOption]>;+ Visibility<[ClangOption, FlangOption]>;
def nodriverkitlib : Flag<["-"], "nodriverkitlib">; def nodriverkitlib : Flag<["-"], "nodriverkitlib">;
def nofixprebinding : Flag<["-"], "nofixprebinding">; def nofixprebinding : Flag<["-"], "nofixprebinding">;
def nolibc : Flag<["-"], "nolibc">; def nolibc : Flag<["-"], "nolibc">;
@@ -5670,10 +5676,10 @@ def nostdincxx : Flag<["-"], "nostdinc++">, Visibility<[ClangOption, CC1Option]>
HelpText<"Disable standard #include directories for the C++ standard library">, HelpText<"Disable standard #include directories for the C++ standard library">,
MarshallingInfoNegativeFlag<HeaderSearchOpts<"UseStandardCXXIncludes">>; MarshallingInfoNegativeFlag<HeaderSearchOpts<"UseStandardCXXIncludes">>;
def nostdlib : Flag<["-"], "nostdlib">, def nostdlib : Flag<["-"], "nostdlib">,
- Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>,+ Visibility<[ClangOption, FlangOption]>,
Group<Link_Group>; Group<Link_Group>;
def stdlib : Flag<["-"], "stdlib">, def stdlib : Flag<["-"], "stdlib">,
- Visibility<[ClangOption, CLOption, FlangOption, DXCOption]>,+ Visibility<[ClangOption, FlangOption]>,
Group<Link_Group>; Group<Link_Group>;
def nostdlibxx : Flag<["-"], "nostdlib++">; def nostdlibxx : Flag<["-"], "nostdlib++">;
def object : Flag<["-"], "object">; def object : Flag<["-"], "object">;
@@ -5787,7 +5793,7 @@ def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
Alias<resource_dir>; Alias<resource_dir>;
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>, def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>,
- Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;+ Visibility<[ClangOption, FlangOption]>;
def rtlib_EQ : Joined<["-", "--"], "rtlib=">, Visibility<[ClangOption, CLOption, FlangOption]>, def rtlib_EQ : Joined<["-", "--"], "rtlib=">, Visibility<[ClangOption, CLOption, FlangOption]>,
HelpText<"Compiler runtime library to use">; HelpText<"Compiler runtime library to use">;
def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>, def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>,
@@ -5851,7 +5857,7 @@ def segs__read__write__addr : Separate<["-"], "segs_read_write_addr">;
def segs__read__ : Joined<["-"], "segs_read_">; def segs__read__ : Joined<["-"], "segs_read_">;
def shared_libgcc : Flag<["-"], "shared-libgcc">; def shared_libgcc : Flag<["-"], "shared-libgcc">;
def shared : Flag<["-", "--"], "shared">, Group<Link_Group>, def shared : Flag<["-", "--"], "shared">, Group<Link_Group>,
- Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;+ Visibility<[ClangOption, FlangOption]>;
def single__module : Flag<["-"], "single_module">; def single__module : Flag<["-"], "single_module">;
def specs_EQ : Joined<["-", "--"], "specs=">, Group<Link_Group>; def specs_EQ : Joined<["-", "--"], "specs=">, Group<Link_Group>;
def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>; def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>;
@@ -5861,7 +5867,7 @@ def start_no_unused_arguments : Flag<["--"], "start-no-unused-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 : Flag<["-", "--"], "static">, Group<Link_Group>, def static : Flag<["-", "--"], "static">, Group<Link_Group>,
- Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,+ Visibility<[ClangOption, FlangOption]>,
Flags<[NoArgumentUnused]>; Flags<[NoArgumentUnused]>;
def std_default_EQ : Joined<["-"], "std-default=">; def std_default_EQ : Joined<["-"], "std-default=">;
def std_EQ : Joined<["-", "--"], "std=">, def std_EQ : Joined<["-", "--"], "std=">,
@@ -6775,7 +6781,6 @@ defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group<gfortran_Group>;
defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>; defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>;
defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>; defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>;
defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>; defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>;
-defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group<gfortran_Group>;
defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>; defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>;
defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>; defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>;
defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>; defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>;
@@ -6908,6 +6913,7 @@ defm underscoring : OptInFC1FFlag<"underscoring", "Appends one trailing undersco
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)">,
NegFlag<SetFalse, [], [ClangOption], "Specifies PowerPC non-native vector element order">>; NegFlag<SetFalse, [], [ClangOption], "Specifies PowerPC non-native vector element order">>;
+defm unsigned : OptInFC1FFlag<"unsigned", "Enables UNSIGNED type">;
def fno_automatic : Flag<["-"], "fno-automatic">, Group<f_Group>, def fno_automatic : Flag<["-"], "fno-automatic">, Group<f_Group>,
HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">; HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">;
clang/include/clang/Driver/SanitizerArgs.h
@@ -87,6 +87,7 @@ public:
bool needsHwasanAliasesRt() const { bool needsHwasanAliasesRt() const {
return needsHwasanRt() && HwasanUseAliases; return needsHwasanRt() && HwasanUseAliases;
} }
+ bool needsTysanRt() const { return Sanitizers.has(SanitizerKind::Type); }
bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); }
bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); }
bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); } bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); }
clang/include/clang/Sema/Sema.h
@@ -10659,6 +10659,11 @@ public:
SourceLocation EndLoc); SourceLocation EndLoc);
void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
+ /// DiagnoseDiscardedExprMarkedNodiscard - Given an expression that is
+ /// semantically a discarded-value expression, diagnose if any [[nodiscard]]
+ /// value has been discarded.
+ void DiagnoseDiscardedExprMarkedNodiscard(const Expr *E);
+
/// DiagnoseUnusedExprResult - If the statement passed in is an expression /// DiagnoseUnusedExprResult - If the statement passed in is an expression
/// whose result is unused, warn. /// whose result is unused, warn.
void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID); void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID);
clang/include/clang/Sema/SemaOpenACC.h
@@ -399,6 +399,8 @@ public:
ClauseKind == OpenACCClauseKind::PCreate || ClauseKind == OpenACCClauseKind::PCreate ||
ClauseKind == OpenACCClauseKind::PresentOrCreate || ClauseKind == OpenACCClauseKind::PresentOrCreate ||
ClauseKind == OpenACCClauseKind::Attach || ClauseKind == OpenACCClauseKind::Attach ||
+ ClauseKind == OpenACCClauseKind::Delete ||
+ ClauseKind == OpenACCClauseKind::UseDevice ||
ClauseKind == OpenACCClauseKind::Detach || ClauseKind == OpenACCClauseKind::Detach ||
ClauseKind == OpenACCClauseKind::DevicePtr || ClauseKind == OpenACCClauseKind::DevicePtr ||
ClauseKind == OpenACCClauseKind::Reduction || ClauseKind == OpenACCClauseKind::Reduction ||
@@ -536,6 +538,8 @@ public:
ClauseKind == OpenACCClauseKind::PCreate || ClauseKind == OpenACCClauseKind::PCreate ||
ClauseKind == OpenACCClauseKind::PresentOrCreate || ClauseKind == OpenACCClauseKind::PresentOrCreate ||
ClauseKind == OpenACCClauseKind::Attach || ClauseKind == OpenACCClauseKind::Attach ||
+ ClauseKind == OpenACCClauseKind::Delete ||
+ ClauseKind == OpenACCClauseKind::UseDevice ||
ClauseKind == OpenACCClauseKind::Detach || ClauseKind == OpenACCClauseKind::Detach ||
ClauseKind == OpenACCClauseKind::DevicePtr || ClauseKind == OpenACCClauseKind::DevicePtr ||
ClauseKind == OpenACCClauseKind::FirstPrivate) && ClauseKind == OpenACCClauseKind::FirstPrivate) &&
@@ -573,6 +577,8 @@ public:
ClauseKind == OpenACCClauseKind::PCreate || ClauseKind == OpenACCClauseKind::PCreate ||
ClauseKind == OpenACCClauseKind::PresentOrCreate || ClauseKind == OpenACCClauseKind::PresentOrCreate ||
ClauseKind == OpenACCClauseKind::Attach || ClauseKind == OpenACCClauseKind::Attach ||
+ ClauseKind == OpenACCClauseKind::Delete ||
+ ClauseKind == OpenACCClauseKind::UseDevice ||
ClauseKind == OpenACCClauseKind::Detach || ClauseKind == OpenACCClauseKind::Detach ||
ClauseKind == OpenACCClauseKind::DevicePtr || ClauseKind == OpenACCClauseKind::DevicePtr ||
ClauseKind == OpenACCClauseKind::FirstPrivate) && ClauseKind == OpenACCClauseKind::FirstPrivate) &&
@@ -656,7 +662,8 @@ public:
/// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
/// happen before any associated declarations or statements have been parsed. /// happen before any associated declarations or statements have been parsed.
/// This function is only called when we are parsing a 'statement' context. /// This function is only called when we are parsing a 'statement' context.
- bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc);+ bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc,
+ ArrayRef<const OpenACCClause *> Clauses);
/// Called after the directive, including its clauses, have been parsed and /// Called after the directive, including its clauses, have been parsed and
/// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
clang/include/clang/Serialization/ASTBitCodes.h
@@ -724,11 +724,9 @@ enum ASTRecordTypes {
/// Record code for vtables to emit. /// Record code for vtables to emit.
VTABLES_TO_EMIT = 70, VTABLES_TO_EMIT = 70,
- /// Record code for the FunctionDecl to lambdas mapping. These lambdas have to+ /// Record code for related declarations that have to be deserialized together
- /// be loaded right after the function they belong to. It is required to have+ /// from the same module.
- /// canonical declaration for the lambda class from the same module as+ RELATED_DECLS_MAP = 71,
- /// enclosing function.
- FUNCTION_DECL_TO_LAMBDAS_MAP = 71,
/// Record code for Sema's vector of functions/blocks with effects to /// Record code for Sema's vector of functions/blocks with effects to
/// be verified. /// be verified.
clang/include/clang/Serialization/ASTReader.h
@@ -537,17 +537,14 @@ private:
/// namespace as if it is not delayed. /// namespace as if it is not delayed.
DelayedNamespaceOffsetMapTy DelayedNamespaceOffsetMap; DelayedNamespaceOffsetMapTy DelayedNamespaceOffsetMap;
- /// Mapping from FunctionDecl IDs to the corresponding lambda IDs.+ /// Mapping from main decl ID to the related decls IDs.
- ///+ ///
- /// These lambdas have to be loaded right after the function they belong to.+ /// These related decls have to be loaded right after the main decl.
- /// It is required to have canonical declaration for lambda class from the+ /// It is required to have canonical declaration for related decls from the
- /// same module as enclosing function. This is required to correctly resolve+ /// same module as the enclosing main decl. Without this, due to lazy
- /// captured variables in the lambda. Without this, due to lazy+ /// deserialization, canonical declarations for the main decl and related can
- /// deserialization, canonical declarations for the function and lambdas can+ /// be selected from different modules.
- /// be selected from different modules and DeclRefExprs may refer to the AST+ llvm::DenseMap<GlobalDeclID, SmallVector<GlobalDeclID, 4>> RelatedDeclsMap;
- /// nodes that don't exist in the function.
- llvm::DenseMap<GlobalDeclID, SmallVector<GlobalDeclID, 4>>
- FunctionToLambdasMap;
struct PendingUpdateRecord { struct PendingUpdateRecord {
Decl *D; Decl *D;
clang/include/clang/Serialization/ASTWriter.h
@@ -230,13 +230,12 @@ private:
/// instead of comparing the result of `getDeclID()` or `GetDeclRef()`. /// instead of comparing the result of `getDeclID()` or `GetDeclRef()`.
llvm::SmallPtrSet<const Decl *, 32> PredefinedDecls; llvm::SmallPtrSet<const Decl *, 32> PredefinedDecls;
- /// Mapping from FunctionDecl ID to the list of lambda IDs inside the+ /// Mapping from the main decl to related decls inside the main decls.
- /// function.
/// ///
- /// These lambdas have to be loaded right after the function they belong to.+ /// These related decls have to be loaded right after the main decl they
- /// In order to have canonical declaration for lambda class from the same+ /// belong to. In order to have canonical declaration for related decls from
- /// module as enclosing function during deserialization.+ /// the same module as the main decl during deserialization.
- llvm::DenseMap<LocalDeclID, SmallVector<LocalDeclID, 4>> FunctionToLambdasMap;+ llvm::DenseMap<LocalDeclID, SmallVector<LocalDeclID, 4>> RelatedDeclsMap;
/// Offset of each declaration in the bitstream, indexed by /// Offset of each declaration in the bitstream, indexed by
/// the declaration's ID. /// the declaration's ID.
clang/lib/AST/ByteCode/Compiler.cpp
@@ -6483,14 +6483,6 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
QualType ToType = E->getType(); QualType ToType = E->getType();
std::optional<PrimType> ToT = classify(ToType); std::optional<PrimType> ToT = classify(ToType);
- // Bitcasting TO nullptr_t is always fine.
- if (ToType->isNullPtrType()) {
- if (!this->discard(SubExpr))
- return false;
-
- return this->emitNullPtr(0, nullptr, E);
- }
-
assert(!ToType->isReferenceType()); assert(!ToType->isReferenceType());
// Prepare storage for the result in case we discard. // Prepare storage for the result in case we discard.
@@ -6523,8 +6515,8 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
return false; return false;
} }
- if (!ToT || ToT == PT_Ptr) {+ if (!ToT) {
- if (!this->emitBitCastPtr(E))+ if (!this->emitBitCast(E))
return false; return false;
return DiscardResult ? this->emitPopPtr(E) : true; return DiscardResult ? this->emitPopPtr(E) : true;
} }
@@ -6540,8 +6532,8 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
ToType->isSpecificBuiltinType(BuiltinType::Char_U)); ToType->isSpecificBuiltinType(BuiltinType::Char_U));
uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u); uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);
- if (!this->emitBitCast(*ToT, ToTypeIsUChar || ToType->isStdByteType(),+ if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
- ResultBitWidth, TargetSemantics, E))+ ResultBitWidth, TargetSemantics, E))
return false; return false;
if (DiscardResult) if (DiscardResult)
clang/lib/AST/ByteCode/Integral.h
@@ -179,7 +179,10 @@ public:
unsigned countLeadingZeros() const { unsigned countLeadingZeros() const {
if constexpr (!Signed) if constexpr (!Signed)
return llvm::countl_zero<ReprT>(V); return llvm::countl_zero<ReprT>(V);
- llvm_unreachable("Don't call countLeadingZeros() on signed types.");+ if (isPositive())
+ return llvm::countl_zero<typename AsUnsigned::ReprT>(
+ static_cast<typename AsUnsigned::ReprT>(V));
+ llvm_unreachable("Don't call countLeadingZeros() on negative values.");
} }
Integral truncate(unsigned TruncBits) const { Integral truncate(unsigned TruncBits) const {
@@ -210,7 +213,7 @@ public:
return Integral(Value.V); return Integral(Value.V);
} }
- static Integral zero() { return from(0); }+ static Integral zero(unsigned BitWidth = 0) { return from(0); }
template <typename T> static Integral from(T Value, unsigned NumBits) { template <typename T> static Integral from(T Value, unsigned NumBits) {
return Integral(Value); return Integral(Value);
clang/lib/AST/ByteCode/Interp.h
@@ -318,18 +318,6 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Ret(InterpState &S, CodePtr &PC) { bool Ret(InterpState &S, CodePtr &PC) {
const T &Ret = S.Stk.pop<T>(); const T &Ret = S.Stk.pop<T>();
- // Make sure returned pointers are live. We might be trying to return a
- // pointer or reference to a local variable.
- // Just return false, since a diagnostic has already been emitted in Sema.
- if constexpr (std::is_same_v<T, Pointer>) {
- // FIXME: We could be calling isLive() here, but the emitted diagnostics
- // seem a little weird, at least if the returned expression is of
- // pointer type.
- // Null pointers are considered live here.
- if (!Ret.isZero() && !Ret.isLive())
- return false;
- }
-
assert(S.Current); assert(S.Current);
assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame"); assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
if (!S.checkingPotentialConstantExpression() || S.Current->Caller) if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
@@ -2511,50 +2499,52 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
S, OpPC, LHS, RHS); S, OpPC, LHS, RHS);
} }
- if constexpr (Dir == ShiftDir::Left) {
- if (LHS.isNegative() && !S.getLangOpts().CPlusPlus20) {
- // C++11 [expr.shift]p2: A signed left shift must have a non-negative
- // operand, and must not overflow the corresponding unsigned type.
- // C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
- // E1 x 2^E2 module 2^N.
- const SourceInfo &Loc = S.Current->getSource(OpPC);
- S.CCEDiag(Loc, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
- if (!S.noteUndefinedBehavior())
- return false;
- }
- }
-
if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits)) if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
return false; return false;
// Limit the shift amount to Bits - 1. If this happened, // Limit the shift amount to Bits - 1. If this happened,
// it has already been diagnosed by CheckShift() above, // it has already been diagnosed by CheckShift() above,
// but we still need to handle it. // but we still need to handle it.
+ // Note that we have to be extra careful here since we're doing the shift in
+ // any case, but we need to adjust the shift amount or the way we do the shift
+ // for the potential error cases.
typename LT::AsUnsigned R; typename LT::AsUnsigned R;
+ unsigned MaxShiftAmount = LHS.bitWidth() - 1;
if constexpr (Dir == ShiftDir::Left) { if constexpr (Dir == ShiftDir::Left) {
- if (RHS > RT::from(Bits - 1, RHS.bitWidth()))+ if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
- LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),+ ComparisonCategoryResult::Greater) {
- LT::AsUnsigned::from(Bits - 1), Bits, &R);+ if (LHS.isNegative())
- else+ R = LT::AsUnsigned::zero(LHS.bitWidth());
+ else {
+ RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
+ LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
+ LT::AsUnsigned::from(RHS, Bits), Bits, &R);
+ }
+ } else if (LHS.isNegative()) {
+ if (LHS.isMin()) {
+ R = LT::AsUnsigned::zero(LHS.bitWidth());
+ } else {
+ // If the LHS is negative, perform the cast and invert the result.
+ typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
+ LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS, Bits), Bits,
+ &R);
+ R = -R;
+ }
+ } else {
+ // The good case, a simple left shift.
LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS), LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
LT::AsUnsigned::from(RHS, Bits), Bits, &R); LT::AsUnsigned::from(RHS, Bits), Bits, &R);
+ }
} else { } else {
- if (RHS > RT::from(Bits - 1, RHS.bitWidth()))+ // Right shift.
- LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),+ if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
- LT::AsUnsigned::from(Bits - 1), Bits, &R);+ ComparisonCategoryResult::Greater) {
- else+ R = LT::AsUnsigned::from(-1);
- LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),+ } else {
- LT::AsUnsigned::from(RHS, Bits), Bits, &R);+ // Do the shift on potentially signed LT, then convert to unsigned type.
- }+ LT A;
-+ LT::shiftRight(LHS, LT::from(RHS, Bits), Bits, &A);
- // We did the shift above as unsigned. Restore the sign bit if we need to.+ R = LT::AsUnsigned::from(A);
- if constexpr (Dir == ShiftDir::Right) {
- if (LHS.isSigned() && LHS.isNegative()) {
- typename LT::AsUnsigned SignBit;
- LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(1, Bits),
- LT::AsUnsigned::from(Bits - 1, Bits), Bits,
- &SignBit);
- LT::AsUnsigned::bitOr(R, SignBit, Bits, &R);
} }
} }
@@ -3040,43 +3030,51 @@ bool CheckNewTypeMismatchArray(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);
template <PrimType Name, class T = typename PrimConv<Name>::T> template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,+inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
- uint32_t ResultBitWidth, const llvm::fltSemantics *Sem) {+ uint32_t ResultBitWidth,
+ const llvm::fltSemantics *Sem) {
const Pointer &FromPtr = S.Stk.pop<Pointer>(); const Pointer &FromPtr = S.Stk.pop<Pointer>();
if (!CheckLoad(S, OpPC, FromPtr)) if (!CheckLoad(S, OpPC, FromPtr))
return false; return false;
- size_t BuffSize = ResultBitWidth / 8;+ if constexpr (std::is_same_v<T, Pointer>) {
- llvm::SmallVector<std::byte> Buff(BuffSize);+ // The only pointer type we can validly bitcast to is nullptr_t.
- bool HasIndeterminateBits = false;+ S.Stk.push<Pointer>();
+ return true;
+ } else {
- Bits FullBitWidth(ResultBitWidth);+ size_t BuffSize = ResultBitWidth / 8;
- Bits BitWidth = FullBitWidth;+ llvm::SmallVector<std::byte> Buff(BuffSize);
+ bool HasIndeterminateBits = false;
- if constexpr (std::is_same_v<T, Floating>) {+ Bits FullBitWidth(ResultBitWidth);
- assert(Sem);+ Bits BitWidth = FullBitWidth;
- BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
- }
- if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,+ if constexpr (std::is_same_v<T, Floating>) {
- HasIndeterminateBits))+ assert(Sem);
- return false;+ BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
+ }
- if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))+ if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
- return false;+ HasIndeterminateBits))
+ return false;
- if constexpr (std::is_same_v<T, Floating>) {+ if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
- assert(Sem);+ return false;
- S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));+
- } else {+ if constexpr (std::is_same_v<T, Floating>) {
- assert(!Sem);+ assert(Sem);
- S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));+ S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
+ } else {
+ assert(!Sem);
+ S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
+ }
+ return true;
} }
- return true;
} }
-inline bool BitCastPtr(InterpState &S, CodePtr OpPC) {+inline bool BitCast(InterpState &S, CodePtr OpPC) {
const Pointer &FromPtr = S.Stk.pop<Pointer>(); const Pointer &FromPtr = S.Stk.pop<Pointer>();
Pointer &ToPtr = S.Stk.peek<Pointer>(); Pointer &ToPtr = S.Stk.peek<Pointer>();
clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1917,7 +1917,8 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
const APSInt &Size = const APSInt &Size =
peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))); peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)));
- if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp)+ if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
+ ID == Builtin::BIwmemcmp)
diagnoseNonConstexprBuiltin(S, OpPC, ID); diagnoseNonConstexprBuiltin(S, OpPC, ID);
if (Size.isZero()) { if (Size.isZero()) {
@@ -1925,14 +1926,18 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
return true; return true;
} }
+ bool IsWide =
+ (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
+
+ const ASTContext &ASTCtx = S.getASTContext();
// FIXME: This is an arbitrary limitation the current constant interpreter // FIXME: This is an arbitrary limitation the current constant interpreter
// had. We could remove this. // had. We could remove this.
- if (!isOneByteCharacterType(PtrA.getType()) ||+ if (!IsWide && (!isOneByteCharacterType(PtrA.getType()) ||
- !isOneByteCharacterType(PtrB.getType())) {+ !isOneByteCharacterType(PtrB.getType()))) {
S.FFDiag(S.Current->getSource(OpPC), S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_memcmp_unsupported) diag::note_constexpr_memcmp_unsupported)
- << ("'" + S.getASTContext().BuiltinInfo.getName(ID) + "'").str()+ << ("'" + ASTCtx.BuiltinInfo.getName(ID) + "'").str() << PtrA.getType()
- << PtrA.getType() << PtrB.getType();+ << PtrB.getType();
return false; return false;
} }
@@ -1941,42 +1946,62 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
// Now, read both pointers to a buffer and compare those. // Now, read both pointers to a buffer and compare those.
BitcastBuffer BufferA( BitcastBuffer BufferA(
- Bits(S.getASTContext().getTypeSize(PtrA.getFieldDesc()->getType())));+ Bits(ASTCtx.getTypeSize(PtrA.getFieldDesc()->getType())));
readPointerToBuffer(S.getContext(), PtrA, BufferA, false); readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
// FIXME: The swapping here is UNDOING something we do when reading the // FIXME: The swapping here is UNDOING something we do when reading the
// data into the buffer. // data into the buffer.
- if (S.getASTContext().getTargetInfo().isBigEndian())+ if (ASTCtx.getTargetInfo().isBigEndian())
swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity()); swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());
BitcastBuffer BufferB( BitcastBuffer BufferB(
- Bits(S.getASTContext().getTypeSize(PtrB.getFieldDesc()->getType())));+ Bits(ASTCtx.getTypeSize(PtrB.getFieldDesc()->getType())));
readPointerToBuffer(S.getContext(), PtrB, BufferB, false); readPointerToBuffer(S.getContext(), PtrB, BufferB, false);
// FIXME: The swapping here is UNDOING something we do when reading the // FIXME: The swapping here is UNDOING something we do when reading the
// data into the buffer. // data into the buffer.
- if (S.getASTContext().getTargetInfo().isBigEndian())+ if (ASTCtx.getTargetInfo().isBigEndian())
swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity()); swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());
size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(), size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),
BufferB.byteSize().getQuantity()); BufferB.byteSize().getQuantity());
- size_t CmpSize =
- std::min(MinBufferSize, static_cast<size_t>(Size.getZExtValue()));
-
- for (size_t I = 0; I != CmpSize; ++I) {
- std::byte A = BufferA.Data[I];
- std::byte B = BufferB.Data[I];
- if (A < B) {+ unsigned ElemSize = 1;
- pushInteger(S, -1, Call->getType());+ if (IsWide)
- return true;+ ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
- } else if (A > B) {+ // The Size given for the wide variants is in wide-char units. Convert it
- pushInteger(S, 1, Call->getType());+ // to bytes.
- return true;+ size_t ByteSize = Size.getZExtValue() * ElemSize;
+ size_t CmpSize = std::min(MinBufferSize, ByteSize);
+
+ for (size_t I = 0; I != CmpSize; I += ElemSize) {
+ if (IsWide) {
+ INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), {
+ T A = *reinterpret_cast<T *>(BufferA.Data.get() + I);
+ T B = *reinterpret_cast<T *>(BufferB.Data.get() + I);
+ if (A < B) {
+ pushInteger(S, -1, Call->getType());
+ return true;
+ } else if (A > B) {
+ pushInteger(S, 1, Call->getType());
+ return true;
+ }
+ });
+ } else {
+ std::byte A = BufferA.Data[I];
+ std::byte B = BufferB.Data[I];
+
+ if (A < B) {
+ pushInteger(S, -1, Call->getType());
+ return true;
+ } else if (A > B) {
+ pushInteger(S, 1, Call->getType());
+ return true;
+ }
} }
} }
// We compared CmpSize bytes above. If the limiting factor was the Size // We compared CmpSize bytes above. If the limiting factor was the Size
// passed, we're done and the result is equality (0). // passed, we're done and the result is equality (0).
- if (Size.getZExtValue() <= CmpSize) {+ if (ByteSize <= CmpSize) {
pushInteger(S, 0, Call->getType()); pushInteger(S, 0, Call->getType());
return true; return true;
} }
@@ -2467,6 +2492,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BImemcmp: case Builtin::BImemcmp:
case Builtin::BI__builtin_bcmp: case Builtin::BI__builtin_bcmp:
case Builtin::BIbcmp: case Builtin::BIbcmp:
+ case Builtin::BI__builtin_wmemcmp:
+ case Builtin::BIwmemcmp:
if (!interp__builtin_memcmp(S, OpPC, Frame, F, Call)) if (!interp__builtin_memcmp(S, OpPC, Frame, F, Call))
return false; return false;
break; break;
clang/lib/AST/ByteCode/Opcodes.td
@@ -839,13 +839,14 @@ def IsConstantContext: Opcode;
def CheckAllocations : Opcode; def CheckAllocations : Opcode;
def BitCastTypeClass : TypeClass { def BitCastTypeClass : TypeClass {
- let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, IntAP, IntAPS, Bool, Float];+ let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64,
+ IntAP, IntAPS, Bool, Float, Ptr];
} }
-def BitCast : Opcode {+def BitCastPrim : Opcode {
let Types = [BitCastTypeClass]; let Types = [BitCastTypeClass];
let Args = [ArgBool, ArgUint32, ArgFltSemantics]; let Args = [ArgBool, ArgUint32, ArgFltSemantics];
let HasGroup = 1; let HasGroup = 1;
} }
-def BitCastPtr : Opcode;+def BitCast : Opcode;
clang/lib/AST/Expr.cpp
@@ -2990,6 +2990,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case ExprWithCleanupsClass: case ExprWithCleanupsClass:
return cast<ExprWithCleanups>(this)->getSubExpr() return cast<ExprWithCleanups>(this)->getSubExpr()
->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx); ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
+ case OpaqueValueExprClass:
+ return cast<OpaqueValueExpr>(this)->getSourceExpr()->isUnusedResultAWarning(
+ WarnE, Loc, R1, R2, Ctx);
} }
} }
clang/lib/AST/OpenACCClause.cpp
@@ -32,7 +32,8 @@ bool OpenACCClauseWithVarList::classof(const OpenACCClause *C) {
return OpenACCPrivateClause::classof(C) || return OpenACCPrivateClause::classof(C) ||
OpenACCFirstPrivateClause::classof(C) || OpenACCFirstPrivateClause::classof(C) ||
OpenACCDevicePtrClause::classof(C) || OpenACCDevicePtrClause::classof(C) ||
- OpenACCDevicePtrClause::classof(C) ||+ OpenACCDeleteClause::classof(C) ||
+ OpenACCUseDeviceClause::classof(C) ||
OpenACCDetachClause::classof(C) || OpenACCAttachClause::classof(C) || OpenACCDetachClause::classof(C) || OpenACCAttachClause::classof(C) ||
OpenACCNoCreateClause::classof(C) || OpenACCNoCreateClause::classof(C) ||
OpenACCPresentClause::classof(C) || OpenACCCopyClause::classof(C) || OpenACCPresentClause::classof(C) || OpenACCCopyClause::classof(C) ||
@@ -288,6 +289,26 @@ OpenACCDetachClause *OpenACCDetachClause::Create(const ASTContext &C,
return new (Mem) OpenACCDetachClause(BeginLoc, LParenLoc, VarList, EndLoc); return new (Mem) OpenACCDetachClause(BeginLoc, LParenLoc, VarList, EndLoc);
} }
+OpenACCDeleteClause *OpenACCDeleteClause::Create(const ASTContext &C,
+ SourceLocation BeginLoc,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList,
+ SourceLocation EndLoc) {
+ void *Mem =
+ C.Allocate(OpenACCDeleteClause::totalSizeToAlloc<Expr *>(VarList.size()));
+ return new (Mem) OpenACCDeleteClause(BeginLoc, LParenLoc, VarList, EndLoc);
+}
+
+OpenACCUseDeviceClause *OpenACCUseDeviceClause::Create(const ASTContext &C,
+ SourceLocation BeginLoc,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(
+ OpenACCUseDeviceClause::totalSizeToAlloc<Expr *>(VarList.size()));
+ return new (Mem) OpenACCUseDeviceClause(BeginLoc, LParenLoc, VarList, EndLoc);
+}
+
OpenACCDevicePtrClause *OpenACCDevicePtrClause::Create(const ASTContext &C, OpenACCDevicePtrClause *OpenACCDevicePtrClause::Create(const ASTContext &C,
SourceLocation BeginLoc, SourceLocation BeginLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
@@ -564,6 +585,21 @@ void OpenACCClausePrinter::VisitDetachClause(const OpenACCDetachClause &C) {
OS << ")"; OS << ")";
} }
+void OpenACCClausePrinter::VisitDeleteClause(const OpenACCDeleteClause &C) {
+ OS << "delete(";
+ llvm::interleaveComma(C.getVarList(), OS,
+ [&](const Expr *E) { printExpr(E); });
+ OS << ")";
+}
+
+void OpenACCClausePrinter::VisitUseDeviceClause(
+ const OpenACCUseDeviceClause &C) {
+ OS << "use_device(";
+ llvm::interleaveComma(C.getVarList(), OS,
+ [&](const Expr *E) { printExpr(E); });
+ OS << ")";
+}
+
void OpenACCClausePrinter::VisitDevicePtrClause( void OpenACCClausePrinter::VisitDevicePtrClause(
const OpenACCDevicePtrClause &C) { const OpenACCDevicePtrClause &C) {
OS << "deviceptr("; OS << "deviceptr(";
clang/lib/AST/StmtProfile.cpp
@@ -2515,6 +2515,11 @@ public:
} }
} }
+ void VisitClauseWithVarList(const OpenACCClauseWithVarList &Clause) {
+ for (auto *E : Clause.getVarList())
+ Profiler.VisitStmt(E);
+ }
+
#define VISIT_CLAUSE(CLAUSE_NAME) \ #define VISIT_CLAUSE(CLAUSE_NAME) \
void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
@@ -2532,25 +2537,21 @@ void OpenACCClauseProfiler::VisitIfClause(const OpenACCIfClause &Clause) {
} }
void OpenACCClauseProfiler::VisitCopyClause(const OpenACCCopyClause &Clause) { void OpenACCClauseProfiler::VisitCopyClause(const OpenACCCopyClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitCopyInClause( void OpenACCClauseProfiler::VisitCopyInClause(
const OpenACCCopyInClause &Clause) { const OpenACCCopyInClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitCopyOutClause( void OpenACCClauseProfiler::VisitCopyOutClause(
const OpenACCCopyOutClause &Clause) { const OpenACCCopyOutClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitCreateClause( void OpenACCClauseProfiler::VisitCreateClause(
const OpenACCCreateClause &Clause) { const OpenACCCreateClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) { void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
@@ -2589,44 +2590,47 @@ void OpenACCClauseProfiler::VisitCollapseClause(
void OpenACCClauseProfiler::VisitPrivateClause( void OpenACCClauseProfiler::VisitPrivateClause(
const OpenACCPrivateClause &Clause) { const OpenACCPrivateClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitFirstPrivateClause( void OpenACCClauseProfiler::VisitFirstPrivateClause(
const OpenACCFirstPrivateClause &Clause) { const OpenACCFirstPrivateClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitAttachClause( void OpenACCClauseProfiler::VisitAttachClause(
const OpenACCAttachClause &Clause) { const OpenACCAttachClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitDetachClause( void OpenACCClauseProfiler::VisitDetachClause(
const OpenACCDetachClause &Clause) { const OpenACCDetachClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);+}
+
+void OpenACCClauseProfiler::VisitDeleteClause(
+ const OpenACCDeleteClause &Clause) {
+ VisitClauseWithVarList(Clause);
} }
void OpenACCClauseProfiler::VisitDevicePtrClause( void OpenACCClauseProfiler::VisitDevicePtrClause(
const OpenACCDevicePtrClause &Clause) { const OpenACCDevicePtrClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitNoCreateClause( void OpenACCClauseProfiler::VisitNoCreateClause(
const OpenACCNoCreateClause &Clause) { const OpenACCNoCreateClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
void OpenACCClauseProfiler::VisitPresentClause( void OpenACCClauseProfiler::VisitPresentClause(
const OpenACCPresentClause &Clause) { const OpenACCPresentClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);+}
+
+void OpenACCClauseProfiler::VisitUseDeviceClause(
+ const OpenACCUseDeviceClause &Clause) {
+ VisitClauseWithVarList(Clause);
} }
void OpenACCClauseProfiler::VisitVectorLengthClause( void OpenACCClauseProfiler::VisitVectorLengthClause(
@@ -2678,8 +2682,7 @@ void OpenACCClauseProfiler::VisitGangClause(const OpenACCGangClause &Clause) {
void OpenACCClauseProfiler::VisitReductionClause( void OpenACCClauseProfiler::VisitReductionClause(
const OpenACCReductionClause &Clause) { const OpenACCReductionClause &Clause) {
- for (auto *E : Clause.getVarList())+ VisitClauseWithVarList(Clause);
- Profiler.VisitStmt(E);
} }
} // namespace } // namespace
clang/lib/AST/TextNodeDumper.cpp
@@ -412,6 +412,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::IfPresent: case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Independent: case OpenACCClauseKind::Independent:
case OpenACCClauseKind::Detach: case OpenACCClauseKind::Detach:
+ case OpenACCClauseKind::Delete:
case OpenACCClauseKind::DevicePtr: case OpenACCClauseKind::DevicePtr:
case OpenACCClauseKind::Finalize: case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::FirstPrivate: case OpenACCClauseKind::FirstPrivate:
@@ -424,6 +425,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Seq: case OpenACCClauseKind::Seq:
case OpenACCClauseKind::Tile: case OpenACCClauseKind::Tile:
case OpenACCClauseKind::Worker: case OpenACCClauseKind::Worker:
+ case OpenACCClauseKind::UseDevice:
case OpenACCClauseKind::Vector: case OpenACCClauseKind::Vector:
case OpenACCClauseKind::VectorLength: case OpenACCClauseKind::VectorLength:
// The condition expression will be printed as a part of the 'children', // The condition expression will be printed as a part of the 'children',
clang/lib/CodeGen/BackendUtil.cpp
@@ -77,6 +77,7 @@
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h" #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
+#include "llvm/Transforms/Instrumentation/TypeSanitizer.h"
#include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/GVN.h"
@@ -735,6 +736,11 @@ static void addSanitizers(const Triple &TargetTriple,
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
} }
+ if (LangOpts.Sanitize.has(SanitizerKind::Type)) {
+ MPM.addPass(ModuleTypeSanitizerPass());
+ MPM.addPass(createModuleToFunctionPassAdaptor(TypeSanitizerPass()));
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::NumericalStability)) if (LangOpts.Sanitize.has(SanitizerKind::NumericalStability))
MPM.addPass(NumericalStabilitySanitizerPass()); MPM.addPass(NumericalStabilitySanitizerPass());
clang/lib/CodeGen/CGBuiltin.cpp
@@ -19436,6 +19436,15 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
/*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(), /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step"); ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
} }
+ case Builtin::BI__builtin_hlsl_wave_active_all_true: {
+ Value *Op = EmitScalarExpr(E->getArg(0));
+ assert(Op->getType()->isIntegerTy(1) &&
+ "Intrinsic WaveActiveAllTrue operand must be a bool");
+
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
+ return EmitRuntimeCall(
+ Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});
+ }
case Builtin::BI__builtin_hlsl_wave_active_any_true: { case Builtin::BI__builtin_hlsl_wave_active_any_true: {
Value *Op = EmitScalarExpr(E->getArg(0)); Value *Op = EmitScalarExpr(E->getArg(0));
assert(Op->getType()->isIntegerTy(1) && assert(Op->getType()->isIntegerTy(1) &&
clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2021,28 +2021,10 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
// ThisPtr may be null if the member function has an explicit 'this' // ThisPtr may be null if the member function has an explicit 'this'
// parameter. // parameter.
if (!ThisPtr.isNull()) { if (!ThisPtr.isNull()) {
- const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl();+ llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit);
- if (isa<ClassTemplateSpecializationDecl>(RD)) {+ TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType);
- // Create pointer type directly in this case.+ ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);+ Elts.push_back(ThisPtrType);
- uint64_t Size = CGM.getContext().getTypeSize(ThisPtrTy);
- auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext());
- llvm::DIType *PointeeType =
- getOrCreateType(ThisPtrTy->getPointeeType(), Unit);
- llvm::DIType *ThisPtrType =
- DBuilder.createPointerType(PointeeType, Size, Align);
- TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType);
- // TODO: This and the artificial type below are misleading, the
- // types aren't artificial the argument is, but the current
- // metadata doesn't represent that.
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- Elts.push_back(ThisPtrType);
- } else {
- llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit);
- TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType);
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- Elts.push_back(ThisPtrType);
- }
} }
// Copy rest of the arguments. // Copy rest of the arguments.
@@ -2995,20 +2977,21 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (!ID) if (!ID)
return nullptr; return nullptr;
+ auto RuntimeLang =
+ static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
+
// Return a forward declaration if this type was imported from a clang module, // Return a forward declaration if this type was imported from a clang module,
// and this is not the compile unit with the implementation of the type (which // and this is not the compile unit with the implementation of the type (which
// may contain hidden ivars). // may contain hidden ivars).
if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() && if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() &&
!ID->getImplementation()) !ID->getImplementation())
- return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,+ return DBuilder.createForwardDecl(
- ID->getName(),+ llvm::dwarf::DW_TAG_structure_type, ID->getName(),
- getDeclContextDescriptor(ID), Unit, 0);+ getDeclContextDescriptor(ID), Unit, 0, RuntimeLang);
// Get overall information about the record type for the debug info. // Get overall information about the record type for the debug info.
llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation()); llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation()); unsigned Line = getLineNumber(ID->getLocation());
- auto RuntimeLang =
- static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
// If this is just a forward declaration return a special forward-declaration // If this is just a forward declaration return a special forward-declaration
// debug type since we won't be able to lay out the entire type. // debug type since we won't be able to lay out the entire type.
clang/lib/CodeGen/CGDeclCXX.cpp
@@ -479,6 +479,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
!isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc)) !isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
+ if (getLangOpts().Sanitize.has(SanitizerKind::Type) &&
+ !isInNoSanitizeList(SanitizerKind::Type, Fn, Loc))
+ Fn->addFnAttr(llvm::Attribute::SanitizeType);
+
if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc)) !isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeThread); Fn->addFnAttr(llvm::Attribute::SanitizeThread);
clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -512,13 +512,17 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() {
IP = Token->getNextNode(); IP = Token->getNextNode();
} }
IRBuilder<> B(IP); IRBuilder<> B(IP);
- for (auto *Fn : CtorFns)+ for (auto *Fn : CtorFns) {
- B.CreateCall(FunctionCallee(Fn), {}, OB);+ auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
+ CI->setCallingConv(Fn->getCallingConv());
+ }
// Insert global dtors before the terminator of the last instruction // Insert global dtors before the terminator of the last instruction
B.SetInsertPoint(F.back().getTerminator()); B.SetInsertPoint(F.back().getTerminator());
- for (auto *Fn : DtorFns)+ for (auto *Fn : DtorFns) {
- B.CreateCall(FunctionCallee(Fn), {}, OB);+ auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
+ CI->setCallingConv(Fn->getCallingConv());
+ }
} }
// No need to keep global ctors/dtors for non-lib profile after call to // No need to keep global ctors/dtors for non-lib profile after call to
clang/lib/CodeGen/CGHLSLRuntime.h
@@ -92,6 +92,7 @@ public:
GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed) GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed) GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -9042,337 +9042,69 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
return; return;
ASTContext &C = CGM.getContext(); ASTContext &C = CGM.getContext();
QualType Ty = D->getType(); QualType Ty = D->getType();
- QualType PtrTy = C.getPointerType(Ty).withRestrict();
- QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
auto *MapperVarDecl = auto *MapperVarDecl =
cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
- SourceLocation Loc = D->getLocation();
CharUnits ElementSize = C.getTypeSizeInChars(Ty); CharUnits ElementSize = C.getTypeSizeInChars(Ty);
llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMem(Ty); llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMem(Ty);
- // Prepare mapper function arguments and attributes.+ CodeGenFunction MapperCGF(CGM);
- ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,+ MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
- C.VoidPtrTy, ImplicitParamKind::Other);+ auto PrivatizeAndGenMapInfoCB =
- ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,+ [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
- ImplicitParamKind::Other);+ llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
- ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,+ MapperCGF.Builder.restoreIP(CodeGenIP);
- C.VoidPtrTy, ImplicitParamKind::Other);+
- ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,+ // Privatize the declared variable of mapper to be the current array
- ImplicitParamKind::Other);+ // element.
- ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,+ Address PtrCurrent(
- ImplicitParamKind::Other);+ PtrPHI, ElemTy,
- ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,+ Address(BeginArg, MapperCGF.VoidPtrTy, CGM.getPointerAlign())
- ImplicitParamKind::Other);+ .getAlignment()
- FunctionArgList Args;+ .alignmentOfArrayElement(ElementSize));
- Args.push_back(&HandleArg);+ CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
- Args.push_back(&BaseArg);+ Scope.addPrivate(MapperVarDecl, PtrCurrent);
- Args.push_back(&BeginArg);+ (void)Scope.Privatize();
- Args.push_back(&SizeArg);+
- Args.push_back(&TypeArg);+ // Get map clause information.
- Args.push_back(&NameArg);+ MappableExprsHandler MEHandler(*D, MapperCGF);
- const CGFunctionInfo &FnInfo =+ MEHandler.generateAllInfoForMapper(CombinedInfo, OMPBuilder);
- CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);+
- llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);+ auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
+ return emitMappingInformation(MapperCGF, OMPBuilder, MapExpr);
+ };
+ if (CGM.getCodeGenOpts().getDebugInfo() !=
+ llvm::codegenoptions::NoDebugInfo) {
+ CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
+ llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
+ FillInfoMap);
+ }
+
+ return CombinedInfo;
+ };
+
+ auto CustomMapperCB = [&](unsigned I, llvm::Function **MapperFunc) {
+ if (CombinedInfo.Mappers[I]) {
+ // Call the corresponding mapper function.
+ *MapperFunc = getOrCreateUserDefinedMapperFunc(
+ cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
+ assert(*MapperFunc && "Expect a valid mapper function is available.");
+ return true;
+ }
+ return false;
+ };
+
SmallString<64> TyStr; SmallString<64> TyStr;
llvm::raw_svector_ostream Out(TyStr); llvm::raw_svector_ostream Out(TyStr);
CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out); CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
std::string Name = getName({"omp_mapper", TyStr, D->getName()}); std::string Name = getName({"omp_mapper", TyStr, D->getName()});
- auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
- Name, &CGM.getModule());
- CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
- Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
- // Start the mapper function code generation.
- CodeGenFunction MapperCGF(CGM);
- MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
- // Compute the starting and end addresses of array elements.
- llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
- C.getPointerType(Int64Ty), Loc);
- // Prepare common arguments for array initiation and deletion.
- llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&HandleArg),
- /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
- llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&BaseArg),
- /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
- llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&BeginArg),
- /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
- // Convert the size in bytes into the number of array elements.
- Size = MapperCGF.Builder.CreateExactUDiv(
- Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
- llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
- BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy));
- llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(ElemTy, PtrBegin, Size);
- llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
- C.getPointerType(Int64Ty), Loc);
- llvm::Value *MapName = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&NameArg),
- /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
-
- // Emit array initiation if this is an array section and \p MapType indicates
- // that memory allocation is required.
- llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
- emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
- MapName, ElementSize, HeadBB, /*IsInit=*/true);
-
- // Emit a for loop to iterate through SizeArg of elements and map all of them.
-
- // Emit the loop header block.
- MapperCGF.EmitBlock(HeadBB);
- llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
- llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
- // Evaluate whether the initial condition is satisfied.
- llvm::Value *IsEmpty =
- MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
- MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
- llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
-
- // Emit the loop body block.
- MapperCGF.EmitBlock(BodyBB);
- llvm::BasicBlock *LastBB = BodyBB;
- llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
- PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
- PtrPHI->addIncoming(PtrBegin, EntryBB);
- Address PtrCurrent(PtrPHI, ElemTy,
- MapperCGF.GetAddrOfLocalVar(&BeginArg)
- .getAlignment()
- .alignmentOfArrayElement(ElementSize));
- // Privatize the declared variable of mapper to be the current array element.
- CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
- Scope.addPrivate(MapperVarDecl, PtrCurrent);
- (void)Scope.Privatize();
- // Get map clause information. Fill up the arrays with all mapped variables.+ auto *NewFn = OMPBuilder.emitUserDefinedMapper(PrivatizeAndGenMapInfoCB,
- MappableExprsHandler::MapCombinedInfoTy Info;+ ElemTy, Name, CustomMapperCB);
- MappableExprsHandler MEHandler(*D, MapperCGF);+ UDMMap.try_emplace(D, NewFn);
- MEHandler.generateAllInfoForMapper(Info, OMPBuilder);
-
- // Call the runtime API __tgt_mapper_num_components to get the number of
- // pre-existing components.
- llvm::Value *OffloadingArgs[] = {Handle};
- llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
- OMPRTL___tgt_mapper_num_components),
- OffloadingArgs);
- llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
- PreviousSize,
- MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
-
- // Fill up the runtime mapper handle for all components.
- for (unsigned I = 0; I < Info.BasePointers.size(); ++I) {
- llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
- Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
- llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
- Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
- llvm::Value *CurSizeArg = Info.Sizes[I];
- llvm::Value *CurNameArg =
- (CGM.getCodeGenOpts().getDebugInfo() ==
- llvm::codegenoptions::NoDebugInfo)
- ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy)
- : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]);
-
- // Extract the MEMBER_OF field from the map type.
- llvm::Value *OriMapType = MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- Info.Types[I]));
- llvm::Value *MemberMapType =
- MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
-
- // Combine the map type inherited from user-defined mapper with that
- // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
- // bits of the \a MapType, which is the input argument of the mapper
- // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
- // bits of MemberMapType.
- // [OpenMP 5.0], 1.2.6. map-type decay.
- // | alloc | to | from | tofrom | release | delete
- // ----------------------------------------------------------
- // alloc | alloc | alloc | alloc | alloc | release | delete
- // to | alloc | to | alloc | to | release | delete
- // from | alloc | alloc | from | from | release | delete
- // tofrom | alloc | to | from | tofrom | release | delete
- llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
- MapType,
- MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_TO |
- OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
- llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
- llvm::BasicBlock *AllocElseBB =
- MapperCGF.createBasicBlock("omp.type.alloc.else");
- llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
- llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
- llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
- llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
- llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
- MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
- // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
- MapperCGF.EmitBlock(AllocBB);
- llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
- MemberMapType,
- MapperCGF.Builder.getInt64(
- ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_TO |
- OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
- MapperCGF.Builder.CreateBr(EndBB);
- MapperCGF.EmitBlock(AllocElseBB);
- llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
- LeftToFrom,
- MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_TO)));
- MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
- // In case of to, clear OMP_MAP_FROM.
- MapperCGF.EmitBlock(ToBB);
- llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
- MemberMapType,
- MapperCGF.Builder.getInt64(
- ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
- MapperCGF.Builder.CreateBr(EndBB);
- MapperCGF.EmitBlock(ToElseBB);
- llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
- LeftToFrom,
- MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
- MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
- // In case of from, clear OMP_MAP_TO.
- MapperCGF.EmitBlock(FromBB);
- llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
- MemberMapType,
- MapperCGF.Builder.getInt64(
- ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_TO)));
- // In case of tofrom, do nothing.
- MapperCGF.EmitBlock(EndBB);
- LastBB = EndBB;
- llvm::PHINode *CurMapType =
- MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
- CurMapType->addIncoming(AllocMapType, AllocBB);
- CurMapType->addIncoming(ToMapType, ToBB);
- CurMapType->addIncoming(FromMapType, FromBB);
- CurMapType->addIncoming(MemberMapType, ToElseBB);
-
- llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
- CurSizeArg, CurMapType, CurNameArg};
- if (Info.Mappers[I]) {
- // Call the corresponding mapper function.
- llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc(
- cast<OMPDeclareMapperDecl>(Info.Mappers[I]));
- assert(MapperFunc && "Expect a valid mapper function is available.");
- MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs);
- } else {
- // Call the runtime API __tgt_push_mapper_component to fill up the runtime
- // data structure.
- MapperCGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___tgt_push_mapper_component),
- OffloadingArgs);
- }
- }
-
- // Update the pointer to point to the next element that needs to be mapped,
- // and check whether we have mapped all elements.
- llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
- ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
- PtrPHI->addIncoming(PtrNext, LastBB);
- llvm::Value *IsDone =
- MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
- llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
- MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
-
- MapperCGF.EmitBlock(ExitBB);
- // Emit array deletion if this is an array section and \p MapType indicates
- // that deletion is required.
- emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
- MapName, ElementSize, DoneBB, /*IsInit=*/false);
-
- // Emit the function exit block.
- MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
- MapperCGF.FinishFunction();
- UDMMap.try_emplace(D, Fn);
if (CGF) if (CGF)
FunctionUDMMap[CGF->CurFn].push_back(D); FunctionUDMMap[CGF->CurFn].push_back(D);
} }
-/// Emit the array initialization or deletion portion for user-defined mapper
-/// code generation. First, it evaluates whether an array section is mapped and
-/// whether the \a MapType instructs to delete this section. If \a IsInit is
-/// true, and \a MapType indicates to not delete this array, array
-/// initialization code is generated. If \a IsInit is false, and \a MapType
-/// indicates to not this array, array deletion code is generated.
-void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
- CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
- llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
- llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB,
- bool IsInit) {
- StringRef Prefix = IsInit ? ".init" : ".del";
-
- // Evaluate if this is an array section.
- llvm::BasicBlock *BodyBB =
- MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
- llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT(
- Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
- llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
- MapType,
- MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
- llvm::Value *DeleteCond;
- llvm::Value *Cond;
- if (IsInit) {
- // base != begin?
- llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateICmpNE(Base, Begin);
- // IsPtrAndObj?
- llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd(
- MapType,
- MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ)));
- PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit);
- BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit);
- Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin);
- DeleteCond = MapperCGF.Builder.CreateIsNull(
- DeleteBit, getName({"omp.array", Prefix, ".delete"}));
- } else {
- Cond = IsArray;
- DeleteCond = MapperCGF.Builder.CreateIsNotNull(
- DeleteBit, getName({"omp.array", Prefix, ".delete"}));
- }
- Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond);
- MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB);
-
- MapperCGF.EmitBlock(BodyBB);
- // Get the array size by multiplying element size and element number (i.e., \p
- // Size).
- llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
- Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
- // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
- // memory allocation/deletion purpose only.
- llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
- MapType,
- MapperCGF.Builder.getInt64(
- ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_TO |
- OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
- MapTypeArg = MapperCGF.Builder.CreateOr(
- MapTypeArg,
- MapperCGF.Builder.getInt64(
- static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
- OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
-
- // Call the runtime API __tgt_push_mapper_component to fill up the runtime
- // data structure.
- llvm::Value *OffloadingArgs[] = {Handle, Base, Begin,
- ArraySize, MapTypeArg, MapName};
- MapperCGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
- OMPRTL___tgt_push_mapper_component),
- OffloadingArgs);
-}
-
llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc(
const OMPDeclareMapperDecl *D) { const OMPDeclareMapperDecl *D) {
auto I = UDMMap.find(D); auto I = UDMMap.find(D);
clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -559,15 +559,6 @@ protected:
llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Ctor, llvm::Value *CopyCtor,
llvm::Value *Dtor, SourceLocation Loc); llvm::Value *Dtor, SourceLocation Loc);
- /// Emit the array initialization or deletion portion for user-defined mapper
- /// code generation.
- void emitUDMapperArrayInitOrDel(CodeGenFunction &MapperCGF,
- llvm::Value *Handle, llvm::Value *BasePtr,
- llvm::Value *Ptr, llvm::Value *Size,
- llvm::Value *MapType, llvm::Value *MapName,
- CharUnits ElementSize,
- llvm::BasicBlock *ExitBB, bool IsInit);
-
struct TaskResultTy { struct TaskResultTy {
llvm::Value *NewTask = nullptr; llvm::Value *NewTask = nullptr;
llvm::Function *TaskEntry = nullptr; llvm::Function *TaskEntry = nullptr;
clang/lib/CodeGen/CodeGenFunction.cpp
@@ -837,6 +837,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
if (SanOpts.has(SanitizerKind::Thread)) if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread); Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+ if (SanOpts.has(SanitizerKind::Type))
+ Fn->addFnAttr(llvm::Attribute::SanitizeType);
if (SanOpts.has(SanitizerKind::NumericalStability)) if (SanOpts.has(SanitizerKind::NumericalStability))
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability); Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
clang/lib/CodeGen/CodeGenModule.cpp
@@ -397,8 +397,8 @@ CodeGenModule::CodeGenModule(ASTContext &C,
if (LangOpts.HLSL) if (LangOpts.HLSL)
createHLSLRuntime(); createHLSLRuntime();
- // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.+ // Enable TBAA unless it's suppressed. TSan and TySan need TBAA even at O0.
- if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||+ if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0)) (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts, TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts,
getLangOpts())); getLangOpts()));
@@ -1218,6 +1218,9 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1); getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1);
if (getTriple().isOSLinux()) { if (getTriple().isOSLinux()) {
+ if (LangOpts.PointerAuthCalls)
+ getModule().addModuleFlag(llvm::Module::Min, "ptrauth-sign-personality",
+ 1);
assert(getTriple().isOSBinFormatELF()); assert(getTriple().isOSBinFormatELF());
using namespace llvm::ELF; using namespace llvm::ELF;
uint64_t PAuthABIVersion = uint64_t PAuthABIVersion =
clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -314,8 +314,10 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
} }
llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) { llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
- // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.+ // At -O0 or relaxed aliasing, TBAA is not emitted for regular types (unless
- if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)+ // we're running TypeSanitizer).
+ if (!Features.Sanitize.has(SanitizerKind::Type) &&
+ (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing))
return nullptr; return nullptr;
// If the type has the may_alias attribute (even on a typedef), it is // If the type has the may_alias attribute (even on a typedef), it is
clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2370,8 +2370,7 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
} else { } else {
Ctx.dump(R.Count, OS); Ctx.dump(R.Count, OS);
- if (R.Kind == CounterMappingRegion::BranchRegion ||+ if (R.isBranch()) {
- R.Kind == CounterMappingRegion::MCDCBranchRegion) {
OS << ", "; OS << ", ";
Ctx.dump(R.FalseCount, OS); Ctx.dump(R.FalseCount, OS);
} }
clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3302,6 +3302,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
CharUnits Align = CGM.getContext().getDeclAlign(VD); CharUnits Align = CGM.getContext().getDeclAlign(VD);
Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align); Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
} }
+ Val = Builder.CreateAddrSpaceCast(Val, Wrapper->getReturnType());
Builder.CreateRet(Val); Builder.CreateRet(Val);
} }
clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -3454,7 +3454,7 @@ llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
if (inheritanceModelHasOnlyOneField(IsFunc, DstInheritance)) { if (inheritanceModelHasOnlyOneField(IsFunc, DstInheritance)) {
Dst = FirstField; Dst = FirstField;
} else { } else {
- Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy));+ Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy));
unsigned Idx = 0; unsigned Idx = 0;
Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++); Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
if (inheritanceModelHasNVOffsetField(IsFunc, DstInheritance)) if (inheritanceModelHasNVOffsetField(IsFunc, DstInheritance))
clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -19,9 +19,10 @@ using namespace CodeGen;
SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
-static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) {+static bool isAsanHwasanMemTagOrTysan(const SanitizerSet &SS) {
return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress |
- SanitizerKind::HWAddress | SanitizerKind::MemTag);+ SanitizerKind::HWAddress | SanitizerKind::MemTag |
+ SanitizerKind::Type);
} }
static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) { static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) {
@@ -31,13 +32,44 @@ static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) {
return Mask; return Mask;
} }
+static bool shouldTagGlobal(const llvm::GlobalVariable &G) {
+ // For now, don't instrument constant data, as it'll be in .rodata anyway. It
+ // may be worth instrumenting these in future to stop them from being used as
+ // gadgets.
+ if (G.getName().starts_with("llvm.") || G.isThreadLocal() || G.isConstant())
+ return false;
+
+ // Globals can be placed implicitly or explicitly in sections. There's two
+ // different types of globals that meet this criteria that cause problems:
+ // 1. Function pointers that are going into various init arrays (either
+ // explicitly through `__attribute__((section(<foo>)))` or implicitly
+ // through `__attribute__((constructor)))`, such as ".(pre)init(_array)",
+ // ".fini(_array)", ".ctors", and ".dtors". These function pointers end up
+ // overaligned and overpadded, making iterating over them problematic, and
+ // each function pointer is individually tagged (so the iteration over
+ // them causes SIGSEGV/MTE[AS]ERR).
+ // 2. Global variables put into an explicit section, where the section's name
+ // is a valid C-style identifier. The linker emits a `__start_<name>` and
+ // `__stop_<name>` symbol for the section, so that you can iterate over
+ // globals within this section. Unfortunately, again, these globals would
+ // be tagged and so iteration causes SIGSEGV/MTE[AS]ERR.
+ //
+ // To mitigate both these cases, and because specifying a section is rare
+ // outside of these two cases, disable MTE protection for globals in any
+ // section.
+ if (G.hasSection())
+ return false;
+
+ return true;
+}
+
void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
SourceLocation Loc, StringRef Name, SourceLocation Loc, StringRef Name,
QualType Ty, QualType Ty,
SanitizerMask NoSanitizeAttrMask, SanitizerMask NoSanitizeAttrMask,
bool IsDynInit) { bool IsDynInit) {
SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize; SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize;
- if (!isAsanHwasanOrMemTag(FsanitizeArgument))+ if (!isAsanHwasanMemTagOrTysan(FsanitizeArgument))
return; return;
FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask); FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask);
@@ -57,11 +89,15 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
Meta.NoHWAddress |= CGM.isInNoSanitizeList( Meta.NoHWAddress |= CGM.isInNoSanitizeList(
FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty); FsanitizeArgument.Mask & SanitizerKind::HWAddress, GV, Loc, Ty);
- Meta.Memtag |=+ if (shouldTagGlobal(*GV)) {
- static_cast<bool>(FsanitizeArgument.Mask & SanitizerKind::MemtagGlobals);+ Meta.Memtag |= static_cast<bool>(FsanitizeArgument.Mask &
- Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);+ SanitizerKind::MemtagGlobals);
- Meta.Memtag &= !CGM.isInNoSanitizeList(+ Meta.Memtag &= !NoSanitizeAttrSet.hasOneOf(SanitizerKind::MemTag);
- FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);+ Meta.Memtag &= !CGM.isInNoSanitizeList(
+ FsanitizeArgument.Mask & SanitizerKind::MemTag, GV, Loc, Ty);
+ } else {
+ Meta.Memtag = false;
+ }
Meta.IsDynInit = IsDynInit && !Meta.NoAddress && Meta.IsDynInit = IsDynInit && !Meta.NoAddress &&
FsanitizeArgument.has(SanitizerKind::Address) && FsanitizeArgument.has(SanitizerKind::Address) &&
@@ -70,11 +106,32 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
GV, Loc, Ty, "init"); GV, Loc, Ty, "init");
GV->setSanitizerMetadata(Meta); GV->setSanitizerMetadata(Meta);
+
+ if (Ty.isNull() || !CGM.getLangOpts().Sanitize.has(SanitizerKind::Type) ||
+ NoSanitizeAttrMask & SanitizerKind::Type)
+ return;
+
+ llvm::MDNode *TBAAInfo = CGM.getTBAATypeInfo(Ty);
+ if (!TBAAInfo || TBAAInfo == CGM.getTBAATypeInfo(CGM.getContext().CharTy))
+ return;
+
+ llvm::Metadata *GlobalMetadata[] = {llvm::ConstantAsMetadata::get(GV),
+ TBAAInfo};
+
+ // Metadata for the global already registered.
+ if (llvm::MDNode::getIfExists(CGM.getLLVMContext(), GlobalMetadata))
+ return;
+
+ llvm::MDNode *ThisGlobal =
+ llvm::MDNode::get(CGM.getLLVMContext(), GlobalMetadata);
+ llvm::NamedMDNode *TysanGlobals =
+ CGM.getModule().getOrInsertNamedMetadata("llvm.tysan.globals");
+ TysanGlobals->addOperand(ThisGlobal);
} }
void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D,
bool IsDynInit) { bool IsDynInit) {
- if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))+ if (!isAsanHwasanMemTagOrTysan(CGM.getLangOpts().Sanitize))
return; return;
std::string QualName; std::string QualName;
llvm::raw_string_ostream OS(QualName); llvm::raw_string_ostream OS(QualName);
clang/lib/Driver/SanitizerArgs.cpp
@@ -37,15 +37,15 @@ static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;
static const SanitizerMask NotAllowedWithExecuteOnly = static const SanitizerMask NotAllowedWithExecuteOnly =
SanitizerKind::Function | SanitizerKind::KCFI; SanitizerKind::Function | SanitizerKind::KCFI;
static const SanitizerMask NeedsUnwindTables = static const SanitizerMask NeedsUnwindTables =
- SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |+ SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |
- SanitizerKind::Memory | SanitizerKind::DataFlow |+ SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |
SanitizerKind::NumericalStability; SanitizerKind::NumericalStability;
static const SanitizerMask SupportsCoverage = static const SanitizerMask SupportsCoverage =
SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Address | SanitizerKind::HWAddress |
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress | SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
- SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |+ SanitizerKind::Type | SanitizerKind::MemtagStack |
- SanitizerKind::MemtagGlobals | SanitizerKind::Memory |+ SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |
- SanitizerKind::KernelMemory | SanitizerKind::Leak |+ SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds | SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
SanitizerKind::DataFlow | SanitizerKind::Fuzzer | SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
@@ -182,6 +182,7 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
{"msan_ignorelist.txt", SanitizerKind::Memory}, {"msan_ignorelist.txt", SanitizerKind::Memory},
{"nsan_ignorelist.txt", SanitizerKind::NumericalStability}, {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
{"tsan_ignorelist.txt", SanitizerKind::Thread}, {"tsan_ignorelist.txt", SanitizerKind::Thread},
+ {"tysan_blacklist.txt", SanitizerKind::Type},
{"dfsan_abilist.txt", SanitizerKind::DataFlow}, {"dfsan_abilist.txt", SanitizerKind::DataFlow},
{"cfi_ignorelist.txt", SanitizerKind::CFI}, {"cfi_ignorelist.txt", SanitizerKind::CFI},
{"ubsan_ignorelist.txt", {"ubsan_ignorelist.txt",
@@ -247,48 +248,76 @@ static SanitizerMask setGroupBits(SanitizerMask Kinds) {
return Kinds; return Kinds;
} }
-// Computes the sanitizer mask based on the default plus opt-in (if supported)+// Computes the sanitizer mask as:
-// minus opt-out.+// Default + Arguments (in or out)
+// with arguments parsed from left to right.
+//
+// Error messages are printed if the AlwaysIn or AlwaysOut invariants are
+// violated, but the caller must enforce these invariants themselves.
static SanitizerMask static SanitizerMask
parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args, parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args,
- bool DiagnoseErrors, SanitizerMask Supported,+ bool DiagnoseErrors, SanitizerMask Default,
- SanitizerMask Default, int OptInID, int OptOutID) {+ SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID,
- SanitizerMask Remove; // During the loop below, the accumulated set of+ int OptOutID) {
- // sanitizers disabled by the current sanitizer+ assert(!(AlwaysIn & AlwaysOut) &&
- // argument or any argument after it.+ "parseSanitizeArgs called with contradictory in/out requirements");
- SanitizerMask Kinds;+
- SanitizerMask SupportedWithGroups = setGroupBits(Supported);+ SanitizerMask Output = Default;
-+ // Keep track of which violations we have already reported, to avoid
- for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {+ // duplicate error messages.
+ SanitizerMask DiagnosedAlwaysInViolations;
+ SanitizerMask DiagnosedAlwaysOutViolations;
+ for (const auto *Arg : Args) {
if (Arg->getOption().matches(OptInID)) { if (Arg->getOption().matches(OptInID)) {
- Arg->claim();+ SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
- SanitizerMask Add = parseArgValues(D, Arg, true);+ // Report error if user explicitly tries to opt-in to an always-out
- Add &= ~Remove;+ // sanitizer.
- SanitizerMask InvalidValues = Add & ~SupportedWithGroups;+ if (SanitizerMask KindsToDiagnose =
- if (InvalidValues && DiagnoseErrors) {+ Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {
- SanitizerSet S;+ if (DiagnoseErrors) {
- S.Mask = InvalidValues;+ SanitizerSet SetToDiagnose;
- D.Diag(diag::err_drv_unsupported_option_argument)+ SetToDiagnose.Mask |= KindsToDiagnose;
- << Arg->getSpelling() << toString(S);+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getSpelling() << toString(SetToDiagnose);
+ DiagnosedAlwaysOutViolations |= KindsToDiagnose;
+ }
} }
- Kinds |= expandSanitizerGroups(Add) & ~Remove;+ Output |= expandSanitizerGroups(Add);
+ Arg->claim();
} else if (Arg->getOption().matches(OptOutID)) { } else if (Arg->getOption().matches(OptOutID)) {
+ SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
+ // Report error if user explicitly tries to opt-out of an always-in
+ // sanitizer.
+ if (SanitizerMask KindsToDiagnose =
+ Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {
+ if (DiagnoseErrors) {
+ SanitizerSet SetToDiagnose;
+ SetToDiagnose.Mask |= KindsToDiagnose;
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getSpelling() << toString(SetToDiagnose);
+ DiagnosedAlwaysInViolations |= KindsToDiagnose;
+ }
+ }
+ Output &= ~expandSanitizerGroups(Remove);
Arg->claim(); Arg->claim();
- Remove |= expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));
} }
} }
- // Apply default behavior.+ return Output;
- Kinds |= Default & ~Remove;
-
- return Kinds;
} }
static SanitizerMask parseSanitizeTrapArgs(const Driver &D, static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
const llvm::opt::ArgList &Args, const llvm::opt::ArgList &Args,
bool DiagnoseErrors) { bool DiagnoseErrors) {
- return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingSupported,+ SanitizerMask AlwaysTrap; // Empty
- TrappingDefault, options::OPT_fsanitize_trap_EQ,+ SanitizerMask NeverTrap = ~(setGroupBits(TrappingSupported));
+
+ // N.B. We do *not* enforce NeverTrap. This maintains the behavior of
+ // '-fsanitize=undefined -fsanitize-trap=undefined'
+ // (clang/test/Driver/fsanitize.c ), which is that vptr is not enabled at all
+ // (not even in recover mode) in order to avoid the need for a ubsan runtime.
+ return parseSanitizeArgs(D, Args, DiagnoseErrors, TrappingDefault, AlwaysTrap,
+ NeverTrap, options::OPT_fsanitize_trap_EQ,
options::OPT_fno_sanitize_trap_EQ); options::OPT_fno_sanitize_trap_EQ);
} }
@@ -542,6 +571,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = { std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
std::make_pair(SanitizerKind::Address, std::make_pair(SanitizerKind::Address,
SanitizerKind::Thread | SanitizerKind::Memory), SanitizerKind::Thread | SanitizerKind::Memory),
+ std::make_pair(SanitizerKind::Type,
+ SanitizerKind::Address | SanitizerKind::KernelAddress |
+ SanitizerKind::Memory | SanitizerKind::Leak |
+ SanitizerKind::Thread | SanitizerKind::KernelAddress),
std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory), std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),
std::make_pair(SanitizerKind::Leak, std::make_pair(SanitizerKind::Leak,
SanitizerKind::Thread | SanitizerKind::Memory), SanitizerKind::Thread | SanitizerKind::Memory),
@@ -652,44 +685,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// default in ASan? // default in ASan?
// Parse -f(no-)?sanitize-recover flags. // Parse -f(no-)?sanitize-recover flags.
- SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;+ SanitizerMask RecoverableKinds = parseSanitizeArgs(
- SanitizerMask DiagnosedUnrecoverableKinds;+ D, Args, DiagnoseErrors, RecoverableByDefault, AlwaysRecoverable,
- SanitizerMask DiagnosedAlwaysRecoverableKinds;+ Unrecoverable, options::OPT_fsanitize_recover_EQ,
- for (const auto *Arg : Args) {+ options::OPT_fno_sanitize_recover_EQ);
- if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {+ RecoverableKinds |= AlwaysRecoverable;
- SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);
- // Report error if user explicitly tries to recover from unrecoverable
- // sanitizer.
- if (SanitizerMask KindsToDiagnose =
- Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
- SanitizerSet SetToDiagnose;
- SetToDiagnose.Mask |= KindsToDiagnose;
- if (DiagnoseErrors)
- D.Diag(diag::err_drv_unsupported_option_argument)
- << Arg->getSpelling() << toString(SetToDiagnose);
- DiagnosedUnrecoverableKinds |= KindsToDiagnose;
- }
- RecoverableKinds |= expandSanitizerGroups(Add);
- Arg->claim();
- } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
- SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);
- // Report error if user explicitly tries to disable recovery from
- // always recoverable sanitizer.
- if (SanitizerMask KindsToDiagnose =
- Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {
- SanitizerSet SetToDiagnose;
- SetToDiagnose.Mask |= KindsToDiagnose;
- if (DiagnoseErrors)
- D.Diag(diag::err_drv_unsupported_option_argument)
- << Arg->getSpelling() << toString(SetToDiagnose);
- DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;
- }
- RecoverableKinds &= ~expandSanitizerGroups(Remove);
- Arg->claim();
- }
- }
- RecoverableKinds &= Kinds;
RecoverableKinds &= ~Unrecoverable; RecoverableKinds &= ~Unrecoverable;
+ RecoverableKinds &= Kinds;
TrappingKinds &= Kinds; TrappingKinds &= Kinds;
RecoverableKinds &= ~TrappingKinds; RecoverableKinds &= ~TrappingKinds;
@@ -1096,10 +1098,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fno_sanitize_link_runtime, LinkRuntimes); options::OPT_fno_sanitize_link_runtime, LinkRuntimes);
// Parse -link-cxx-sanitizer flag. // Parse -link-cxx-sanitizer flag.
- LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,+ LinkCXXRuntimes =
- options::OPT_fno_sanitize_link_cxx_runtime,+ D.CCCIsCXX() && !Args.hasArg(clang::driver::options::OPT_nostdlibxx);
- LinkCXXRuntimes) ||+ LinkCXXRuntimes =
- D.CCCIsCXX();+ Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,
+ options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);
NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile, NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,
options::OPT_fmemory_profile_EQ, options::OPT_fmemory_profile_EQ,
clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1417,7 +1417,6 @@ void tools::addAsNeededOption(const ToolChain &TC,
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
const llvm::opt::ArgList &Args, const llvm::opt::ArgList &Args,
- const SanitizerArgs &SanArgs,
ArgStringList &CmdArgs) { ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on // Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary). // (see PR15823 why this is necessary).
@@ -1444,18 +1443,18 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
// libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv
// requirement. // requirement.
if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() && if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
- !TC.getTriple().isMusl() && SanArgs.needsMsanRt())+ !TC.getTriple().isMusl())
CmdArgs.push_back("-lresolv"); CmdArgs.push_back("-lresolv");
} }
static void static void
collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
- const SanitizerArgs &SanArgs,
SmallVectorImpl<StringRef> &SharedRuntimes, SmallVectorImpl<StringRef> &SharedRuntimes,
SmallVectorImpl<StringRef> &StaticRuntimes, SmallVectorImpl<StringRef> &StaticRuntimes,
SmallVectorImpl<StringRef> &NonWholeStaticRuntimes, SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
SmallVectorImpl<StringRef> &HelperStaticRuntimes, SmallVectorImpl<StringRef> &HelperStaticRuntimes,
SmallVectorImpl<StringRef> &RequiredSymbols) { SmallVectorImpl<StringRef> &RequiredSymbols) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
// Collect shared runtimes. // Collect shared runtimes.
if (SanArgs.needsSharedRt()) { if (SanArgs.needsSharedRt()) {
if (SanArgs.needsAsanRt()) { if (SanArgs.needsAsanRt()) {
@@ -1481,6 +1480,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
} }
if (SanArgs.needsTsanRt()) if (SanArgs.needsTsanRt())
SharedRuntimes.push_back("tsan"); SharedRuntimes.push_back("tsan");
+ if (SanArgs.needsTysanRt())
+ SharedRuntimes.push_back("tysan");
if (SanArgs.needsHwasanRt()) { if (SanArgs.needsHwasanRt()) {
if (SanArgs.needsHwasanAliasesRt()) if (SanArgs.needsHwasanAliasesRt())
SharedRuntimes.push_back("hwasan_aliases"); SharedRuntimes.push_back("hwasan_aliases");
@@ -1553,6 +1554,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.linkCXXRuntimes()) if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("tsan_cxx"); StaticRuntimes.push_back("tsan_cxx");
} }
+ if (!SanArgs.needsSharedRt() && SanArgs.needsTysanRt())
+ StaticRuntimes.push_back("tysan");
if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) { if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) {
if (SanArgs.requiresMinimalRuntime()) { if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("ubsan_minimal"); StaticRuntimes.push_back("ubsan_minimal");
@@ -1589,12 +1592,12 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++, // Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in. // C runtime, etc). Returns true if sanitizer system deps need to be linked in.
bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
- const SanitizerArgs &SanArgs,
ArgStringList &CmdArgs) { ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols; NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
if (SanArgs.linkRuntimes()) { if (SanArgs.linkRuntimes()) {
- collectSanitizerRuntimes(TC, Args, SanArgs, SharedRuntimes, StaticRuntimes,+ collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
NonWholeStaticRuntimes, HelperStaticRuntimes, NonWholeStaticRuntimes, HelperStaticRuntimes,
RequiredSymbols); RequiredSymbols);
} }
clang/lib/Driver/ToolChains/CommonArgs.h
@@ -38,12 +38,10 @@ void addLinkerCompressDebugSectionsOption(const ToolChain &TC,
void claimNoWarnArgs(const llvm::opt::ArgList &Args); void claimNoWarnArgs(const llvm::opt::ArgList &Args);
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args, bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
- const SanitizerArgs &SanArgs,
llvm::opt::ArgStringList &CmdArgs); llvm::opt::ArgStringList &CmdArgs);
void linkSanitizerRuntimeDeps(const ToolChain &TC, void linkSanitizerRuntimeDeps(const ToolChain &TC,
const llvm::opt::ArgList &Args, const llvm::opt::ArgList &Args,
- const SanitizerArgs &SanArgs,
llvm::opt::ArgStringList &CmdArgs); llvm::opt::ArgStringList &CmdArgs);
bool addXRayRuntime(const ToolChain &TC, const llvm::opt::ArgList &Args, bool addXRayRuntime(const ToolChain &TC, const llvm::opt::ArgList &Args,
clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1600,6 +1600,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
"Static sanitizer runtimes not supported"); "Static sanitizer runtimes not supported");
AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
} }
+ if (Sanitize.needsTysanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "tysan");
if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false); AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
@@ -3603,6 +3605,10 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::Thread; Res |= SanitizerKind::Thread;
} }
+ if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {
+ Res |= SanitizerKind::Type;
+ }
+
if (IsX86_64) if (IsX86_64)
Res |= SanitizerKind::NumericalStability; Res |= SanitizerKind::NumericalStability;
clang/lib/Driver/ToolChains/Flang.cpp
@@ -55,7 +55,9 @@ void Flang::addFortranDialectOptions(const ArgList &Args,
options::OPT_fdefault_double_8, options::OPT_fdefault_double_8,
options::OPT_flarge_sizes, options::OPT_flarge_sizes,
options::OPT_fno_automatic, options::OPT_fno_automatic,
- options::OPT_fhermetic_module_files});+ options::OPT_fhermetic_module_files,
+ options::OPT_frealloc_lhs,
+ options::OPT_fno_realloc_lhs});
} }
void Flang::addPreprocessingOptions(const ArgList &Args, void Flang::addPreprocessingOptions(const ArgList &Args,
@@ -120,7 +122,8 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
options::OPT_fintrinsic_modules_path, options::OPT_pedantic, options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
options::OPT_std_EQ, options::OPT_W_Joined, options::OPT_std_EQ, options::OPT_W_Joined,
options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ, options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ,
- options::OPT_funderscoring, options::OPT_fno_underscoring});+ options::OPT_funderscoring, options::OPT_fno_underscoring,
+ options::OPT_funsigned, options::OPT_fno_unsigned});
llvm::codegenoptions::DebugInfoKind DebugInfoKind; llvm::codegenoptions::DebugInfoKind DebugInfoKind;
if (Args.hasArg(options::OPT_gN_Group)) { if (Args.hasArg(options::OPT_gN_Group)) {
clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -297,9 +297,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.getLTOMode() == LTOK_Thin); D.getLTOMode() == LTOK_Thin);
} }
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsSanitizerDeps =
- addSanitizerRuntimes(ToolChain, Args, SanArgs, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -340,7 +338,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
} }
if (NeedsSanitizerDeps) if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, Args, SanArgs, CmdArgs);+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps) if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs); linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -184,8 +184,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Note that Fuchsia never needs to link in sanitizer runtime deps. Any // Note that Fuchsia never needs to link in sanitizer runtime deps. Any
// sanitizer runtimes with system dependencies use the `.deplibs` feature // sanitizer runtimes with system dependencies use the `.deplibs` feature
// instead. // instead.
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);+ addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- addSanitizerRuntimes(ToolChain, Args, SanArgs, CmdArgs);
addXRayRuntime(ToolChain, Args, CmdArgs); addXRayRuntime(ToolChain, Args, CmdArgs);
@@ -318,9 +317,10 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true); Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true);
addMultilibFlag(Exceptions, "-fexceptions", Flags); addMultilibFlag(Exceptions, "-fexceptions", Flags);
addMultilibFlag(!Exceptions, "-fno-exceptions", Flags); addMultilibFlag(!Exceptions, "-fno-exceptions", Flags);
- const SanitizerArgs &SanArgs = getSanitizerArgs(Args);+ addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "-fsanitize=address",
- addMultilibFlag(SanArgs.needsAsanRt(), "-fsanitize=address", Flags);+ Flags);
- addMultilibFlag(SanArgs.needsHwasanRt(), "-fsanitize=hwaddress", Flags);+ addMultilibFlag(getSanitizerArgs(Args).needsHwasanRt(),
+ "-fsanitize=hwaddress", Flags);
addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium", addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium",
"-fc++-abi=itanium", Flags); "-fc++-abi=itanium", Flags);
clang/lib/Driver/ToolChains/Gnu.cpp
@@ -23,7 +23,6 @@
#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/MultilibBuilder.h" #include "clang/Driver/MultilibBuilder.h"
#include "clang/Driver/Options.h" #include "clang/Driver/Options.h"
-#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/Tool.h" #include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h" #include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSet.h"
@@ -539,9 +538,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle"); CmdArgs.push_back("--no-demangle");
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsSanitizerDeps =
- addSanitizerRuntimes(ToolChain, Args, SanArgs, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -586,7 +583,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--start-group"); CmdArgs.push_back("--start-group");
if (NeedsSanitizerDeps) if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, Args, SanArgs, CmdArgs);+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps) if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs); linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -13,7 +13,6 @@
#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h" #include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h" #include "clang/Driver/Options.h"
-#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/Option/ArgList.h" #include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
@@ -216,8 +215,7 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
"-mcpu=hexagon" + "-mcpu=hexagon" +
toolchains::HexagonToolChain::GetTargetCPUVersion(Args))); toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
- SanitizerArgs SanArgs = HTC.getSanitizerArgs(Args);+ addSanitizerRuntimes(HTC, Args, CmdArgs);
- addSanitizerRuntimes(HTC, Args, SanArgs, CmdArgs);
assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) { if (Output.isFilename()) {
@@ -303,8 +301,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
bool UseShared = IsShared && !IsStatic; bool UseShared = IsShared && !IsStatic;
StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args); StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
- const SanitizerArgs &SanArgs = HTC.getSanitizerArgs(Args);+ bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, SanArgs, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -374,7 +371,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (NeedsSanitizerDeps) { if (NeedsSanitizerDeps) {
- linkSanitizerRuntimeDeps(HTC, Args, SanArgs, CmdArgs);+ linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);
if (UNW != ToolChain::UNW_None) if (UNW != ToolChain::UNW_None)
CmdArgs.push_back("-lunwind"); CmdArgs.push_back("-lunwind");
clang/lib/Driver/ToolChains/Linux.cpp
@@ -837,6 +837,8 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ || if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
IsLoongArch64 || IsRISCV64) IsLoongArch64 || IsRISCV64)
Res |= SanitizerKind::Thread; Res |= SanitizerKind::Thread;
+ if (IsX86_64 || IsAArch64)
+ Res |= SanitizerKind::Type;
if (IsX86_64 || IsSystemZ || IsPowerPC64) if (IsX86_64 || IsSystemZ || IsPowerPC64)
Res |= SanitizerKind::KernelMemory; Res |= SanitizerKind::KernelMemory;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch || if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -274,12 +274,11 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_s, options::OPT_t}); options::OPT_s, options::OPT_t});
ToolChain.AddFilePathLibArgs(Args, CmdArgs); ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsSanitizerDeps =
- addSanitizerRuntimes(ToolChain, Args, SanArgs, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);
if (SanArgs.needsSharedRt()) { if (SanArgs.needsSharedRt()) {
CmdArgs.push_back("-rpath"); CmdArgs.push_back("-rpath");
CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath())); CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath()));
@@ -335,7 +334,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
} }
if (NeedsSanitizerDeps) if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, Args, SanArgs, CmdArgs);+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps) if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, Args, CmdArgs); linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
if (Args.hasArg(options::OPT_pthread)) if (Args.hasArg(options::OPT_pthread))
clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -213,9 +213,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.getLTOMode() == LTOK_Thin); D.getLTOMode() == LTOK_Thin);
} }
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsSanitizerDeps =
- addSanitizerRuntimes(ToolChain, Args, SanArgs, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -253,7 +251,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (NeedsSanitizerDeps) { if (NeedsSanitizerDeps) {
CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins")); CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
- linkSanitizerRuntimeDeps(ToolChain, Args, SanArgs, CmdArgs);+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
} }
if (NeedsXRayDeps) { if (NeedsXRayDeps) {
CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins")); CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
clang/lib/Driver/ToolChains/Solaris.cpp
@@ -203,8 +203,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group}); Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group});
- const SanitizerArgs &SA = ToolChain.getSanitizerArgs(Args);+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, SA, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
@@ -251,8 +250,9 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_shared)) { if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-lgcc"); CmdArgs.push_back("-lgcc");
} }
+ const SanitizerArgs &SA = ToolChain.getSanitizerArgs(Args);
if (NeedsSanitizerDeps) { if (NeedsSanitizerDeps) {
- linkSanitizerRuntimeDeps(ToolChain, Args, SA, CmdArgs);+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
// Work around Solaris/amd64 ld bug when calling __tls_get_addr directly. // Work around Solaris/amd64 ld bug when calling __tls_get_addr directly.
// However, ld -z relax=transtls is available since Solaris 11.2, but not // However, ld -z relax=transtls is available since Solaris 11.2, but not
clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -1067,9 +1067,8 @@ void SymbolGraphSerializer::serializeWithExtensionGraphs(
for (auto &ExtensionSGF : Serializer.ExtendedModules) { for (auto &ExtensionSGF : Serializer.ExtendedModules) {
if (auto ExtensionOS = if (auto ExtensionOS =
- CreateOutputStream(ExtensionSGF.getKey() + "@" + API.ProductName))+ CreateOutputStream(API.ProductName + "@" + ExtensionSGF.getKey()))
- Serializer.serializeGraphToStream(*ExtensionOS, Options,+ Serializer.serializeGraphToStream(*ExtensionOS, Options, API.ProductName,
- ExtensionSGF.getKey(),
std::move(ExtensionSGF.getValue())); std::move(ExtensionSGF.getValue()));
} }
} }
clang/lib/Format/ContinuationIndenter.cpp
@@ -826,8 +826,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) {
if (Prev->is(TT_TemplateString) && Prev->opensScope()) if (Prev->is(TT_TemplateString) && Prev->opensScope())
return true; return true;
- if (Prev->is(TT_TemplateString) && Prev->closesScope())+ if (Prev->opensScope() ||
+ (Prev->is(TT_TemplateString) && Prev->closesScope())) {
break; break;
+ }
} }
return false; return false;
}; };
clang/lib/Frontend/CompilerInvocation.cpp
@@ -4257,6 +4257,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
if (TT.getArch() == llvm::Triple::UnknownArch || if (TT.getArch() == llvm::Triple::UnknownArch ||
!(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() || !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
TT.getArch() == llvm::Triple::systemz || TT.getArch() == llvm::Triple::systemz ||
+ TT.getArch() == llvm::Triple::loongarch64 ||
TT.getArch() == llvm::Triple::nvptx || TT.getArch() == llvm::Triple::nvptx ||
TT.getArch() == llvm::Triple::nvptx64 || TT.getArch() == llvm::Triple::nvptx64 ||
TT.getArch() == llvm::Triple::amdgcn || TT.getArch() == llvm::Triple::amdgcn ||
clang/lib/Frontend/InitPreprocessor.cpp
@@ -752,6 +752,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_if_consteval", "202106L"); Builder.defineMacro("__cpp_if_consteval", "202106L");
Builder.defineMacro("__cpp_multidimensional_subscript", "202211L"); Builder.defineMacro("__cpp_multidimensional_subscript", "202211L");
Builder.defineMacro("__cpp_auto_cast", "202110L"); Builder.defineMacro("__cpp_auto_cast", "202110L");
+ Builder.defineMacro("__cpp_explicit_this_parameter", "202110L");
} }
// We provide those C++23 features as extensions in earlier language modes, so // We provide those C++23 features as extensions in earlier language modes, so
clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -2241,6 +2241,15 @@ float4 trunc(float4);
// Wave* builtins // Wave* builtins
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
+/// \brief Returns true if the expression is true in all active lanes in the
+/// current wave.
+///
+/// \param Val The boolean expression to evaluate.
+/// \return True if the expression is true in all lanes.
+_HLSL_AVAILABILITY(shadermodel, 6.0)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_all_true)
+__attribute__((convergent)) bool WaveActiveAllTrue(bool Val);
+
/// \brief Returns true if the expression is true in any active lane in the /// \brief Returns true if the expression is true in any active lane in the
/// current wave. /// current wave.
/// ///
clang/lib/Parse/ParseOpenACC.cpp
@@ -998,17 +998,17 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
// make sure we get the right differentiator. // make sure we get the right differentiator.
assert(DirKind == OpenACCDirectiveKind::Update); assert(DirKind == OpenACCDirectiveKind::Update);
[[fallthrough]]; [[fallthrough]];
- case OpenACCClauseKind::Delete:
case OpenACCClauseKind::Device: case OpenACCClauseKind::Device:
case OpenACCClauseKind::DeviceResident: case OpenACCClauseKind::DeviceResident:
case OpenACCClauseKind::Host: case OpenACCClauseKind::Host:
case OpenACCClauseKind::Link: case OpenACCClauseKind::Link:
- case OpenACCClauseKind::UseDevice:
ParseOpenACCVarList(ClauseKind); ParseOpenACCVarList(ClauseKind);
break; break;
case OpenACCClauseKind::Attach: case OpenACCClauseKind::Attach:
+ case OpenACCClauseKind::Delete:
case OpenACCClauseKind::Detach: case OpenACCClauseKind::Detach:
case OpenACCClauseKind::DevicePtr: case OpenACCClauseKind::DevicePtr:
+ case OpenACCClauseKind::UseDevice:
ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
/*IsReadOnly=*/false, /*IsZero=*/false); /*IsReadOnly=*/false, /*IsZero=*/false);
break; break;
@@ -1512,8 +1512,8 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
ParsingOpenACCDirectiveRAII DirScope(*this); ParsingOpenACCDirectiveRAII DirScope(*this);
OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
- if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind,+ if (getActions().OpenACC().ActOnStartStmtDirective(
- DirInfo.StartLoc))+ DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
return StmtError(); return StmtError();
StmtResult AssocStmt; StmtResult AssocStmt;
clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -191,6 +191,19 @@ public:
return *this; return *this;
} }
+ BuiltinTypeDeclBuilder &addLoadMethods() {
+ if (Record->isCompleteDefinition())
+ return *this;
+
+ ASTContext &AST = Record->getASTContext();
+ IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
+ DeclarationName Load(&II);
+ // TODO: We also need versions with status for CheckAccessFullyMapped.
+ addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false);
+
+ return *this;
+ }
+
FieldDecl *getResourceHandleField() { FieldDecl *getResourceHandleField() {
auto I = Fields.find("__handle"); auto I = Fields.find("__handle");
assert(I != Fields.end() && assert(I != Fields.end() &&
@@ -546,6 +559,10 @@ private:
public: public:
~BuiltinTypeMethodBuilder() { finalizeMethod(); } ~BuiltinTypeMethodBuilder() { finalizeMethod(); }
+ BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
+ BuiltinTypeMethodBuilder &
+ operator=(const BuiltinTypeMethodBuilder &Other) = delete;
+
Expr *getResourceHandleExpr() { Expr *getResourceHandleExpr() {
// The first statement added to a method or access to 'this' creates the // The first statement added to a method or access to 'this' creates the
// declaration. // declaration.
@@ -921,6 +938,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
ResourceKind::TypedBuffer, /*IsROV=*/false, ResourceKind::TypedBuffer, /*IsROV=*/false,
/*RawBuffer=*/false) /*RawBuffer=*/false)
.addArraySubscriptOperators() .addArraySubscriptOperators()
+ .addLoadMethods()
.completeDefinition(); .completeDefinition();
}); });
@@ -933,6 +951,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
ResourceKind::TypedBuffer, /*IsROV=*/true, ResourceKind::TypedBuffer, /*IsROV=*/true,
/*RawBuffer=*/false) /*RawBuffer=*/false)
.addArraySubscriptOperators() .addArraySubscriptOperators()
+ .addLoadMethods()
.completeDefinition(); .completeDefinition();
}); });
clang/lib/Sema/SemaExpr.cpp
@@ -11786,6 +11786,50 @@ static bool checkForArray(const Expr *E) {
return D->getType()->isArrayType() && !D->isWeak(); return D->getType()->isArrayType() && !D->isWeak();
} }
+/// Detect patterns ptr + size >= ptr and ptr + size < ptr, where ptr is a
+/// pointer and size is an unsigned integer. Return whether the result is
+/// always true/false.
+static std::optional<bool> isTautologicalBoundsCheck(const Expr *LHS,
+ const Expr *RHS,
+ BinaryOperatorKind Opc) {
+ if (!LHS->getType()->isPointerType())
+ return std::nullopt;
+
+ // Canonicalize to >= or < predicate.
+ switch (Opc) {
+ case BO_GE:
+ case BO_LT:
+ break;
+ case BO_GT:
+ std::swap(LHS, RHS);
+ Opc = BO_LT;
+ break;
+ case BO_LE:
+ std::swap(LHS, RHS);
+ Opc = BO_GE;
+ break;
+ default:
+ return std::nullopt;
+ }
+
+ auto *BO = dyn_cast<BinaryOperator>(LHS);
+ if (!BO || BO->getOpcode() != BO_Add)
+ return std::nullopt;
+
+ Expr *Other;
+ if (Expr::isSameComparisonOperand(BO->getLHS(), RHS))
+ Other = BO->getRHS();
+ else if (Expr::isSameComparisonOperand(BO->getRHS(), RHS))
+ Other = BO->getLHS();
+ else
+ return std::nullopt;
+
+ if (!Other->getType()->isUnsignedIntegerType())
+ return std::nullopt;
+
+ return Opc == BO_GE;
+}
+
/// Diagnose some forms of syntactically-obvious tautological comparison. /// Diagnose some forms of syntactically-obvious tautological comparison.
static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS, Expr *LHS, Expr *RHS,
@@ -11895,6 +11939,12 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
S.PDiag(diag::warn_comparison_always) S.PDiag(diag::warn_comparison_always)
<< 1 /*array comparison*/ << 1 /*array comparison*/
<< Result); << Result);
+ } else if (std::optional<bool> Res =
+ isTautologicalBoundsCheck(LHS, RHS, Opc)) {
+ S.DiagRuntimeBehavior(Loc, nullptr,
+ S.PDiag(diag::warn_comparison_always)
+ << 2 /*pointer comparison*/
+ << (*Res ? AlwaysTrue : AlwaysFalse));
} }
} }
clang/lib/Sema/SemaExprCXX.cpp
@@ -8201,7 +8201,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
return ExprError(); return ExprError();
if (!ObjectType->isDependentType() && !ObjectType->isScalarType() && if (!ObjectType->isDependentType() && !ObjectType->isScalarType() &&
- !ObjectType->isVectorType()) {+ !ObjectType->isVectorType() && !ObjectType->isMatrixType()) {
if (getLangOpts().MSVCCompat && ObjectType->isVoidType()) if (getLangOpts().MSVCCompat && ObjectType->isVoidType())
Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange(); Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange();
else { else {
clang/lib/Sema/SemaExprMember.cpp
@@ -1003,15 +1003,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
: !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) && : !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) &&
"dependent lookup context that isn't the current instantiation?"); "dependent lookup context that isn't the current instantiation?");
- // C++1z [expr.ref]p2:
- // For the first option (dot) the first expression shall be a glvalue [...]
- if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) {
- ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
- if (Converted.isInvalid())
- return ExprError();
- BaseExpr = Converted.get();
- }
-
const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
DeclarationName MemberName = MemberNameInfo.getName(); DeclarationName MemberName = MemberNameInfo.getName();
SourceLocation MemberLoc = MemberNameInfo.getLoc(); SourceLocation MemberLoc = MemberNameInfo.getLoc();
@@ -1128,26 +1119,68 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true); BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true);
} }
+ // C++17 [expr.ref]p2, per CWG2813:
+ // For the first option (dot), if the id-expression names a static member or
+ // an enumerator, the first expression is a discarded-value expression; if
+ // the id-expression names a non-static data member, the first expression
+ // shall be a glvalue.
+ auto ConvertBaseExprToDiscardedValue = [&] {
+ assert(getLangOpts().CPlusPlus &&
+ "Static member / member enumerator outside of C++");
+ if (IsArrow)
+ return false;
+ ExprResult Converted = IgnoredValueConversions(BaseExpr);
+ if (Converted.isInvalid())
+ return true;
+ BaseExpr = Converted.get();
+ DiagnoseDiscardedExprMarkedNodiscard(BaseExpr);
+ return false;
+ };
+ auto ConvertBaseExprToGLValue = [&] {
+ if (IsArrow || !BaseExpr->isPRValue())
+ return false;
+ ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
+ if (Converted.isInvalid())
+ return true;
+ BaseExpr = Converted.get();
+ return false;
+ };
+
// Check the use of this member. // Check the use of this member.
if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))
return ExprError(); return ExprError();
- if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))+ if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
+ if (ConvertBaseExprToGLValue())
+ return ExprError();
return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl, return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,
MemberNameInfo); MemberNameInfo);
+ }
- if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))+ if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl)) {
+ // No temporaries are materialized for property references yet.
+ // They might be materialized when this is transformed into a member call.
+ // Note that this is slightly different behaviour from MSVC which doesn't
+ // implement CWG2813 yet: MSVC might materialize an extra temporary if the
+ // getter or setter function is an explicit object member function.
return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD, return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
MemberNameInfo); MemberNameInfo);
+ }
- if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))+ if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) {
+ if (ConvertBaseExprToGLValue())
+ return ExprError();
// We may have found a field within an anonymous union or struct // We may have found a field within an anonymous union or struct
// (C++ [class.union]). // (C++ [class.union]).
return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
FoundDecl, BaseExpr, FoundDecl, BaseExpr,
OpLoc); OpLoc);
+ }
+ // Static data member
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+ if (ConvertBaseExprToDiscardedValue())
+ return ExprError();
return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,
SS.getWithLocInContext(Context), TemplateKWLoc, Var, SS.getWithLocInContext(Context), TemplateKWLoc, Var,
FoundDecl, /*HadMultipleCandidates=*/false, FoundDecl, /*HadMultipleCandidates=*/false,
@@ -1161,7 +1194,13 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (MemberFn->isInstance()) { if (MemberFn->isInstance()) {
valueKind = VK_PRValue; valueKind = VK_PRValue;
type = Context.BoundMemberTy; type = Context.BoundMemberTy;
+ if (MemberFn->isImplicitObjectMemberFunction() &&
+ ConvertBaseExprToGLValue())
+ return ExprError();
} else { } else {
+ // Static member function
+ if (ConvertBaseExprToDiscardedValue())
+ return ExprError();
valueKind = VK_LValue; valueKind = VK_LValue;
type = MemberFn->getType(); type = MemberFn->getType();
} }
@@ -1174,6 +1213,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+ if (ConvertBaseExprToDiscardedValue())
+ return ExprError();
return BuildMemberExpr( return BuildMemberExpr(
BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context), BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context),
TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false, TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false,
@@ -1181,6 +1222,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
} }
if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
+ if (ConvertBaseExprToDiscardedValue())
+ return ExprError();
if (!TemplateArgs) { if (!TemplateArgs) {
diagnoseMissingTemplateArguments( diagnoseMissingTemplateArguments(
SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc); SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc);
clang/lib/Sema/SemaOpenACC.cpp
@@ -425,6 +425,15 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
return false; return false;
} }
} }
+ case OpenACCClauseKind::Delete: {
+ switch (DirectiveKind) {
+ case OpenACCDirectiveKind::ExitData:
+ return true;
+ default:
+ return false;
+ }
+ }
+
case OpenACCClauseKind::Detach: { case OpenACCClauseKind::Detach: {
switch (DirectiveKind) { switch (DirectiveKind) {
case OpenACCDirectiveKind::ExitData: case OpenACCDirectiveKind::ExitData:
@@ -433,6 +442,15 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
return false; return false;
} }
} }
+
+ case OpenACCClauseKind::UseDevice: {
+ switch (DirectiveKind) {
+ case OpenACCDirectiveKind::HostData:
+ return true;
+ default:
+ return false;
+ }
+ }
} }
default: default:
@@ -1066,6 +1084,25 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDetachClause(
Clause.getEndLoc()); Clause.getEndLoc());
} }
+OpenACCClause *SemaOpenACCClauseVisitor::VisitDeleteClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+ return OpenACCDeleteClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getLParenLoc(), Clause.getVarList(),
+ Clause.getEndLoc());
+}
+
+OpenACCClause *SemaOpenACCClauseVisitor::VisitUseDeviceClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // ActOnVar ensured that everything is a valid variable or array, so nothing
+ // left to do here.
+ return OpenACCUseDeviceClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
+ Clause.getEndLoc());
+}
+
OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
SemaOpenACC::OpenACCParsedClause &Clause) { SemaOpenACC::OpenACCParsedClause &Clause) {
// Restrictions only properly implemented on 'compute'/'combined'/'data' // Restrictions only properly implemented on 'compute'/'combined'/'data'
@@ -2411,6 +2448,15 @@ bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind,
ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) { ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) {
Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts(); Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
+ // 'use_device' doesn't allow array subscript or array sections.
+ // OpenACC3.3 2.8:
+ // A 'var' in a 'use_device' clause must be the name of a variable or array.
+ if (CK == OpenACCClauseKind::UseDevice &&
+ isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
+ Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
+ return ExprError();
+ }
+
// Sub-arrays/subscript-exprs are fine as long as the base is a // Sub-arrays/subscript-exprs are fine as long as the base is a
// VarExpr/MemberExpr. So strip all of those off. // VarExpr/MemberExpr. So strip all of those off.
while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) { while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
@@ -2431,16 +2477,20 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) {
// If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
// reduction clause must be a scalar variable name, an aggregate variable // reduction clause must be a scalar variable name, an aggregate variable
// name, an array element, or a subarray. // name, an array element, or a subarray.
- // A MemberExpr that references a Field is valid.+ // If CK is a 'use_device', this also isn't valid, as it isn' the name of a
- if (CK != OpenACCClauseKind::Reduction) {+ // variable or array.
+ // A MemberExpr that references a Field is valid for other clauses.
+ if (CK != OpenACCClauseKind::Reduction &&
+ CK != OpenACCClauseKind::UseDevice) {
if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) { if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
return VarExpr; return VarExpr;
} }
} }
- // Referring to 'this' is always OK.+ // Referring to 'this' is ok for the most part, but for 'use_device' doesn't
- if (isa<CXXThisExpr>(CurVarExpr))+ // fall into 'variable or array name'
+ if (CK != OpenACCClauseKind::UseDevice && isa<CXXThisExpr>(CurVarExpr))
return VarExpr; return VarExpr;
// Nothing really we can do here, as these are dependent. So just return they // Nothing really we can do here, as these are dependent. So just return they
@@ -2455,8 +2505,11 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) {
if (isa<RecoveryExpr>(CurVarExpr)) if (isa<RecoveryExpr>(CurVarExpr))
return ExprError(); return ExprError();
- Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)+ if (CK == OpenACCClauseKind::UseDevice)
- << (CK != OpenACCClauseKind::Reduction);+ Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
+ else
+ Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
+ << (CK != OpenACCClauseKind::Reduction);
return ExprError(); return ExprError();
} }
@@ -3473,8 +3526,35 @@ void SemaOpenACC::ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body) {
} }
} }
-bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K,+namespace {
- SourceLocation StartLoc) {+// Get a list of clause Kinds for diagnosing a list, joined by a commas and an
+// 'or'.
+std::string GetListOfClauses(llvm::ArrayRef<OpenACCClauseKind> Clauses) {
+ assert(!Clauses.empty() && "empty clause list not supported");
+
+ std::string Output;
+ llvm::raw_string_ostream OS{Output};
+
+ if (Clauses.size() == 1) {
+ OS << '\'' << Clauses[0] << '\'';
+ return Output;
+ }
+
+ llvm::ArrayRef<OpenACCClauseKind> AllButLast{Clauses.begin(),
+ Clauses.end() - 1};
+
+ llvm::interleave(
+ AllButLast, [&](OpenACCClauseKind K) { OS << '\'' << K << '\''; },
+ [&] { OS << ", "; });
+
+ OS << " or \'" << Clauses.back() << '\'';
+ return Output;
+}
+} // namespace
+
+bool SemaOpenACC::ActOnStartStmtDirective(
+ OpenACCDirectiveKind K, SourceLocation StartLoc,
+ ArrayRef<const OpenACCClause *> Clauses) {
SemaRef.DiscardCleanupsInEvaluationContext(); SemaRef.DiscardCleanupsInEvaluationContext();
SemaRef.PopExpressionEvaluationContext(); SemaRef.PopExpressionEvaluationContext();
@@ -3501,6 +3581,59 @@ bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K,
<< OpenACCClauseKind::Tile; << OpenACCClauseKind::Tile;
} }
+ // OpenACC3.3 2.6.5: At least one copy, copyin, copyout, create, no_create,
+ // present, deviceptr, attach, or default clause must appear on a 'data'
+ // construct.
+ if (K == OpenACCDirectiveKind::Data &&
+ llvm::find_if(Clauses,
+ llvm::IsaPred<OpenACCCopyClause, OpenACCCopyInClause,
+ OpenACCCopyOutClause, OpenACCCreateClause,
+ OpenACCNoCreateClause, OpenACCPresentClause,
+ OpenACCDevicePtrClause, OpenACCAttachClause,
+ OpenACCDefaultClause>) == Clauses.end())
+ return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
+ << K
+ << GetListOfClauses(
+ {OpenACCClauseKind::Copy, OpenACCClauseKind::CopyIn,
+ OpenACCClauseKind::CopyOut, OpenACCClauseKind::Create,
+ OpenACCClauseKind::NoCreate, OpenACCClauseKind::Present,
+ OpenACCClauseKind::DevicePtr, OpenACCClauseKind::Attach,
+ OpenACCClauseKind::Default});
+
+ // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear
+ // on an enter data directive.
+ if (K == OpenACCDirectiveKind::EnterData &&
+ llvm::find_if(Clauses,
+ llvm::IsaPred<OpenACCCopyInClause, OpenACCCreateClause,
+ OpenACCAttachClause>) == Clauses.end())
+ return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
+ << K
+ << GetListOfClauses({
+ OpenACCClauseKind::CopyIn,
+ OpenACCClauseKind::Create,
+ OpenACCClauseKind::Attach,
+ });
+ // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must
+ // appear on an exit data directive.
+ if (K == OpenACCDirectiveKind::ExitData &&
+ llvm::find_if(Clauses,
+ llvm::IsaPred<OpenACCCopyOutClause, OpenACCDeleteClause,
+ OpenACCDetachClause>) == Clauses.end())
+ return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
+ << K
+ << GetListOfClauses({
+ OpenACCClauseKind::CopyOut,
+ OpenACCClauseKind::Delete,
+ OpenACCClauseKind::Detach,
+ });
+
+ // OpenACC3.3 2.8: At least 'one use_device' clause must appear.
+ if (K == OpenACCDirectiveKind::HostData &&
+ llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
+ Clauses.end())
+ return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
+ << K << GetListOfClauses({OpenACCClauseKind::UseDevice});
+
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
} }
clang/lib/Sema/SemaOverload.cpp
@@ -5933,7 +5933,9 @@ ExprResult Sema::PerformImplicitObjectArgumentInitialization(
DestType = ImplicitParamRecordType; DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context); FromClassification = From->Classify(Context);
- // When performing member access on a prvalue, materialize a temporary.+ // CWG2813 [expr.call]p6:
+ // If the function is an implicit object member function, the object
+ // expression of the class member access shall be a glvalue [...]
if (From->isPRValue()) { if (From->isPRValue()) {
From = CreateMaterializeTemporaryExpr(FromRecordType, From, From = CreateMaterializeTemporaryExpr(FromRecordType, From,
Method->getRefQualifier() != Method->getRefQualifier() !=
@@ -6464,11 +6466,6 @@ static Expr *GetExplicitObjectExpr(Sema &S, Expr *Obj,
VK_LValue, OK_Ordinary, SourceLocation(), VK_LValue, OK_Ordinary, SourceLocation(),
/*CanOverflow=*/false, FPOptionsOverride()); /*CanOverflow=*/false, FPOptionsOverride());
} }
- if (Obj->Classify(S.getASTContext()).isPRValue()) {
- Obj = S.CreateMaterializeTemporaryExpr(
- ObjType, Obj,
- !Fun->getParamDecl(0)->getType()->isRValueReferenceType());
- }
return Obj; return Obj;
} }
@@ -15584,8 +15581,6 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
CurFPFeatureOverrides(), Proto->getNumParams()); CurFPFeatureOverrides(), Proto->getNumParams());
} else { } else {
// Convert the object argument (for a non-static member function call). // Convert the object argument (for a non-static member function call).
- // We only need to do this if there was actually an overload; otherwise
- // it was done at lookup.
ExprResult ObjectArg = PerformImplicitObjectArgumentInitialization( ExprResult ObjectArg = PerformImplicitObjectArgumentInitialization(
MemExpr->getBase(), Qualifier, FoundDecl, Method); MemExpr->getBase(), Qualifier, FoundDecl, Method);
if (ObjectArg.isInvalid()) if (ObjectArg.isInvalid())
clang/lib/Sema/SemaStmt.cpp
@@ -226,17 +226,18 @@ static bool DiagnoseNoDiscard(Sema &S, const NamedDecl *OffendingDecl,
return S.Diag(Loc, diag::warn_unused_result) << A << true << Msg << R1 << R2; return S.Diag(Loc, diag::warn_unused_result) << A << true << Msg << R1 << R2;
} }
-void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {+namespace {
- if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
- return DiagnoseUnusedExprResult(Label->getSubStmt(), DiagID);
- const Expr *E = dyn_cast_or_null<Expr>(S);+// Diagnoses unused expressions that call functions marked [[nodiscard]],
- if (!E)+// [[gnu::warn_unused_result]] and similar.
- return;+// Additionally, a DiagID can be provided to emit a warning in additional
+// contexts (such as for an unused LHS of a comma expression)
+void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
+ bool NoDiscardOnly = !DiagID.has_value();
// If we are in an unevaluated expression context, then there can be no unused // If we are in an unevaluated expression context, then there can be no unused
// results because the results aren't expected to be used in the first place. // results because the results aren't expected to be used in the first place.
- if (isUnevaluatedContext())+ if (S.isUnevaluatedContext())
return; return;
SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc(); SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc();
@@ -245,30 +246,31 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
// expression is a call to a function with the warn_unused_result attribute, // expression is a call to a function with the warn_unused_result attribute,
// we warn no matter the location. Because of the order in which the various // we warn no matter the location. Because of the order in which the various
// checks need to happen, we factor out the macro-related test here. // checks need to happen, we factor out the macro-related test here.
- bool ShouldSuppress =+ bool ShouldSuppress = S.SourceMgr.isMacroBodyExpansion(ExprLoc) ||
- SourceMgr.isMacroBodyExpansion(ExprLoc) ||+ S.SourceMgr.isInSystemMacro(ExprLoc);
- SourceMgr.isInSystemMacro(ExprLoc);
const Expr *WarnExpr; const Expr *WarnExpr;
SourceLocation Loc; SourceLocation Loc;
SourceRange R1, R2; SourceRange R1, R2;
- if (!E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context))+ if (!E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, S.Context))
- return;
-
- // If this is a GNU statement expression expanded from a macro, it is probably
- // unused because it is a function-like macro that can be used as either an
- // expression or statement. Don't warn, because it is almost certainly a
- // false positive.
- if (isa<StmtExpr>(E) && Loc.isMacroID())
return; return;
- // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers.+ if (!NoDiscardOnly) {
- // That macro is frequently used to suppress "unused parameter" warnings,+ // If this is a GNU statement expression expanded from a macro, it is
- // but its implementation makes clang's -Wunused-value fire. Prevent this.+ // probably unused because it is a function-like macro that can be used as
- if (isa<ParenExpr>(E->IgnoreImpCasts()) && Loc.isMacroID()) {+ // either an expression or statement. Don't warn, because it is almost
- SourceLocation SpellLoc = Loc;+ // certainly a false positive.
- if (findMacroSpelling(SpellLoc, "UNREFERENCED_PARAMETER"))+ if (isa<StmtExpr>(E) && Loc.isMacroID())
return; return;
+
+ // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers.
+ // That macro is frequently used to suppress "unused parameter" warnings,
+ // but its implementation makes clang's -Wunused-value fire. Prevent this.
+ if (isa<ParenExpr>(E->IgnoreImpCasts()) && Loc.isMacroID()) {
+ SourceLocation SpellLoc = Loc;
+ if (S.findMacroSpelling(SpellLoc, "UNREFERENCED_PARAMETER"))
+ return;
+ }
} }
// Okay, we have an unused result. Depending on what the base expression is, // Okay, we have an unused result. Depending on what the base expression is,
@@ -279,7 +281,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
E = TempExpr->getSubExpr(); E = TempExpr->getSubExpr();
- if (DiagnoseUnusedComparison(*this, E))+ if (DiagnoseUnusedComparison(S, E))
return; return;
E = WarnExpr; E = WarnExpr;
@@ -293,8 +295,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
if (E->getType()->isVoidType()) if (E->getType()->isVoidType())
return; return;
- auto [OffendingDecl, A] = CE->getUnusedResultAttr(Context);+ auto [OffendingDecl, A] = CE->getUnusedResultAttr(S.Context);
- if (DiagnoseNoDiscard(*this, OffendingDecl,+ if (DiagnoseNoDiscard(S, OffendingDecl,
cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2, cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
/*isCtor=*/false)) /*isCtor=*/false))
return; return;
@@ -307,11 +309,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
if (ShouldSuppress) if (ShouldSuppress)
return; return;
if (FD->hasAttr<PureAttr>()) { if (FD->hasAttr<PureAttr>()) {
- Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";+ S.Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
return; return;
} }
if (FD->hasAttr<ConstAttr>()) { if (FD->hasAttr<ConstAttr>()) {
- Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";+ S.Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
return; return;
} }
} }
@@ -323,15 +325,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
OffendingDecl = Ctor->getParent(); OffendingDecl = Ctor->getParent();
A = OffendingDecl->getAttr<WarnUnusedResultAttr>(); A = OffendingDecl->getAttr<WarnUnusedResultAttr>();
} }
- if (DiagnoseNoDiscard(*this, OffendingDecl, A, Loc, R1, R2,+ if (DiagnoseNoDiscard(S, OffendingDecl, A, Loc, R1, R2,
/*isCtor=*/true)) /*isCtor=*/true))
return; return;
} }
} else if (const auto *ILE = dyn_cast<InitListExpr>(E)) { } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) { if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
- if (DiagnoseNoDiscard(*this, TD, TD->getAttr<WarnUnusedResultAttr>(), Loc,+ if (DiagnoseNoDiscard(S, TD, TD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
- R1, R2, /*isCtor=*/false))+ R2, /*isCtor=*/false))
return; return;
} }
} else if (ShouldSuppress) } else if (ShouldSuppress)
@@ -339,23 +341,24 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
E = WarnExpr; E = WarnExpr;
if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
- if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) {+ if (S.getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) {
- Diag(Loc, diag::err_arc_unused_init_message) << R1;+ S.Diag(Loc, diag::err_arc_unused_init_message) << R1;
return; return;
} }
const ObjCMethodDecl *MD = ME->getMethodDecl(); const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD) { if (MD) {
- if (DiagnoseNoDiscard(*this, nullptr, MD->getAttr<WarnUnusedResultAttr>(),+ if (DiagnoseNoDiscard(S, nullptr, MD->getAttr<WarnUnusedResultAttr>(),
- Loc, R1, R2, /*isCtor=*/false))+ Loc, R1, R2,
+ /*isCtor=*/false))
return; return;
} }
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
const Expr *Source = POE->getSyntacticForm(); const Expr *Source = POE->getSyntacticForm();
// Handle the actually selected call of an OpenMP specialized call. // Handle the actually selected call of an OpenMP specialized call.
- if (LangOpts.OpenMP && isa<CallExpr>(Source) &&+ if (S.LangOpts.OpenMP && isa<CallExpr>(Source) &&
POE->getNumSemanticExprs() == 1 && POE->getNumSemanticExprs() == 1 &&
isa<CallExpr>(POE->getSemanticExpr(0))) isa<CallExpr>(POE->getSemanticExpr(0)))
- return DiagnoseUnusedExprResult(POE->getSemanticExpr(0), DiagID);+ return DiagnoseUnused(S, POE->getSemanticExpr(0), DiagID);
if (isa<ObjCSubscriptRefExpr>(Source)) if (isa<ObjCSubscriptRefExpr>(Source))
DiagID = diag::warn_unused_container_subscript_expr; DiagID = diag::warn_unused_container_subscript_expr;
else if (isa<ObjCPropertyRefExpr>(Source)) else if (isa<ObjCPropertyRefExpr>(Source))
@@ -372,17 +375,21 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
if (!RD->getAttr<WarnUnusedAttr>()) if (!RD->getAttr<WarnUnusedAttr>())
return; return;
} }
+
+ if (NoDiscardOnly)
+ return;
+
// Diagnose "(void*) blah" as a typo for "(void) blah". // Diagnose "(void*) blah" as a typo for "(void) blah".
- else if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) {+ if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) {
TypeSourceInfo *TI = CE->getTypeInfoAsWritten(); TypeSourceInfo *TI = CE->getTypeInfoAsWritten();
QualType T = TI->getType(); QualType T = TI->getType();
// We really do want to use the non-canonical type here. // We really do want to use the non-canonical type here.
- if (T == Context.VoidPtrTy) {+ if (T == S.Context.VoidPtrTy) {
PointerTypeLoc TL = TI->getTypeLoc().castAs<PointerTypeLoc>(); PointerTypeLoc TL = TI->getTypeLoc().castAs<PointerTypeLoc>();
- Diag(Loc, diag::warn_unused_voidptr)+ S.Diag(Loc, diag::warn_unused_voidptr)
- << FixItHint::CreateRemoval(TL.getStarLoc());+ << FixItHint::CreateRemoval(TL.getStarLoc());
return; return;
} }
} }
@@ -391,16 +398,34 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
// isn't an array. // isn't an array.
if (E->isGLValue() && E->getType().isVolatileQualified() && if (E->isGLValue() && E->getType().isVolatileQualified() &&
!E->getType()->isArrayType()) { !E->getType()->isArrayType()) {
- Diag(Loc, diag::warn_unused_volatile) << R1 << R2;+ S.Diag(Loc, diag::warn_unused_volatile) << R1 << R2;
return; return;
} }
// Do not diagnose use of a comma operator in a SFINAE context because the // Do not diagnose use of a comma operator in a SFINAE context because the
// type of the left operand could be used for SFINAE, so technically it is // type of the left operand could be used for SFINAE, so technically it is
// *used*. // *used*.
- if (DiagID != diag::warn_unused_comma_left_operand || !isSFINAEContext())+ if (DiagID == diag::warn_unused_comma_left_operand && S.isSFINAEContext())
- DiagIfReachable(Loc, S ? llvm::ArrayRef(S) : llvm::ArrayRef<Stmt *>(),+ return;
- PDiag(DiagID) << R1 << R2);+
+ S.DiagIfReachable(Loc, llvm::ArrayRef<const Stmt *>(E),
+ S.PDiag(*DiagID) << R1 << R2);
+}
+} // namespace
+
+void Sema::DiagnoseDiscardedExprMarkedNodiscard(const Expr *E) {
+ DiagnoseUnused(*this, E, std::nullopt);
+}
+
+void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
+ if (const LabelStmt *Label = dyn_cast_if_present<LabelStmt>(S))
+ S = Label->getSubStmt();
+
+ const Expr *E = dyn_cast_if_present<Expr>(S);
+ if (!E)
+ return;
+
+ DiagnoseUnused(*this, E, DiagID);
} }
void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) { void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) {
clang/lib/Sema/SemaStmtAsm.cpp
@@ -664,11 +664,16 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
SmallerValueMentioned |= OutSize < InSize; SmallerValueMentioned |= OutSize < InSize;
} }
+ // If the input is an integer register while the output is floating point,
+ // or vice-versa, there is no way they can work together.
+ bool FPTiedToInt = (InputDomain == AD_FP) ^ (OutputDomain == AD_FP);
+
// If the smaller value wasn't mentioned in the asm string, and if the // If the smaller value wasn't mentioned in the asm string, and if the
// output was a register, just extend the shorter one to the size of the // output was a register, just extend the shorter one to the size of the
// larger one. // larger one.
- if (!SmallerValueMentioned && InputDomain != AD_Other &&+ if (!SmallerValueMentioned && !FPTiedToInt && InputDomain != AD_Other &&
OutputConstraintInfos[TiedTo].allowsRegister()) { OutputConstraintInfos[TiedTo].allowsRegister()) {
+
// FIXME: GCC supports the OutSize to be 128 at maximum. Currently codegen // FIXME: GCC supports the OutSize to be 128 at maximum. Currently codegen
// crash when the size larger than the register size. So we limit it here. // crash when the size larger than the register size. So we limit it here.
if (OutTy->isStructureType() && if (OutTy->isStructureType() &&
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2146,6 +2146,23 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
// Check whether there is already a function template specialization for // Check whether there is already a function template specialization for
// this declaration. // this declaration.
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+ bool isFriend;
+ if (FunctionTemplate)
+ isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
+ else
+ isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+ // Friend function defined withing class template may stop being function
+ // definition during AST merges from different modules, in this case decl
+ // with function body should be used for instantiation.
+ if (isFriend) {
+ const FunctionDecl *Defn = nullptr;
+ if (D->hasBody(Defn)) {
+ D = const_cast<FunctionDecl *>(Defn);
+ FunctionTemplate = Defn->getDescribedFunctionTemplate();
+ }
+ }
+
if (FunctionTemplate && !TemplateParams) { if (FunctionTemplate && !TemplateParams) {
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost(); ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
@@ -2158,12 +2175,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
return SpecFunc; return SpecFunc;
} }
- bool isFriend;
- if (FunctionTemplate)
- isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
- else
- isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
-
bool MergeWithParentScope = (TemplateParams != nullptr) || bool MergeWithParentScope = (TemplateParams != nullptr) ||
Owner->isFunctionOrMethod() || Owner->isFunctionOrMethod() ||
!(isa<Decl>(Owner) && !(isa<Decl>(Owner) &&
@@ -4692,6 +4703,17 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) { ParmVarDecl *Param) {
assert(Param->hasUninstantiatedDefaultArg()); assert(Param->hasUninstantiatedDefaultArg());
+ // FIXME: We don't track member specialization info for non-defining
+ // friend declarations, so we will not be able to later find the function
+ // pattern. As a workaround, don't instantiate the default argument in this
+ // case. This is correct per the standard and only an issue for recovery
+ // purposes. [dcl.fct.default]p4:
+ // if a friend declaration D specifies a default argument expression,
+ // that declaration shall be a definition.
+ if (FD->getFriendObjectKind() != Decl::FOK_None &&
+ !FD->getTemplateInstantiationPattern())
+ return true;
+
// Instantiate the expression. // Instantiate the expression.
// //
// FIXME: Pass in a correct Pattern argument, otherwise // FIXME: Pass in a correct Pattern argument, otherwise
clang/lib/Sema/SemaType.cpp
@@ -2312,6 +2312,17 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
return T; return T;
} }
+static bool CheckBitIntElementType(Sema &S, SourceLocation AttrLoc,
+ const BitIntType *BIT,
+ bool ForMatrixType = false) {
+ // Only support _BitInt elements with byte-sized power of 2 NumBits.
+ unsigned NumBits = BIT->getNumBits();
+ if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8)
+ return S.Diag(AttrLoc, diag::err_attribute_invalid_bitint_vector_type)
+ << ForMatrixType << (NumBits < 8);
+ return false;
+}
+
QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
SourceLocation AttrLoc) { SourceLocation AttrLoc) {
// The base type must be integer (not Boolean or enumeration) or float, and // The base type must be integer (not Boolean or enumeration) or float, and
@@ -2324,15 +2335,10 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType; Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
return QualType(); return QualType();
} }
- // Only support _BitInt elements with byte-sized power of 2 NumBits.+
- if (const auto *BIT = CurType->getAs<BitIntType>()) {+ if (const auto *BIT = CurType->getAs<BitIntType>();
- unsigned NumBits = BIT->getNumBits();+ BIT && CheckBitIntElementType(*this, AttrLoc, BIT))
- if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8) {+ return QualType();
- Diag(AttrLoc, diag::err_attribute_invalid_bitint_vector_type)
- << (NumBits < 8);
- return QualType();
- }
- }
if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent()) if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
@@ -2402,15 +2408,9 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
return QualType(); return QualType();
} }
- // Only support _BitInt elements with byte-sized power of 2 NumBits.+ if (const auto *BIT = T->getAs<BitIntType>();
- if (T->isBitIntType()) {+ BIT && CheckBitIntElementType(*this, AttrLoc, BIT))
- unsigned NumBits = T->castAs<BitIntType>()->getNumBits();+ return QualType();
- if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8) {
- Diag(AttrLoc, diag::err_attribute_invalid_bitint_vector_type)
- << (NumBits < 8);
- return QualType();
- }
- }
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
std::optional<llvm::APSInt> vecSize = std::optional<llvm::APSInt> vecSize =
@@ -2455,6 +2455,11 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols,
return QualType(); return QualType();
} }
+ if (const auto *BIT = ElementTy->getAs<BitIntType>();
+ BIT &&
+ CheckBitIntElementType(*this, AttrLoc, BIT, /*ForMatrixType=*/true))
+ return QualType();
+
if (NumRows->isTypeDependent() || NumCols->isTypeDependent() || if (NumRows->isTypeDependent() || NumCols->isTypeDependent() ||
NumRows->isValueDependent() || NumCols->isValueDependent()) NumRows->isValueDependent() || NumCols->isValueDependent())
return Context.getDependentSizedMatrixType(ElementTy, NumRows, NumCols, return Context.getDependentSizedMatrixType(ElementTy, NumRows, NumCols,
clang/lib/Sema/TreeTransform.h
@@ -11777,6 +11777,28 @@ void OpenACCClauseTransform<Derived>::VisitDetachClause(
ParsedClause.getEndLoc()); ParsedClause.getEndLoc());
} }
+template <typename Derived>
+void OpenACCClauseTransform<Derived>::VisitDeleteClause(
+ const OpenACCDeleteClause &C) {
+ ParsedClause.setVarListDetails(VisitVarList(C.getVarList()),
+ /*IsReadOnly=*/false, /*IsZero=*/false);
+ NewClause = OpenACCDeleteClause::Create(
+ Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
+ ParsedClause.getEndLoc());
+}
+
+template <typename Derived>
+void OpenACCClauseTransform<Derived>::VisitUseDeviceClause(
+ const OpenACCUseDeviceClause &C) {
+ ParsedClause.setVarListDetails(VisitVarList(C.getVarList()),
+ /*IsReadOnly=*/false, /*IsZero=*/false);
+ NewClause = OpenACCUseDeviceClause::Create(
+ Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
+ ParsedClause.getEndLoc());
+}
+
template <typename Derived> template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitDevicePtrClause( void OpenACCClauseTransform<Derived>::VisitDevicePtrClause(
const OpenACCDevicePtrClause &C) { const OpenACCDevicePtrClause &C) {
@@ -12156,8 +12178,8 @@ StmtResult TreeTransform<Derived>::TransformOpenACCComputeConstruct(
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
// Transform Structured Block. // Transform Structured Block.
@@ -12183,8 +12205,8 @@ TreeTransform<Derived>::TransformOpenACCLoopConstruct(OpenACCLoopConstruct *C) {
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
// Transform Loop. // Transform Loop.
@@ -12209,8 +12231,8 @@ StmtResult TreeTransform<Derived>::TransformOpenACCCombinedConstruct(
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
// Transform Loop. // Transform Loop.
@@ -12234,8 +12256,8 @@ TreeTransform<Derived>::TransformOpenACCDataConstruct(OpenACCDataConstruct *C) {
llvm::SmallVector<OpenACCClause *> TransformedClauses = llvm::SmallVector<OpenACCClause *> TransformedClauses =
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
SemaOpenACC::AssociatedStmtRAII AssocStmtRAII( SemaOpenACC::AssociatedStmtRAII AssocStmtRAII(
@@ -12258,8 +12280,8 @@ StmtResult TreeTransform<Derived>::TransformOpenACCEnterDataConstruct(
llvm::SmallVector<OpenACCClause *> TransformedClauses = llvm::SmallVector<OpenACCClause *> TransformedClauses =
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
return getDerived().RebuildOpenACCEnterDataConstruct( return getDerived().RebuildOpenACCEnterDataConstruct(
@@ -12275,8 +12297,8 @@ StmtResult TreeTransform<Derived>::TransformOpenACCExitDataConstruct(
llvm::SmallVector<OpenACCClause *> TransformedClauses = llvm::SmallVector<OpenACCClause *> TransformedClauses =
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
return getDerived().RebuildOpenACCExitDataConstruct( return getDerived().RebuildOpenACCExitDataConstruct(
@@ -12292,8 +12314,8 @@ StmtResult TreeTransform<Derived>::TransformOpenACCHostDataConstruct(
llvm::SmallVector<OpenACCClause *> TransformedClauses = llvm::SmallVector<OpenACCClause *> TransformedClauses =
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
C->clauses()); C->clauses());
- if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),+ if (getSema().OpenACC().ActOnStartStmtDirective(
- C->getBeginLoc()))+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
return StmtError(); return StmtError();
SemaOpenACC::AssociatedStmtRAII AssocStmtRAII( SemaOpenACC::AssociatedStmtRAII AssocStmtRAII(
clang/lib/Serialization/ASTReader.cpp
@@ -3963,14 +3963,14 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
break; break;
} }
- case FUNCTION_DECL_TO_LAMBDAS_MAP:+ case RELATED_DECLS_MAP:
for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) { for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/) {
GlobalDeclID ID = ReadDeclID(F, Record, I); GlobalDeclID ID = ReadDeclID(F, Record, I);
- auto &Lambdas = FunctionToLambdasMap[ID];+ auto &RelatedDecls = RelatedDeclsMap[ID];
unsigned NN = Record[I++]; unsigned NN = Record[I++];
- Lambdas.reserve(NN);+ RelatedDecls.reserve(NN);
for (unsigned II = 0; II < NN; II++) for (unsigned II = 0; II < NN; II++)
- Lambdas.push_back(ReadDeclID(F, Record, I));+ RelatedDecls.push_back(ReadDeclID(F, Record, I));
} }
break; break;
@@ -10278,19 +10278,6 @@ void ASTReader::finishPendingActions() {
PBEnd = PendingBodies.end(); PBEnd = PendingBodies.end();
PB != PBEnd; ++PB) { PB != PBEnd; ++PB) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
- // For a function defined inline within a class template, force the
- // canonical definition to be the one inside the canonical definition of
- // the template. This ensures that we instantiate from a correct view
- // of the template.
- //
- // Sadly we can't do this more generally: we can't be sure that all
- // copies of an arbitrary class definition will have the same members
- // defined (eg, some member functions may not be instantiated, and some
- // special members may or may not have been implicitly defined).
- if (auto *RD = dyn_cast<CXXRecordDecl>(FD->getLexicalParent()))
- if (RD->isDependentContext() && !RD->isThisDeclarationADefinition())
- continue;
-
// FIXME: Check for =delete/=default? // FIXME: Check for =delete/=default?
const FunctionDecl *Defn = nullptr; const FunctionDecl *Defn = nullptr;
if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) { if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) {
@@ -12448,6 +12435,18 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
return OpenACCDetachClause::Create(getContext(), BeginLoc, LParenLoc, return OpenACCDetachClause::Create(getContext(), BeginLoc, LParenLoc,
VarList, EndLoc); VarList, EndLoc);
} }
+ case OpenACCClauseKind::Delete: {
+ SourceLocation LParenLoc = readSourceLocation();
+ llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
+ return OpenACCDeleteClause::Create(getContext(), BeginLoc, LParenLoc,
+ VarList, EndLoc);
+ }
+ case OpenACCClauseKind::UseDevice: {
+ SourceLocation LParenLoc = readSourceLocation();
+ llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
+ return OpenACCUseDeviceClause::Create(getContext(), BeginLoc, LParenLoc,
+ VarList, EndLoc);
+ }
case OpenACCClauseKind::DevicePtr: { case OpenACCClauseKind::DevicePtr: {
SourceLocation LParenLoc = readSourceLocation(); SourceLocation LParenLoc = readSourceLocation();
llvm::SmallVector<Expr *> VarList = readOpenACCVarList(); llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
@@ -12590,8 +12589,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
} }
case OpenACCClauseKind::NoHost: case OpenACCClauseKind::NoHost:
- case OpenACCClauseKind::UseDevice:
- case OpenACCClauseKind::Delete:
case OpenACCClauseKind::Device: case OpenACCClauseKind::Device:
case OpenACCClauseKind::DeviceResident: case OpenACCClauseKind::DeviceResident:
case OpenACCClauseKind::Host: case OpenACCClauseKind::Host:
clang/lib/Serialization/ASTReaderDecl.cpp
@@ -4329,13 +4329,12 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
DC->setHasExternalVisibleStorage(true); DC->setHasExternalVisibleStorage(true);
} }
- // Load any pending lambdas for the function.+ // Load any pending related decls.
- if (auto *FD = dyn_cast<FunctionDecl>(D); FD && FD->isCanonicalDecl()) {+ if (D->isCanonicalDecl()) {
- if (auto IT = FunctionToLambdasMap.find(ID);+ if (auto IT = RelatedDeclsMap.find(ID); IT != RelatedDeclsMap.end()) {
- IT != FunctionToLambdasMap.end()) {
for (auto LID : IT->second) for (auto LID : IT->second)
GetDecl(LID); GetDecl(LID);
- FunctionToLambdasMap.erase(IT);+ RelatedDeclsMap.erase(IT);
} }
} }
clang/lib/Serialization/ASTWriter.cpp
@@ -941,7 +941,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(PENDING_IMPLICIT_INSTANTIATIONS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
RECORD(UPDATE_VISIBLE); RECORD(UPDATE_VISIBLE);
RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD); RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);
- RECORD(FUNCTION_DECL_TO_LAMBDAS_MAP);+ RECORD(RELATED_DECLS_MAP);
RECORD(DECL_UPDATE_OFFSETS); RECORD(DECL_UPDATE_OFFSETS);
RECORD(DECL_UPDATES); RECORD(DECL_UPDATES);
RECORD(CUDA_SPECIAL_DECL_REFS); RECORD(CUDA_SPECIAL_DECL_REFS);
@@ -5972,23 +5972,23 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD, Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD,
DelayedNamespaceRecord); DelayedNamespaceRecord);
- if (!FunctionToLambdasMap.empty()) {+ if (!RelatedDeclsMap.empty()) {
- // TODO: on disk hash table for function to lambda mapping might be more+ // TODO: on disk hash table for related decls mapping might be more
// efficent becuase it allows lazy deserialization. // efficent becuase it allows lazy deserialization.
- RecordData FunctionToLambdasMapRecord;+ RecordData RelatedDeclsMapRecord;
- for (const auto &Pair : FunctionToLambdasMap) {+ for (const auto &Pair : RelatedDeclsMap) {
- FunctionToLambdasMapRecord.push_back(Pair.first.getRawValue());+ RelatedDeclsMapRecord.push_back(Pair.first.getRawValue());
- FunctionToLambdasMapRecord.push_back(Pair.second.size());+ RelatedDeclsMapRecord.push_back(Pair.second.size());
for (const auto &Lambda : Pair.second) for (const auto &Lambda : Pair.second)
- FunctionToLambdasMapRecord.push_back(Lambda.getRawValue());+ RelatedDeclsMapRecord.push_back(Lambda.getRawValue());
} }
auto Abv = std::make_shared<llvm::BitCodeAbbrev>(); auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
- Abv->Add(llvm::BitCodeAbbrevOp(FUNCTION_DECL_TO_LAMBDAS_MAP));+ Abv->Add(llvm::BitCodeAbbrevOp(RELATED_DECLS_MAP));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
unsigned FunctionToLambdaMapAbbrev = Stream.EmitAbbrev(std::move(Abv)); unsigned FunctionToLambdaMapAbbrev = Stream.EmitAbbrev(std::move(Abv));
- Stream.EmitRecord(FUNCTION_DECL_TO_LAMBDAS_MAP, FunctionToLambdasMapRecord,+ Stream.EmitRecord(RELATED_DECLS_MAP, RelatedDeclsMapRecord,
FunctionToLambdaMapAbbrev); FunctionToLambdaMapAbbrev);
} }
@@ -8362,6 +8362,18 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
writeOpenACCVarList(DC); writeOpenACCVarList(DC);
return; return;
} }
+ case OpenACCClauseKind::Delete: {
+ const auto *DC = cast<OpenACCDeleteClause>(C);
+ writeSourceLocation(DC->getLParenLoc());
+ writeOpenACCVarList(DC);
+ return;
+ }
+ case OpenACCClauseKind::UseDevice: {
+ const auto *UDC = cast<OpenACCUseDeviceClause>(C);
+ writeSourceLocation(UDC->getLParenLoc());
+ writeOpenACCVarList(UDC);
+ return;
+ }
case OpenACCClauseKind::DevicePtr: { case OpenACCClauseKind::DevicePtr: {
const auto *DPC = cast<OpenACCDevicePtrClause>(C); const auto *DPC = cast<OpenACCDevicePtrClause>(C);
writeSourceLocation(DPC->getLParenLoc()); writeSourceLocation(DPC->getLParenLoc());
@@ -8505,8 +8517,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
} }
case OpenACCClauseKind::NoHost: case OpenACCClauseKind::NoHost:
- case OpenACCClauseKind::UseDevice:
- case OpenACCClauseKind::Delete:
case OpenACCClauseKind::Device: case OpenACCClauseKind::Device:
case OpenACCClauseKind::DeviceResident: case OpenACCClauseKind::DeviceResident:
case OpenACCClauseKind::Host: case OpenACCClauseKind::Host:
clang/lib/Serialization/ASTWriterDecl.cpp
@@ -798,6 +798,17 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
} }
} }
+ if (D->getFriendObjectKind()) {
+ // For a function defined inline within a class template, we have to force
+ // the canonical definition to be the one inside the canonical definition of
+ // the template. Remember this relation to deserialize them together.
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalParent()))
+ if (RD->isDependentContext() && RD->isThisDeclarationADefinition()) {
+ Writer.RelatedDeclsMap[Writer.GetDeclRef(RD)].push_back(
+ Writer.GetDeclRef(D));
+ }
+ }
+
Record.push_back(D->param_size()); Record.push_back(D->param_size());
for (auto *P : D->parameters()) for (auto *P : D->parameters())
Record.AddDeclRef(P); Record.AddDeclRef(P);
@@ -1563,7 +1574,7 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
// For lambdas inside canonical FunctionDecl remember the mapping. // For lambdas inside canonical FunctionDecl remember the mapping.
if (auto FD = llvm::dyn_cast_or_null<FunctionDecl>(D->getDeclContext()); if (auto FD = llvm::dyn_cast_or_null<FunctionDecl>(D->getDeclContext());
FD && FD->isCanonicalDecl()) { FD && FD->isCanonicalDecl()) {
- Writer.FunctionToLambdasMap[Writer.GetDeclRef(FD)].push_back(+ Writer.RelatedDeclsMap[Writer.GetDeclRef(FD)].push_back(
Writer.GetDeclRef(D)); Writer.GetDeclRef(D));
} }
} else { } else {
clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp
@@ -40,6 +40,7 @@ public:
struct LocalVisitor : DynamicRecursiveASTVisitor { struct LocalVisitor : DynamicRecursiveASTVisitor {
const UncountedLambdaCapturesChecker *Checker; const UncountedLambdaCapturesChecker *Checker;
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore; llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIgnore;
+ llvm::DenseSet<const LambdaExpr *> LambdasToIgnore;
QualType ClsType; QualType ClsType;
explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker) explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker)
@@ -51,7 +52,7 @@ public:
bool TraverseCXXMethodDecl(CXXMethodDecl *CXXMD) override { bool TraverseCXXMethodDecl(CXXMethodDecl *CXXMD) override {
llvm::SaveAndRestore SavedDecl(ClsType); llvm::SaveAndRestore SavedDecl(ClsType);
- if (CXXMD && CXXMD->isInstance())+ if (CXXMD->isInstance())
ClsType = CXXMD->getThisType(); ClsType = CXXMD->getThisType();
return DynamicRecursiveASTVisitor::TraverseCXXMethodDecl(CXXMD); return DynamicRecursiveASTVisitor::TraverseCXXMethodDecl(CXXMD);
} }
@@ -61,6 +62,24 @@ public:
return result && *result; return result && *result;
} }
+ bool VisitLambdaExpr(LambdaExpr *L) override {
+ if (LambdasToIgnore.contains(L))
+ return true;
+ Checker->visitLambdaExpr(L, shouldCheckThis());
+ return true;
+ }
+
+ bool VisitVarDecl(VarDecl *VD) override {
+ auto *Init = VD->getInit();
+ if (!Init)
+ return true;
+ auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts());
+ if (!L)
+ return true;
+ LambdasToIgnore.insert(L); // Evaluate lambdas in VisitDeclRefExpr.
+ return true;
+ }
+
bool VisitDeclRefExpr(DeclRefExpr *DRE) override { bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
if (DeclRefExprsToIgnore.contains(DRE)) if (DeclRefExprsToIgnore.contains(DRE))
return true; return true;
@@ -73,6 +92,7 @@ public:
auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts()); auto *L = dyn_cast_or_null<LambdaExpr>(Init->IgnoreParenCasts());
if (!L) if (!L)
return true; return true;
+ LambdasToIgnore.insert(L);
Checker->visitLambdaExpr(L, shouldCheckThis()); Checker->visitLambdaExpr(L, shouldCheckThis());
return true; return true;
} }
@@ -95,10 +115,10 @@ public:
if (ArgIndex >= CE->getNumArgs()) if (ArgIndex >= CE->getNumArgs())
return true; return true;
auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts(); auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts();
- if (!Param->hasAttr<NoEscapeAttr>() && !TreatAllArgsAsNoEscape) {+ if (auto *L = dyn_cast_or_null<LambdaExpr>(Arg)) {
- if (auto *L = dyn_cast_or_null<LambdaExpr>(Arg)) {+ LambdasToIgnore.insert(L);
+ if (!Param->hasAttr<NoEscapeAttr>() && !TreatAllArgsAsNoEscape)
Checker->visitLambdaExpr(L, shouldCheckThis()); Checker->visitLambdaExpr(L, shouldCheckThis());
- }
} }
++ArgIndex; ++ArgIndex;
} }
@@ -117,6 +137,10 @@ public:
if (!MD || CE->getNumArgs() < 1) if (!MD || CE->getNumArgs() < 1)
return; return;
auto *Arg = CE->getArg(0)->IgnoreParenCasts(); auto *Arg = CE->getArg(0)->IgnoreParenCasts();
+ if (auto *L = dyn_cast_or_null<LambdaExpr>(Arg)) {
+ LambdasToIgnore.insert(L); // Calling a lambda upon creation is safe.
+ return;
+ }
auto *ArgRef = dyn_cast<DeclRefExpr>(Arg); auto *ArgRef = dyn_cast<DeclRefExpr>(Arg);
if (!ArgRef) if (!ArgRef)
return; return;
@@ -130,6 +154,7 @@ public:
if (!L) if (!L)
return; return;
DeclRefExprsToIgnore.insert(ArgRef); DeclRefExprsToIgnore.insert(ArgRef);
+ LambdasToIgnore.insert(L);
Checker->visitLambdaExpr(L, shouldCheckThis(), Checker->visitLambdaExpr(L, shouldCheckThis(),
/* ignoreParamVarDecl */ true); /* ignoreParamVarDecl */ true);
} }
clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -261,6 +261,11 @@ SYMBOL(data, std::ranges::, <ranges>)
SYMBOL(data, std::ranges::, <iterator>) SYMBOL(data, std::ranges::, <iterator>)
SYMBOL(cdata, std::ranges::, <ranges>) SYMBOL(cdata, std::ranges::, <ranges>)
SYMBOL(cdata, std::ranges::, <iterator>) SYMBOL(cdata, std::ranges::, <iterator>)
+// https://eel.is/c++draft/tuple.general#2:
+// In addition to being available via inclusion of the <tuple> header,
+// ignore ... is available when <utility> ... is included.
+SYMBOL(ignore, std::, <tuple>)
+SYMBOL(ignore, std::, <utility>)
// Ignore specializations // Ignore specializations
SYMBOL(hash, std::, <functional>) SYMBOL(hash, std::, <functional>)
@@ -389,18 +394,10 @@ SYMBOL(make_error_condition, std::, /*no headers*/)
SYMBOL(erase, std::, /*no headers*/) SYMBOL(erase, std::, /*no headers*/)
SYMBOL(erase_if, std::, /*no headers*/) SYMBOL(erase_if, std::, /*no headers*/)
-// cppreference symbol index page was missing these symbols.
-// Remove them when the cppreference offline archive catches up.
-SYMBOL(regular_invocable, std::, <concepts>)
-
// Symbols missing from the generated symbol map as reported by users. // Symbols missing from the generated symbol map as reported by users.
// Remove when the generator starts producing them. // Remove when the generator starts producing them.
SYMBOL(div, std::, <cstdlib>) SYMBOL(div, std::, <cstdlib>)
SYMBOL(abort, std::, <cstdlib>) SYMBOL(abort, std::, <cstdlib>)
-SYMBOL(atomic_wait, std::, <atomic>)
-SYMBOL(atomic_wait_explicit, std::, <atomic>)
-SYMBOL(move_backward, std::, <algorithm>)
-SYMBOL(month_weekday, std::chrono::, <chrono>)
SYMBOL(binary_search, std::ranges::, <algorithm>) SYMBOL(binary_search, std::ranges::, <algorithm>)
SYMBOL(equal_range, std::ranges::, <algorithm>) SYMBOL(equal_range, std::ranges::, <algorithm>)
clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
@@ -6,7 +6,7 @@
// This file was generated automatically by // This file was generated automatically by
// clang/tools/include-mapping/gen_std.py, DO NOT EDIT! // clang/tools/include-mapping/gen_std.py, DO NOT EDIT!
// //
-// Generated from cppreference offline HTML book (modified on 2024-06-10).+// Generated from cppreference offline HTML book (modified on 2024-11-10).
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
SYMBOL(ATOMIC_BOOL_LOCK_FREE, None, <atomic>) SYMBOL(ATOMIC_BOOL_LOCK_FREE, None, <atomic>)
@@ -578,6 +578,7 @@ SYMBOL(add_pointer, std::, <type_traits>)
SYMBOL(add_pointer_t, std::, <type_traits>) SYMBOL(add_pointer_t, std::, <type_traits>)
SYMBOL(add_rvalue_reference, std::, <type_traits>) SYMBOL(add_rvalue_reference, std::, <type_traits>)
SYMBOL(add_rvalue_reference_t, std::, <type_traits>) SYMBOL(add_rvalue_reference_t, std::, <type_traits>)
+SYMBOL(add_sat, std::, <numeric>)
SYMBOL(add_volatile, std::, <type_traits>) SYMBOL(add_volatile, std::, <type_traits>)
SYMBOL(add_volatile_t, std::, <type_traits>) SYMBOL(add_volatile_t, std::, <type_traits>)
SYMBOL(addressof, std::, <memory>) SYMBOL(addressof, std::, <memory>)
@@ -699,6 +700,10 @@ SYMBOL(atomic_fetch_add, std::, <atomic>)
SYMBOL(atomic_fetch_add_explicit, std::, <atomic>) SYMBOL(atomic_fetch_add_explicit, std::, <atomic>)
SYMBOL(atomic_fetch_and, std::, <atomic>) SYMBOL(atomic_fetch_and, std::, <atomic>)
SYMBOL(atomic_fetch_and_explicit, std::, <atomic>) SYMBOL(atomic_fetch_and_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_max, std::, <atomic>)
+SYMBOL(atomic_fetch_max_explicit, std::, <atomic>)
+SYMBOL(atomic_fetch_min, std::, <atomic>)
+SYMBOL(atomic_fetch_min_explicit, std::, <atomic>)
SYMBOL(atomic_fetch_or, std::, <atomic>) SYMBOL(atomic_fetch_or, std::, <atomic>)
SYMBOL(atomic_fetch_or_explicit, std::, <atomic>) SYMBOL(atomic_fetch_or_explicit, std::, <atomic>)
SYMBOL(atomic_fetch_sub, std::, <atomic>) SYMBOL(atomic_fetch_sub, std::, <atomic>)
@@ -727,6 +732,8 @@ SYMBOL(atomic_signal_fence, std::, <atomic>)
SYMBOL(atomic_store, std::, <atomic>) SYMBOL(atomic_store, std::, <atomic>)
SYMBOL(atomic_store_explicit, std::, <atomic>) SYMBOL(atomic_store_explicit, std::, <atomic>)
SYMBOL(atomic_thread_fence, std::, <atomic>) SYMBOL(atomic_thread_fence, std::, <atomic>)
+SYMBOL(atomic_wait, std::, <atomic>)
+SYMBOL(atomic_wait_explicit, std::, <atomic>)
SYMBOL(atto, std::, <ratio>) SYMBOL(atto, std::, <ratio>)
SYMBOL(auto_ptr, std::, <memory>) SYMBOL(auto_ptr, std::, <memory>)
SYMBOL(back_insert_iterator, std::, <iterator>) SYMBOL(back_insert_iterator, std::, <iterator>)
@@ -829,6 +836,8 @@ SYMBOL(boolalpha, std::, <ios>)
SYMBOL(boolalpha, std::, <iostream>) SYMBOL(boolalpha, std::, <iostream>)
SYMBOL(boyer_moore_horspool_searcher, std::, <functional>) SYMBOL(boyer_moore_horspool_searcher, std::, <functional>)
SYMBOL(boyer_moore_searcher, std::, <functional>) SYMBOL(boyer_moore_searcher, std::, <functional>)
+SYMBOL(breakpoint, std::, <debugging>)
+SYMBOL(breakpoint_if_debugging, std::, <debugging>)
SYMBOL(bsearch, std::, <cstdlib>) SYMBOL(bsearch, std::, <cstdlib>)
SYMBOL(bsearch, None, <cstdlib>) SYMBOL(bsearch, None, <cstdlib>)
SYMBOL(bsearch, None, <stdlib.h>) SYMBOL(bsearch, None, <stdlib.h>)
@@ -951,6 +960,7 @@ SYMBOL(copy_constructible, std::, <concepts>)
SYMBOL(copy_if, std::, <algorithm>) SYMBOL(copy_if, std::, <algorithm>)
SYMBOL(copy_n, std::, <algorithm>) SYMBOL(copy_n, std::, <algorithm>)
SYMBOL(copyable, std::, <concepts>) SYMBOL(copyable, std::, <concepts>)
+SYMBOL(copyable_function, std::, <functional>)
SYMBOL(copysign, std::, <cmath>) SYMBOL(copysign, std::, <cmath>)
SYMBOL(copysign, None, <cmath>) SYMBOL(copysign, None, <cmath>)
SYMBOL(copysign, None, <math.h>) SYMBOL(copysign, None, <math.h>)
@@ -1048,12 +1058,14 @@ SYMBOL(dextents, std::, <mdspan>)
SYMBOL(difftime, std::, <ctime>) SYMBOL(difftime, std::, <ctime>)
SYMBOL(difftime, None, <ctime>) SYMBOL(difftime, None, <ctime>)
SYMBOL(difftime, None, <time.h>) SYMBOL(difftime, None, <time.h>)
+SYMBOL(dims, std::, <mdspan>)
SYMBOL(disable_sized_sentinel_for, std::, <iterator>) SYMBOL(disable_sized_sentinel_for, std::, <iterator>)
SYMBOL(discard_block_engine, std::, <random>) SYMBOL(discard_block_engine, std::, <random>)
SYMBOL(discrete_distribution, std::, <random>) SYMBOL(discrete_distribution, std::, <random>)
SYMBOL(disjunction, std::, <type_traits>) SYMBOL(disjunction, std::, <type_traits>)
SYMBOL(disjunction_v, std::, <type_traits>) SYMBOL(disjunction_v, std::, <type_traits>)
SYMBOL(distance, std::, <iterator>) SYMBOL(distance, std::, <iterator>)
+SYMBOL(div_sat, std::, <numeric>)
SYMBOL(div_t, std::, <cstdlib>) SYMBOL(div_t, std::, <cstdlib>)
SYMBOL(div_t, None, <cstdlib>) SYMBOL(div_t, None, <cstdlib>)
SYMBOL(div_t, None, <stdlib.h>) SYMBOL(div_t, None, <stdlib.h>)
@@ -1077,6 +1089,7 @@ SYMBOL(emit_on_flush, std::, <ostream>)
SYMBOL(emit_on_flush, std::, <iostream>) SYMBOL(emit_on_flush, std::, <iostream>)
SYMBOL(enable_if, std::, <type_traits>) SYMBOL(enable_if, std::, <type_traits>)
SYMBOL(enable_if_t, std::, <type_traits>) SYMBOL(enable_if_t, std::, <type_traits>)
+SYMBOL(enable_nonlocking_formatter_optimization, std::, <format>)
SYMBOL(enable_shared_from_this, std::, <memory>) SYMBOL(enable_shared_from_this, std::, <memory>)
SYMBOL(endian, std::, <bit>) SYMBOL(endian, std::, <bit>)
SYMBOL(endl, std::, <ostream>) SYMBOL(endl, std::, <ostream>)
@@ -1241,8 +1254,7 @@ SYMBOL(fgetwc, None, <wchar.h>)
SYMBOL(fgetws, std::, <cwchar>) SYMBOL(fgetws, std::, <cwchar>)
SYMBOL(fgetws, None, <cwchar>) SYMBOL(fgetws, None, <cwchar>)
SYMBOL(fgetws, None, <wchar.h>) SYMBOL(fgetws, None, <wchar.h>)
-SYMBOL(filebuf, std::, <streambuf>)+SYMBOL(filebuf, std::, <fstream>)
-SYMBOL(filebuf, std::, <iostream>)
SYMBOL(filebuf, std::, <iosfwd>) SYMBOL(filebuf, std::, <iosfwd>)
SYMBOL(fill, std::, <algorithm>) SYMBOL(fill, std::, <algorithm>)
SYMBOL(fill_n, std::, <algorithm>) SYMBOL(fill_n, std::, <algorithm>)
@@ -1322,11 +1334,13 @@ SYMBOL(format, std::, <format>)
SYMBOL(format_args, std::, <format>) SYMBOL(format_args, std::, <format>)
SYMBOL(format_context, std::, <format>) SYMBOL(format_context, std::, <format>)
SYMBOL(format_error, std::, <format>) SYMBOL(format_error, std::, <format>)
+SYMBOL(format_kind, std::, <format>)
SYMBOL(format_parse_context, std::, <format>) SYMBOL(format_parse_context, std::, <format>)
SYMBOL(format_string, std::, <format>) SYMBOL(format_string, std::, <format>)
SYMBOL(format_to, std::, <format>) SYMBOL(format_to, std::, <format>)
SYMBOL(format_to_n, std::, <format>) SYMBOL(format_to_n, std::, <format>)
SYMBOL(format_to_n_result, std::, <format>) SYMBOL(format_to_n_result, std::, <format>)
+SYMBOL(formattable, std::, <format>)
SYMBOL(formatted_size, std::, <format>) SYMBOL(formatted_size, std::, <format>)
SYMBOL(formatter, std::, <format>) SYMBOL(formatter, std::, <format>)
SYMBOL(forward, std::, <utility>) SYMBOL(forward, std::, <utility>)
@@ -1398,6 +1412,7 @@ SYMBOL(ftell, std::, <cstdio>)
SYMBOL(ftell, None, <cstdio>) SYMBOL(ftell, None, <cstdio>)
SYMBOL(ftell, None, <stdio.h>) SYMBOL(ftell, None, <stdio.h>)
SYMBOL(function, std::, <functional>) SYMBOL(function, std::, <functional>)
+SYMBOL(function_ref, std::, <functional>)
SYMBOL(future, std::, <future>) SYMBOL(future, std::, <future>)
SYMBOL(future_category, std::, <future>) SYMBOL(future_category, std::, <future>)
SYMBOL(future_errc, std::, <future>) SYMBOL(future_errc, std::, <future>)
@@ -1488,7 +1503,6 @@ SYMBOL(hypotl, None, <math.h>)
SYMBOL(identity, std::, <functional>) SYMBOL(identity, std::, <functional>)
SYMBOL(ifstream, std::, <fstream>) SYMBOL(ifstream, std::, <fstream>)
SYMBOL(ifstream, std::, <iosfwd>) SYMBOL(ifstream, std::, <iosfwd>)
-SYMBOL(ignore, std::, <tuple>)
SYMBOL(ilogb, std::, <cmath>) SYMBOL(ilogb, std::, <cmath>)
SYMBOL(ilogb, None, <cmath>) SYMBOL(ilogb, None, <cmath>)
SYMBOL(ilogb, None, <math.h>) SYMBOL(ilogb, None, <math.h>)
@@ -1544,6 +1558,7 @@ SYMBOL(inner_product, std::, <numeric>)
SYMBOL(inout_ptr, std::, <memory>) SYMBOL(inout_ptr, std::, <memory>)
SYMBOL(inout_ptr_t, std::, <memory>) SYMBOL(inout_ptr_t, std::, <memory>)
SYMBOL(inplace_merge, std::, <algorithm>) SYMBOL(inplace_merge, std::, <algorithm>)
+SYMBOL(inplace_vector, std::, <inplace_vector>)
SYMBOL(input_iterator, std::, <iterator>) SYMBOL(input_iterator, std::, <iterator>)
SYMBOL(input_iterator_tag, std::, <iterator>) SYMBOL(input_iterator_tag, std::, <iterator>)
SYMBOL(input_or_output_iterator, std::, <iterator>) SYMBOL(input_or_output_iterator, std::, <iterator>)
@@ -1649,6 +1664,7 @@ SYMBOL(is_copy_assignable_v, std::, <type_traits>)
SYMBOL(is_copy_constructible, std::, <type_traits>) SYMBOL(is_copy_constructible, std::, <type_traits>)
SYMBOL(is_copy_constructible_v, std::, <type_traits>) SYMBOL(is_copy_constructible_v, std::, <type_traits>)
SYMBOL(is_corresponding_member, std::, <type_traits>) SYMBOL(is_corresponding_member, std::, <type_traits>)
+SYMBOL(is_debugger_present, std::, <debugging>)
SYMBOL(is_default_constructible, std::, <type_traits>) SYMBOL(is_default_constructible, std::, <type_traits>)
SYMBOL(is_default_constructible_v, std::, <type_traits>) SYMBOL(is_default_constructible_v, std::, <type_traits>)
SYMBOL(is_destructible, std::, <type_traits>) SYMBOL(is_destructible, std::, <type_traits>)
@@ -1790,6 +1806,8 @@ SYMBOL(is_union, std::, <type_traits>)
SYMBOL(is_union_v, std::, <type_traits>) SYMBOL(is_union_v, std::, <type_traits>)
SYMBOL(is_unsigned, std::, <type_traits>) SYMBOL(is_unsigned, std::, <type_traits>)
SYMBOL(is_unsigned_v, std::, <type_traits>) SYMBOL(is_unsigned_v, std::, <type_traits>)
+SYMBOL(is_virtual_base_of, std::, <type_traits>)
+SYMBOL(is_virtual_base_of_v, std::, <type_traits>)
SYMBOL(is_void, std::, <type_traits>) SYMBOL(is_void, std::, <type_traits>)
SYMBOL(is_void_v, std::, <type_traits>) SYMBOL(is_void_v, std::, <type_traits>)
SYMBOL(is_volatile, std::, <type_traits>) SYMBOL(is_volatile, std::, <type_traits>)
@@ -1938,7 +1956,9 @@ SYMBOL(latch, std::, <latch>)
SYMBOL(launch, std::, <future>) SYMBOL(launch, std::, <future>)
SYMBOL(launder, std::, <new>) SYMBOL(launder, std::, <new>)
SYMBOL(layout_left, std::, <mdspan>) SYMBOL(layout_left, std::, <mdspan>)
+SYMBOL(layout_left_padded, std::, <mdspan>)
SYMBOL(layout_right, std::, <mdspan>) SYMBOL(layout_right, std::, <mdspan>)
+SYMBOL(layout_right_padded, std::, <mdspan>)
SYMBOL(layout_stride, std::, <mdspan>) SYMBOL(layout_stride, std::, <mdspan>)
SYMBOL(lcm, std::, <numeric>) SYMBOL(lcm, std::, <numeric>)
SYMBOL(lconv, std::, <clocale>) SYMBOL(lconv, std::, <clocale>)
@@ -2222,6 +2242,7 @@ SYMBOL(moneypunct, std::, <locale>)
SYMBOL(moneypunct_byname, std::, <locale>) SYMBOL(moneypunct_byname, std::, <locale>)
SYMBOL(monostate, std::, <variant>) SYMBOL(monostate, std::, <variant>)
SYMBOL(movable, std::, <concepts>) SYMBOL(movable, std::, <concepts>)
+SYMBOL(move_backward, std::, <algorithm>)
SYMBOL(move_constructible, std::, <concepts>) SYMBOL(move_constructible, std::, <concepts>)
SYMBOL(move_if_noexcept, std::, <utility>) SYMBOL(move_if_noexcept, std::, <utility>)
SYMBOL(move_iterator, std::, <iterator>) SYMBOL(move_iterator, std::, <iterator>)
@@ -2229,6 +2250,7 @@ SYMBOL(move_only_function, std::, <functional>)
SYMBOL(move_sentinel, std::, <iterator>) SYMBOL(move_sentinel, std::, <iterator>)
SYMBOL(mt19937, std::, <random>) SYMBOL(mt19937, std::, <random>)
SYMBOL(mt19937_64, std::, <random>) SYMBOL(mt19937_64, std::, <random>)
+SYMBOL(mul_sat, std::, <numeric>)
SYMBOL(multimap, std::, <map>) SYMBOL(multimap, std::, <map>)
SYMBOL(multiplies, std::, <functional>) SYMBOL(multiplies, std::, <functional>)
SYMBOL(multiset, std::, <set>) SYMBOL(multiset, std::, <set>)
@@ -2283,6 +2305,8 @@ SYMBOL(noboolalpha, std::, <iostream>)
SYMBOL(noemit_on_flush, std::, <ostream>) SYMBOL(noemit_on_flush, std::, <ostream>)
SYMBOL(noemit_on_flush, std::, <iostream>) SYMBOL(noemit_on_flush, std::, <iostream>)
SYMBOL(none_of, std::, <algorithm>) SYMBOL(none_of, std::, <algorithm>)
+SYMBOL(nontype, std::, <utility>)
+SYMBOL(nontype_t, std::, <utility>)
SYMBOL(noop_coroutine, std::, <coroutine>) SYMBOL(noop_coroutine, std::, <coroutine>)
SYMBOL(noop_coroutine_handle, std::, <coroutine>) SYMBOL(noop_coroutine_handle, std::, <coroutine>)
SYMBOL(noop_coroutine_promise, std::, <coroutine>) SYMBOL(noop_coroutine_promise, std::, <coroutine>)
@@ -2442,6 +2466,8 @@ SYMBOL(random_access_iterator_tag, std::, <iterator>)
SYMBOL(random_device, std::, <random>) SYMBOL(random_device, std::, <random>)
SYMBOL(random_shuffle, std::, <algorithm>) SYMBOL(random_shuffle, std::, <algorithm>)
SYMBOL(range_error, std::, <stdexcept>) SYMBOL(range_error, std::, <stdexcept>)
+SYMBOL(range_format, std::, <format>)
+SYMBOL(range_formatter, std::, <format>)
SYMBOL(rank, std::, <type_traits>) SYMBOL(rank, std::, <type_traits>)
SYMBOL(rank_v, std::, <type_traits>) SYMBOL(rank_v, std::, <type_traits>)
SYMBOL(ranlux24, std::, <random>) SYMBOL(ranlux24, std::, <random>)
@@ -2486,6 +2512,7 @@ SYMBOL(regex_search, std::, <regex>)
SYMBOL(regex_token_iterator, std::, <regex>) SYMBOL(regex_token_iterator, std::, <regex>)
SYMBOL(regex_traits, std::, <regex>) SYMBOL(regex_traits, std::, <regex>)
SYMBOL(regular, std::, <concepts>) SYMBOL(regular, std::, <concepts>)
+SYMBOL(regular_invocable, std::, <concepts>)
SYMBOL(reinterpret_pointer_cast, std::, <memory>) SYMBOL(reinterpret_pointer_cast, std::, <memory>)
SYMBOL(relation, std::, <concepts>) SYMBOL(relation, std::, <concepts>)
SYMBOL(relaxed, std::, <memory>) SYMBOL(relaxed, std::, <memory>)
@@ -2580,8 +2607,10 @@ SYMBOL(roundl, std::, <cmath>)
SYMBOL(roundl, None, <cmath>) SYMBOL(roundl, None, <cmath>)
SYMBOL(roundl, None, <math.h>) SYMBOL(roundl, None, <math.h>)
SYMBOL(runtime_error, std::, <stdexcept>) SYMBOL(runtime_error, std::, <stdexcept>)
+SYMBOL(runtime_format, std::, <format>)
SYMBOL(same_as, std::, <concepts>) SYMBOL(same_as, std::, <concepts>)
SYMBOL(sample, std::, <algorithm>) SYMBOL(sample, std::, <algorithm>)
+SYMBOL(saturate_cast, std::, <numeric>)
SYMBOL(scalbln, std::, <cmath>) SYMBOL(scalbln, std::, <cmath>)
SYMBOL(scalbln, None, <cmath>) SYMBOL(scalbln, None, <cmath>)
SYMBOL(scalbln, None, <math.h>) SYMBOL(scalbln, None, <math.h>)
@@ -2786,6 +2815,7 @@ SYMBOL(strftime, None, <ctime>)
SYMBOL(strftime, None, <time.h>) SYMBOL(strftime, None, <time.h>)
SYMBOL(strict, std::, <memory>) SYMBOL(strict, std::, <memory>)
SYMBOL(strict_weak_order, std::, <concepts>) SYMBOL(strict_weak_order, std::, <concepts>)
+SYMBOL(strided_slice, std::, <mdspan>)
SYMBOL(string, std::, <string>) SYMBOL(string, std::, <string>)
SYMBOL(string_view, std::, <string_view>) SYMBOL(string_view, std::, <string_view>)
SYMBOL(stringbuf, std::, <sstream>) SYMBOL(stringbuf, std::, <sstream>)
@@ -2857,6 +2887,8 @@ SYMBOL(strxfrm, None, <cstring>)
SYMBOL(strxfrm, None, <string.h>) SYMBOL(strxfrm, None, <string.h>)
SYMBOL(student_t_distribution, std::, <random>) SYMBOL(student_t_distribution, std::, <random>)
SYMBOL(sub_match, std::, <regex>) SYMBOL(sub_match, std::, <regex>)
+SYMBOL(sub_sat, std::, <numeric>)
+SYMBOL(submdspan_mapping_result, std::, <mdspan>)
SYMBOL(subtract_with_carry_engine, std::, <random>) SYMBOL(subtract_with_carry_engine, std::, <random>)
SYMBOL(suspend_always, std::, <coroutine>) SYMBOL(suspend_always, std::, <coroutine>)
SYMBOL(suspend_never, std::, <coroutine>) SYMBOL(suspend_never, std::, <coroutine>)
@@ -2897,6 +2929,7 @@ SYMBOL(tanl, None, <math.h>)
SYMBOL(tera, std::, <ratio>) SYMBOL(tera, std::, <ratio>)
SYMBOL(terminate, std::, <exception>) SYMBOL(terminate, std::, <exception>)
SYMBOL(terminate_handler, std::, <exception>) SYMBOL(terminate_handler, std::, <exception>)
+SYMBOL(text_encoding, std::, <text_encoding>)
SYMBOL(tgamma, std::, <cmath>) SYMBOL(tgamma, std::, <cmath>)
SYMBOL(tgamma, None, <cmath>) SYMBOL(tgamma, None, <cmath>)
SYMBOL(tgamma, None, <math.h>) SYMBOL(tgamma, None, <math.h>)
@@ -3127,7 +3160,9 @@ SYMBOL(visit, std::, <variant>)
SYMBOL(visit_format_arg, std::, <format>) SYMBOL(visit_format_arg, std::, <format>)
SYMBOL(void_t, std::, <type_traits>) SYMBOL(void_t, std::, <type_traits>)
SYMBOL(vprint_nonunicode, std::, <print>) SYMBOL(vprint_nonunicode, std::, <print>)
+SYMBOL(vprint_nonunicode_buffered, std::, <print>)
SYMBOL(vprint_unicode, std::, <print>) SYMBOL(vprint_unicode, std::, <print>)
+SYMBOL(vprint_unicode_buffered, std::, <print>)
SYMBOL(vprintf, std::, <cstdio>) SYMBOL(vprintf, std::, <cstdio>)
SYMBOL(vprintf, None, <cstdio>) SYMBOL(vprintf, None, <cstdio>)
SYMBOL(vprintf, None, <stdio.h>) SYMBOL(vprintf, None, <stdio.h>)
@@ -3156,6 +3191,7 @@ SYMBOL(vwscanf, std::, <cwchar>)
SYMBOL(vwscanf, None, <cwchar>) SYMBOL(vwscanf, None, <cwchar>)
SYMBOL(vwscanf, None, <wchar.h>) SYMBOL(vwscanf, None, <wchar.h>)
SYMBOL(wbuffer_convert, std::, <locale>) SYMBOL(wbuffer_convert, std::, <locale>)
+SYMBOL(wbuffer_convert, std::, <locale>)
SYMBOL(wcerr, std::, <iostream>) SYMBOL(wcerr, std::, <iostream>)
SYMBOL(wcin, std::, <iostream>) SYMBOL(wcin, std::, <iostream>)
SYMBOL(wclog, std::, <iostream>) SYMBOL(wclog, std::, <iostream>)
@@ -3274,8 +3310,7 @@ SYMBOL(weak_ordering, std::, <compare>)
SYMBOL(weak_ptr, std::, <memory>) SYMBOL(weak_ptr, std::, <memory>)
SYMBOL(weakly_incrementable, std::, <iterator>) SYMBOL(weakly_incrementable, std::, <iterator>)
SYMBOL(weibull_distribution, std::, <random>) SYMBOL(weibull_distribution, std::, <random>)
-SYMBOL(wfilebuf, std::, <streambuf>)+SYMBOL(wfilebuf, std::, <fstream>)
-SYMBOL(wfilebuf, std::, <iostream>)
SYMBOL(wfilebuf, std::, <iosfwd>) SYMBOL(wfilebuf, std::, <iosfwd>)
SYMBOL(wformat_args, std::, <format>) SYMBOL(wformat_args, std::, <format>)
SYMBOL(wformat_context, std::, <format>) SYMBOL(wformat_context, std::, <format>)
@@ -3348,6 +3383,7 @@ SYMBOL(wstreampos, std::, <iosfwd>)
SYMBOL(wstreampos, std::, <iosfwd>) SYMBOL(wstreampos, std::, <iosfwd>)
SYMBOL(wstring, std::, <string>) SYMBOL(wstring, std::, <string>)
SYMBOL(wstring_convert, std::, <locale>) SYMBOL(wstring_convert, std::, <locale>)
+SYMBOL(wstring_convert, std::, <locale>)
SYMBOL(wstring_view, std::, <string_view>) SYMBOL(wstring_view, std::, <string_view>)
SYMBOL(wstringbuf, std::, <sstream>) SYMBOL(wstringbuf, std::, <sstream>)
SYMBOL(wstringbuf, std::, <iosfwd>) SYMBOL(wstringbuf, std::, <iosfwd>)
@@ -3423,6 +3459,7 @@ SYMBOL(minutes, std::chrono::, <chrono>)
SYMBOL(month, std::chrono::, <chrono>) SYMBOL(month, std::chrono::, <chrono>)
SYMBOL(month_day, std::chrono::, <chrono>) SYMBOL(month_day, std::chrono::, <chrono>)
SYMBOL(month_day_last, std::chrono::, <chrono>) SYMBOL(month_day_last, std::chrono::, <chrono>)
+SYMBOL(month_weekday, std::chrono::, <chrono>)
SYMBOL(month_weekday_last, std::chrono::, <chrono>) SYMBOL(month_weekday_last, std::chrono::, <chrono>)
SYMBOL(nanoseconds, std::chrono::, <chrono>) SYMBOL(nanoseconds, std::chrono::, <chrono>)
SYMBOL(nonexistent_local_time, std::chrono::, <chrono>) SYMBOL(nonexistent_local_time, std::chrono::, <chrono>)
@@ -3605,6 +3642,7 @@ SYMBOL(chunk_view, std::ranges::, <ranges>)
SYMBOL(clamp, std::ranges::, <algorithm>) SYMBOL(clamp, std::ranges::, <algorithm>)
SYMBOL(common_range, std::ranges::, <ranges>) SYMBOL(common_range, std::ranges::, <ranges>)
SYMBOL(common_view, std::ranges::, <ranges>) SYMBOL(common_view, std::ranges::, <ranges>)
+SYMBOL(concat_view, std::ranges::, <ranges>)
SYMBOL(const_iterator_t, std::ranges::, <ranges>) SYMBOL(const_iterator_t, std::ranges::, <ranges>)
SYMBOL(constant_range, std::ranges::, <ranges>) SYMBOL(constant_range, std::ranges::, <ranges>)
SYMBOL(construct_at, std::ranges::, <memory>) SYMBOL(construct_at, std::ranges::, <memory>)
@@ -3629,11 +3667,13 @@ SYMBOL(disable_sized_range, std::ranges::, <ranges>)
SYMBOL(distance, std::ranges::, <iterator>) SYMBOL(distance, std::ranges::, <iterator>)
SYMBOL(drop_view, std::ranges::, <ranges>) SYMBOL(drop_view, std::ranges::, <ranges>)
SYMBOL(drop_while_view, std::ranges::, <ranges>) SYMBOL(drop_while_view, std::ranges::, <ranges>)
+SYMBOL(elements_of, std::ranges::, <ranges>)
SYMBOL(elements_view, std::ranges::, <ranges>) SYMBOL(elements_view, std::ranges::, <ranges>)
SYMBOL(empty_view, std::ranges::, <ranges>) SYMBOL(empty_view, std::ranges::, <ranges>)
SYMBOL(enable_borrowed_range, std::ranges::, <ranges>) SYMBOL(enable_borrowed_range, std::ranges::, <ranges>)
SYMBOL(enable_view, std::ranges::, <ranges>) SYMBOL(enable_view, std::ranges::, <ranges>)
SYMBOL(ends_with, std::ranges::, <algorithm>) SYMBOL(ends_with, std::ranges::, <algorithm>)
+SYMBOL(enumerate_view, std::ranges::, <ranges>)
SYMBOL(equal, std::ranges::, <algorithm>) SYMBOL(equal, std::ranges::, <algorithm>)
SYMBOL(equal_to, std::ranges::, <functional>) SYMBOL(equal_to, std::ranges::, <functional>)
SYMBOL(fill, std::ranges::, <algorithm>) SYMBOL(fill, std::ranges::, <algorithm>)
@@ -3833,11 +3873,13 @@ SYMBOL(cartesian_product, std::ranges::views::, <ranges>)
SYMBOL(chunk, std::ranges::views::, <ranges>) SYMBOL(chunk, std::ranges::views::, <ranges>)
SYMBOL(chunk_by, std::ranges::views::, <ranges>) SYMBOL(chunk_by, std::ranges::views::, <ranges>)
SYMBOL(common, std::ranges::views::, <ranges>) SYMBOL(common, std::ranges::views::, <ranges>)
+SYMBOL(concat, std::ranges::views::, <ranges>)
SYMBOL(counted, std::ranges::views::, <ranges>) SYMBOL(counted, std::ranges::views::, <ranges>)
SYMBOL(drop, std::ranges::views::, <ranges>) SYMBOL(drop, std::ranges::views::, <ranges>)
SYMBOL(drop_while, std::ranges::views::, <ranges>) SYMBOL(drop_while, std::ranges::views::, <ranges>)
SYMBOL(elements, std::ranges::views::, <ranges>) SYMBOL(elements, std::ranges::views::, <ranges>)
SYMBOL(empty, std::ranges::views::, <ranges>) SYMBOL(empty, std::ranges::views::, <ranges>)
+SYMBOL(enumerate, std::ranges::views::, <ranges>)
SYMBOL(filter, std::ranges::views::, <ranges>) SYMBOL(filter, std::ranges::views::, <ranges>)
SYMBOL(iota, std::ranges::views::, <ranges>) SYMBOL(iota, std::ranges::views::, <ranges>)
SYMBOL(istream, std::ranges::views::, <ranges>) SYMBOL(istream, std::ranges::views::, <ranges>)
@@ -3914,11 +3956,13 @@ SYMBOL(cartesian_product, std::views::, <ranges>)
SYMBOL(chunk, std::views::, <ranges>) SYMBOL(chunk, std::views::, <ranges>)
SYMBOL(chunk_by, std::views::, <ranges>) SYMBOL(chunk_by, std::views::, <ranges>)
SYMBOL(common, std::views::, <ranges>) SYMBOL(common, std::views::, <ranges>)
+SYMBOL(concat, std::views::, <ranges>)
SYMBOL(counted, std::views::, <ranges>) SYMBOL(counted, std::views::, <ranges>)
SYMBOL(drop, std::views::, <ranges>) SYMBOL(drop, std::views::, <ranges>)
SYMBOL(drop_while, std::views::, <ranges>) SYMBOL(drop_while, std::views::, <ranges>)
SYMBOL(elements, std::views::, <ranges>) SYMBOL(elements, std::views::, <ranges>)
SYMBOL(empty, std::views::, <ranges>) SYMBOL(empty, std::views::, <ranges>)
+SYMBOL(enumerate, std::views::, <ranges>)
SYMBOL(filter, std::views::, <ranges>) SYMBOL(filter, std::views::, <ranges>)
SYMBOL(iota, std::views::, <ranges>) SYMBOL(iota, std::views::, <ranges>)
SYMBOL(istream, std::views::, <ranges>) SYMBOL(istream, std::views::, <ranges>)
clang/runtime/CMakeLists.txt
@@ -122,7 +122,7 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
COMPONENT compiler-rt) COMPONENT compiler-rt)
# Add top-level targets that build specific compiler-rt runtimes. # Add top-level targets that build specific compiler-rt runtimes.
- set(COMPILER_RT_RUNTIMES fuzzer asan builtins dfsan lsan msan profile tsan ubsan ubsan-minimal)+ set(COMPILER_RT_RUNTIMES fuzzer asan builtins dfsan lsan msan profile tsan tysan ubsan ubsan-minimal)
foreach(runtime ${COMPILER_RT_RUNTIMES}) foreach(runtime ${COMPILER_RT_RUNTIMES})
get_ext_project_build_command(build_runtime_cmd ${runtime}) get_ext_project_build_command(build_runtime_cmd ${runtime})
add_custom_target(${runtime} add_custom_target(${runtime}
clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -507,3 +507,11 @@ typedef bool bool9 __attribute__((ext_vector_type(9)));
// both-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}} // both-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}}
// both-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}} // both-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}}
constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0}); constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0});
+
+// both-warning@+2 {{returning reference to local temporary object}}
+// both-note@+1 {{temporary created here}}
+constexpr const intptr_t &returns_local() { return 0L; }
+
+// both-error@+2 {{constexpr variable 'test_nullptr_bad' must be initialized by a constant expression}}
+// both-note@+1 {{read of temporary whose lifetime has ended}}
+constexpr nullptr_t test_nullptr_bad = __builtin_bit_cast(nullptr_t, returns_local());
clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1270,4 +1270,19 @@ namespace Memcmp {
static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 7) != 0); static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 7) != 0);
static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 6) != 0); static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 6) != 0);
static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 5) == 0); static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 5) == 0);
+
+
+ static_assert(__builtin_wmemcmp(L"abaa", L"abba", 3) == -1);
+ static_assert(__builtin_wmemcmp(L"abaa", L"abba", 2) == 0);
+ static_assert(__builtin_wmemcmp(0, 0, 0) == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wmemcmp(L"a\x83838383", L"aa", 2) ==
+ (wchar_t)-1U >> 31);
+#endif
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0banana", 100) == 0); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 100) == -1); // FIXME: Should we reject this?
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 7) == -1);
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 6) == -1);
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 5) == 0);
} }
clang/test/AST/ByteCode/functions.cpp
@@ -303,21 +303,17 @@ namespace ReturnLocalPtr {
return &a; // both-warning {{address of stack memory}} return &a; // both-warning {{address of stack memory}}
} }
- /// GCC rejects the expression below, just like the new interpreter. The current interpreter+ /// FIXME: Both interpreters should diagnose this. We're returning a pointer to a local
- /// however accepts it and only warns about the function above returning an address to stack+ /// variable.
- /// memory. If we change the condition to 'p() != nullptr', it even succeeds.+ static_assert(p() == nullptr, ""); // both-error {{static assertion failed}}
- static_assert(p() == nullptr, ""); // ref-error {{static assertion failed}} \+
- // expected-error {{not an integral constant expression}}
-
- /// FIXME: The current interpreter emits diagnostics in the reference case below, but the
- /// new one does not.
constexpr const int &p2() { constexpr const int &p2() {
- int a = 12; // ref-note {{declared here}}+ int a = 12; // both-note {{declared here}}
return a; // both-warning {{reference to stack memory associated with local variable}} return a; // both-warning {{reference to stack memory associated with local variable}}
} }
static_assert(p2() == 12, ""); // both-error {{not an integral constant expression}} \ static_assert(p2() == 12, ""); // both-error {{not an integral constant expression}} \
- // ref-note {{read of variable whose lifetime has ended}}+ // both-note {{read of variable whose lifetime has ended}}
} }
namespace VoidReturn { namespace VoidReturn {
clang/test/AST/ByteCode/shifts.cpp
@@ -1,7 +1,9 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,all %s // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,all %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=cxx17,all %s // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=cxx17,all %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=cxx17,all -triple armv8 %s
// RUN: %clang_cc1 -std=c++20 -verify=ref,all %s // RUN: %clang_cc1 -std=c++20 -verify=ref,all %s
// RUN: %clang_cc1 -std=c++17 -verify=ref-cxx17,all %s // RUN: %clang_cc1 -std=c++17 -verify=ref-cxx17,all %s
+// RUN: %clang_cc1 -std=c++17 -verify=ref-cxx17,all -triple armv8 %s
#define INT_MIN (~__INT_MAX__) #define INT_MIN (~__INT_MAX__)
@@ -21,27 +23,15 @@ namespace shifts {
c = 1 << 0; c = 1 << 0;
c = 1 << -0; c = 1 << -0;
c = 1 >> -0; c = 1 >> -0;
- c = 1 << -1; // expected-warning {{shift count is negative}} \+ c = 1 << -1; // all-warning {{shift count is negative}} \
- // expected-note {{negative shift count -1}} \+ // all-note {{negative shift count -1}}
- // cxx17-note {{negative shift count -1}} \
- // cxx17-warning {{shift count is negative}} \
- // ref-warning {{shift count is negative}} \
- // ref-note {{negative shift count -1}} \
- // ref-cxx17-warning {{shift count is negative}} \
- // ref-cxx17-note {{negative shift count -1}}
c = 1 >> -1; // expected-warning {{shift count is negative}} \ c = 1 >> -1; // expected-warning {{shift count is negative}} \
// cxx17-warning {{shift count is negative}} \ // cxx17-warning {{shift count is negative}} \
// ref-warning {{shift count is negative}} \ // ref-warning {{shift count is negative}} \
// ref-cxx17-warning {{shift count is negative}} // ref-cxx17-warning {{shift count is negative}}
- c = 1 << (unsigned)-1; // expected-warning {{shift count >= width of type}} \+ c = 1 << (unsigned)-1; // all-warning {{shift count >= width of type}} \
- // expected-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}} \+ // all-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}}
- // cxx17-warning {{shift count >= width of type}} \
- // cxx17-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}} \
- // ref-warning {{shift count >= width of type}} \
- // ref-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}} \
- // ref-cxx17-warning {{shift count >= width of type}} \
- // ref-cxx17-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}}
c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}} \ c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}} \
// cxx17-warning {{shift count >= width of type}} \ // cxx17-warning {{shift count >= width of type}} \
// ref-warning {{shift count >= width of type}} \ // ref-warning {{shift count >= width of type}} \
@@ -212,3 +202,28 @@ enum shiftof {
X3 = (1<<32) // all-error {{expression is not an integral constant expression}} \ X3 = (1<<32) // all-error {{expression is not an integral constant expression}} \
// all-note {{shift count 32 >= width of type 'int'}} // all-note {{shift count 32 >= width of type 'int'}}
}; };
+
+#if __WCHAR_WIDTH__ == 32
+# if !defined(__WCHAR_UNSIGNED__)
+static_assert(((wchar_t)-1U >> 31) == -1);
+# else
+static_assert(((wchar_t)-1U >> 31) == 1);
+# endif
+#endif
+
+#if __INT_WIDTH__ == 32
+static_assert(((int)-1U >> 32) == -1); // all-error {{not an integral constant expression}} \
+ // all-note {{shift count 32 >= width of type 'int' (32 bits)}}
+#endif
+
+static_assert((-4 << 32) == 0); // all-error {{not an integral constant expression}} \
+ // all-note {{shift count}}
+
+static_assert((-4 << 1) == -8); // ref-cxx17-error {{not an integral constant expression}} \
+ // ref-cxx17-note {{left shift of negative value -4}} \
+ // cxx17-error {{not an integral constant expression}} \
+ // cxx17-note {{left shift of negative value -4}}
+static_assert((-4 << 31) == 0); // ref-cxx17-error {{not an integral constant expression}} \
+ // ref-cxx17-note {{left shift of negative value -4}} \
+ // cxx17-error {{not an integral constant expression}} \
+ // cxx17-note {{left shift of negative value -4}}
clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -87,6 +87,21 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'unsigned int' ParmVar 0x{{[0-9A-Fa-f]+}} 'Index' 'unsigned int' // CHECK-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'unsigned int' ParmVar 0x{{[0-9A-Fa-f]+}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline // CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
+// CHECK-NEXT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Load 'element_type (unsigned int)'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Index 'unsigned int'
+// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
+// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
+// CHECK-NEXT: UnaryOperator 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' prefix '*' cannot overflow
+// CHECK-NEXT: CallExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type *'
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '<builtin fn type>' Function 0x{{[0-9A-Fa-f]+}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '__hlsl_resource_t
+// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME: ' lvalue .__handle 0x{{[0-9A-Fa-f]+}}
+// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'unsigned int' ParmVar 0x{{[0-9A-Fa-f]+}} 'Index' 'unsigned int'
+// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
+
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class [[RESOURCE]] definition // CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class [[RESOURCE]] definition
// CHECK: TemplateArgument type 'float' // CHECK: TemplateArgument type 'float'
clang/test/AST/ast-print-openacc-data-construct.cpp
@@ -10,8 +10,8 @@ void foo() {
#pragma acc data default(none) #pragma acc data default(none)
; ;
-// CHECK: #pragma acc data device_type(int)+// CHECK: #pragma acc data default(none) device_type(int)
-#pragma acc data device_type(int)+#pragma acc data default(none) device_type(int)
; ;
// CHECK: #pragma acc enter data copyin(Var) // CHECK: #pragma acc enter data copyin(Var)
@@ -20,8 +20,7 @@ void foo() {
// CHECK: #pragma acc exit data copyout(Var) // CHECK: #pragma acc exit data copyout(Var)
#pragma acc exit data copyout(Var) #pragma acc exit data copyout(Var)
; ;
-// CHECK: #pragma acc host_data+// CHECK: #pragma acc host_data use_device(Var)
-// CHECK-NOT: use_device(Var)
#pragma acc host_data use_device(Var) #pragma acc host_data use_device(Var)
; ;
@@ -38,7 +37,7 @@ void foo() {
// CHECK: #pragma acc exit data copyout(Var) if(i == array[1]) // CHECK: #pragma acc exit data copyout(Var) if(i == array[1])
#pragma acc exit data copyout(Var) if(i == array[1]) #pragma acc exit data copyout(Var) if(i == array[1])
; ;
-// CHECK: #pragma acc host_data if(i == array[1])+// CHECK: #pragma acc host_data use_device(Var) if(i == array[1])
#pragma acc host_data use_device(Var) if(i == array[1]) #pragma acc host_data use_device(Var) if(i == array[1])
; ;
@@ -114,10 +113,20 @@ void foo() {
// CHECK: #pragma acc exit data copyout(i) finalize // CHECK: #pragma acc exit data copyout(i) finalize
#pragma acc exit data copyout(i) finalize #pragma acc exit data copyout(i) finalize
-// CHECK: #pragma acc host_data if_present+// CHECK: #pragma acc host_data use_device(i) if_present
#pragma acc host_data use_device(i) if_present #pragma acc host_data use_device(i) if_present
; ;
// CHECK: #pragma acc exit data copyout(i) detach(iPtr, arrayPtr[0]) // CHECK: #pragma acc exit data copyout(i) detach(iPtr, arrayPtr[0])
#pragma acc exit data copyout(i) detach(iPtr, arrayPtr[0]) #pragma acc exit data copyout(i) detach(iPtr, arrayPtr[0])
+// CHECK: #pragma acc exit data copyout(i) delete(i, array[1], array, array[1:2])
+#pragma acc exit data copyout(i) delete(i, array[1], array, array[1:2])
+ ;
+
+// CHECK: #pragma acc exit data copyout(i) delete(i, array[1], array, array[1:2])
+#pragma acc exit data copyout(i) delete(i, array[1], array, array[1:2])
+
+// CHECK: #pragma acc host_data use_device(i)
+#pragma acc host_data use_device(i)
+ ;
} }
clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
@@ -1,16 +1,72 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker -verify %s
-struct A {+#include "mock-types.h"
- static void b();+
+namespace WTF {
+
+namespace Detail {
+
+template<typename Out, typename... In>
+class CallableWrapperBase {
+public:
+ virtual ~CallableWrapperBase() { }
+ virtual Out call(In...) = 0;
+};
+
+template<typename, typename, typename...> class CallableWrapper;
+
+template<typename CallableType, typename Out, typename... In>
+class CallableWrapper : public CallableWrapperBase<Out, In...> {
+public:
+ explicit CallableWrapper(CallableType& callable)
+ : m_callable(callable) { }
+ Out call(In... in) final { return m_callable(in...); }
+
+private:
+ CallableType m_callable;
+};
+
+} // namespace Detail
+
+template<typename> class Function;
+
+template<typename Out, typename... In> Function<Out(In...)> adopt(Detail::CallableWrapperBase<Out, In...>*);
+
+template <typename Out, typename... In>
+class Function<Out(In...)> {
+public:
+ using Impl = Detail::CallableWrapperBase<Out, In...>;
+
+ Function() = default;
+
+ template<typename FunctionType>
+ Function(FunctionType f)
+ : m_callableWrapper(new Detail::CallableWrapper<FunctionType, Out, In...>(f)) { }
+
+ Out operator()(In... in) const { return m_callableWrapper->call(in...); }
+ explicit operator bool() const { return !!m_callableWrapper; }
+
+private:
+ enum AdoptTag { Adopt };
+ Function(Impl* impl, AdoptTag)
+ : m_callableWrapper(impl)
+ {
+ }
+
+ friend Function adopt<Out, In...>(Impl*);
+
+ std::unique_ptr<Impl> m_callableWrapper;
}; };
-struct RefCountable {+template<typename Out, typename... In> Function<Out(In...)> adopt(Detail::CallableWrapperBase<Out, In...>* impl)
- void ref() {}+{
- void deref() {}+ return Function<Out(In...)>(impl, Function<Out(In...)>::Adopt);
- void method();+}
- void constMethod() const;+
- int trivial() { return 123; }+} // namespace WTF
- RefCountable* next();+
+struct A {
+ static void b();
}; };
RefCountable* make_obj(); RefCountable* make_obj();
@@ -185,3 +241,21 @@ void lambda_with_args(RefCountable* obj) {
}; };
trivial_lambda(1); trivial_lambda(1);
} }
+
+void callFunctionOpaque(WTF::Function<void()>&&);
+void callFunction(WTF::Function<void()>&& function) {
+ someFunction();
+ function();
+}
+
+void lambda_converted_to_function(RefCountable* obj)
+{
+ callFunction([&]() {
+ obj->method();
+ // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
+ });
+ callFunctionOpaque([&]() {
+ obj->method();
+ // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
+ });
+}
clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11,cxx11-17 -pedantic %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11,cxx11-17 -pedantic %s
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify=expected,cxx11-17,since-cxx17 -pedantic %s // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify=expected,cxx11-17,since-cxx17 -pedantic %s
// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=expected,since-cxx17 -pedantic %s // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=expected,since-cxx17 -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify=expected,since-cxx17 -pedantic %s
struct [[nodiscard]] S {}; struct [[nodiscard]] S {};
// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}} // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
@@ -134,3 +135,50 @@ void usage() {
static_cast<double>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw away as a double}} static_cast<double>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw away as a double}}
} }
} // namespace p1771 } // namespace p1771
+
+namespace discarded_member_access {
+struct X {
+ union {
+ int variant_member;
+ };
+ struct { // expected-warning {{anonymous structs are a GNU extension}}
+ int anonymous_struct_member;
+ };
+ int data_member;
+ static int static_data_member;
+ enum {
+ unscoped_enum
+ };
+ enum class scoped_enum_t {
+ scoped_enum
+ };
+ using enum scoped_enum_t;
+ // cxx11-17-warning@-1 {{using enum declaration is a C++20 extension}}
+
+ void implicit_object_member_function();
+ static void static_member_function();
+#if __cplusplus >= 202302L
+ void explicit_object_member_function(this X self);
+#endif
+};
+
+[[nodiscard]] X get_X();
+// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
+void f() {
+ (void) get_X().variant_member;
+ (void) get_X().anonymous_struct_member;
+ (void) get_X().data_member;
+ (void) get_X().static_data_member;
+ // expected-warning@-1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (void) get_X().unscoped_enum;
+ // expected-warning@-1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (void) get_X().scoped_enum;
+ // expected-warning@-1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (void) get_X().implicit_object_member_function();
+ (void) get_X().static_member_function();
+ // expected-warning@-1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if __cplusplus >= 202302L
+ (void) get_X().explicit_object_member_function();
+#endif
+}
+} // namespace discarded_member_access
clang/test/CXX/drs/cwg28xx.cpp
@@ -30,7 +30,25 @@ using U2 = decltype(&main);
#endif #endif
} // namespace cwg2811 } // namespace cwg2811
-namespace cwg2819 { // cwg2819: 19+namespace cwg2813 { // cwg2813: 20
+#if __cplusplus >= 202302L
+struct X {
+ X() = default;
+
+ X(const X&) = delete;
+ X& operator=(const X&) = delete;
+
+ void f(this X self) { }
+};
+
+void f() {
+ X{}.f();
+}
+#endif
+} // namespace cwg2813
+
+namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01
+
#if __cpp_constexpr >= 202306L #if __cpp_constexpr >= 202306L
constexpr void* p = nullptr; constexpr void* p = nullptr;
constexpr int* q = static_cast<int*>(p); constexpr int* q = static_cast<int*>(p);
clang/test/CXX/temp/temp.res/p4.cpp
@@ -185,3 +185,23 @@ template<typename T> struct S {
friend void X::f(T::type); friend void X::f(T::type);
}; };
} }
+
+namespace GH113324 {
+template <typename = int> struct S1 {
+ friend void f1(S1, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
+ friend void f2(S1 a, S1 = decltype(a){}); // expected-error {{friend declaration specifying a default argument must be a definition}}
+};
+
+template <class T> using alias = int;
+template <typename T> struct S2 {
+ // FIXME: We miss diagnosing the default argument instantiation failure
+ // (forming reference to void)
+ friend void f3(S2, int a = alias<T &>(1)); // expected-error {{friend declaration specifying a default argument must be a definition}}
+};
+
+void test() {
+ f1(S1<>{});
+ f2(S1<>{});
+ f3(S2<void>());
+}
+} // namespace GH113324
clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_mla.c
@@ -0,0 +1,316 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -DSME_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -DSME_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme-f8f16 -target-feature +sme-f8f32 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
+#include <arm_sme.h>
+
+#ifdef SME_OVERLOADED_FORMS
+#define SME_ACLE_FUNC(A1, A2_UNUSED, A3, A4_UNUSED, A5) A1##A3##A5
+#else
+#define SME_ACLE_FUNC(A1, A2, A3, A4, A5) A1##A2##A3##A4##A5
+#endif
+
+// FMLAL (indexed)
+
+// CHECK-LABEL: define dso_local void @test_svmla_lane_za16_vg2x1(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.lane.za16.vg2x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]], i32 0)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z26test_svmla_lane_za16_vg2x1ju13__SVMfloat8_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.lane.za16.vg2x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]], i32 0)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_lane_za16_vg2x1(uint32_t slice, svmfloat8_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_lane_za16,_mf8,_vg2x1_fpm,,)(slice, zn, zm, 0, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_lane_za16_vg2x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.lane.za16.vg2x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 15)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z26test_svmla_lane_za16_vg2x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.lane.za16.vg2x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 15)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_lane_za16_vg2x2(uint32_t slice, svmfloat8x2_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_lane_za16,_mf8,_vg2x2_fpm,,)(slice, zn, zm, 15, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_lane_za16_vg2x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.lane.za16.vg2x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]], i32 7)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z26test_svmla_lane_za16_vg2x4j13svmfloat8x4_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.lane.za16.vg2x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]], i32 7)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_lane_za16_vg2x4(uint32_t slice, svmfloat8x4_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_lane_za16,_mf8,_vg2x4_fpm,,)(slice, zn, zm, 7, fpm);
+}
+
+// FMLALL (indexed)
+
+// CHECK-LABEL: define dso_local void @test_svmla_lane_za32_vg4x1(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.lane.za32.vg4x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]], i32 0)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z26test_svmla_lane_za32_vg4x1ju13__SVMfloat8_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.lane.za32.vg4x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]], i32 0)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_lane_za32_vg4x1(uint32_t slice, svmfloat8_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_lane_za32,_mf8,_vg4x1_fpm,,)(slice, zn, zm, 0, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_lane_za32_vg4x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.lane.za32.vg4x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 15)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z26test_svmla_lane_za32_vg4x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.lane.za32.vg4x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 15)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_lane_za32_vg4x2(uint32_t slice, svmfloat8x2_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_lane_za32,_mf8,_vg4x2_fpm,,)(slice, zn, zm, 15, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_lane_za32_vg4x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.lane.za32.vg4x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]], i32 7)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z26test_svmla_lane_za32_vg4x4j13svmfloat8x4_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.lane.za32.vg4x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]], i32 7)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_lane_za32_vg4x4(uint32_t slice, svmfloat8x4_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_lane_za32,_mf8,_vg4x4_fpm,,)(slice, zn, zm, 7, fpm);
+}
+
+// FMLAL (single)
+
+// CHECK-LABEL: define dso_local void @test_svmla_single_za16_vg2x1(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.single.za16.vg2x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z28test_svmla_single_za16_vg2x1ju13__SVMfloat8_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.single.za16.vg2x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_single_za16_vg2x1(uint32_t slice, svmfloat8_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla,_single,_za16,_mf8,_vg2x1_fpm)(slice, zn, zm, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_single_za16_vg2x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.single.za16.vg2x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z28test_svmla_single_za16_vg2x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.single.za16.vg2x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_single_za16_vg2x2(uint32_t slice, svmfloat8x2_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla,_single,_za16,_mf8,_vg2x2_fpm)(slice, zn, zm, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_single_za16_vg2x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.single.za16.vg2x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z28test_svmla_single_za16_vg2x4j13svmfloat8x4_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.single.za16.vg2x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_single_za16_vg2x4(uint32_t slice, svmfloat8x4_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla,_single,_za16,_mf8,_vg2x4_fpm)(slice, zn, zm, fpm);
+}
+
+// FMLALL (single)
+
+// CHECK-LABEL: define dso_local void @test_svmla_single_za32_vg4x1(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.single.za32.vg4x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z28test_svmla_single_za32_vg4x1ju13__SVMfloat8_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.single.za32.vg4x1(i32 [[SLICE]], <vscale x 16 x i8> [[ZN]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_single_za32_vg4x1(uint32_t slice, svmfloat8_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla,_single,_za32,_mf8,_vg4x1_fpm)(slice, zn, zm, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_single_za32_vg4x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.single.za32.vg4x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z28test_svmla_single_za32_vg4x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.single.za32.vg4x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_single_za32_vg4x2(uint32_t slice, svmfloat8x2_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla,_single,_za32,_mf8,_vg4x2_fpm)(slice, zn, zm, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_single_za32_vg4x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.single.za32.vg4x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z28test_svmla_single_za32_vg4x4j13svmfloat8x4_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.single.za32.vg4x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_single_za32_vg4x4(uint32_t slice, svmfloat8x4_t zn, svmfloat8_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla,_single,_za32,_mf8,_vg4x4_fpm)(slice, zn, zm, fpm);
+}
+
+// FMLAL (multi)
+
+// CHECK-LABEL: define dso_local void @test_svmla_multi_za16_vg2x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.multi.za16.vg2x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z27test_svmla_multi_za16_vg2x2j13svmfloat8x2_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.multi.za16.vg2x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_multi_za16_vg2x2(uint32_t slice, svmfloat8x2_t zn, svmfloat8x2_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_za16,_mf8,_vg2x2_fpm,,)(slice, zn, zm, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_multi_za16_vg2x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.multi.za16.vg2x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z27test_svmla_multi_za16_vg2x4j13svmfloat8x4_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlal.multi.za16.vg2x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_multi_za16_vg2x4(uint32_t slice, svmfloat8x4_t zn, svmfloat8x4_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_za16,_mf8,_vg2x4_fpm,,)(slice, zn, zm, fpm);
+}
+
+// FMLALL (multi)
+
+// CHECK-LABEL: define dso_local void @test_svmla_multi_za32_vg4x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.multi.za32.vg4x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z27test_svmla_multi_za32_vg4x2j13svmfloat8x2_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.multi.za32.vg4x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_multi_za32_vg4x2(uint32_t slice, svmfloat8x2_t zn, svmfloat8x2_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_za32,_mf8,_vg4x2_fpm,,)(slice, zn, zm, fpm);
+}
+
+// CHECK-LABEL: define dso_local void @test_svmla_multi_za32_vg4x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.multi.za32.vg4x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z27test_svmla_multi_za32_vg4x4j13svmfloat8x4_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPM:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPM]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fmlall.multi.za32.vg4x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svmla_multi_za32_vg4x4(uint32_t slice, svmfloat8x4_t zn, svmfloat8x4_t zm, fpm_t fpm) __arm_streaming __arm_inout("za") {
+ SME_ACLE_FUNC(svmla_za32,_mf8,_vg4x4_fpm,,)(slice, zn, zm, fpm);
+}
clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_fp8_fdot.c
@@ -1,18 +1,18 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// REQUIRES: aarch64-registered-target // REQUIRES: aarch64-registered-target
-#include <arm_sme.h>
// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s // RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s
// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s
// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -target-feature -S -disable-O0-optnone -Werror -Wall -o /dev/null %s // RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -target-feature -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
#include <arm_sme.h> #include <arm_sme.h>
#ifdef SVE_OVERLOADED_FORMS #ifdef SVE_OVERLOADED_FORMS
-#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3) A1##A3+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED,A5) A1##A3##A5
#else #else
-#define SVE_ACLE_FUNC(A1,A2,A3) A1##A2##A3+#define SVE_ACLE_FUNC(A1,A2,A3,A4,A5) A1##A2##A3##A4##A5
#endif #endif
// CHECK-LABEL: define dso_local void @test_svdot_lane_za32_f8_vg1x2( // CHECK-LABEL: define dso_local void @test_svdot_lane_za32_f8_vg1x2(
@@ -32,7 +32,7 @@
void test_svdot_lane_za32_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn, void test_svdot_lane_za32_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
svmfloat8_t zm, fpm_t fpmr) svmfloat8_t zm, fpm_t fpmr)
__arm_streaming __arm_inout("za") { __arm_streaming __arm_inout("za") {
- SVE_ACLE_FUNC(svdot_lane_za32,_mf8,_vg1x2_fpm)(slice, zn, zm, 3, fpmr);+ SVE_ACLE_FUNC(svdot_lane_za32,_mf8,_vg1x2_fpm,,)(slice, zn, zm, 3, fpmr);
} }
// CHECK-LABEL: define dso_local void @test_svdot_lane_za32_f8_vg1x4( // CHECK-LABEL: define dso_local void @test_svdot_lane_za32_f8_vg1x4(
@@ -52,7 +52,7 @@ void test_svdot_lane_za32_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
void test_svdot_lane_za32_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn, void test_svdot_lane_za32_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
svmfloat8_t zm, fpm_t fpmr) svmfloat8_t zm, fpm_t fpmr)
__arm_streaming __arm_inout("za") { __arm_streaming __arm_inout("za") {
- SVE_ACLE_FUNC(svdot_lane_za32,_mf8,_vg1x4_fpm)(slice, zn, zm, 3, fpmr);+ SVE_ACLE_FUNC(svdot_lane_za32,_mf8,_vg1x4_fpm,,)(slice, zn, zm, 3, fpmr);
} }
// CHECK-LABEL: define dso_local void @test_svdot_lane_za16_f8_vg1x2( // CHECK-LABEL: define dso_local void @test_svdot_lane_za16_f8_vg1x2(
@@ -72,7 +72,7 @@ void test_svdot_lane_za32_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
void test_svdot_lane_za16_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn, void test_svdot_lane_za16_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
svmfloat8_t zm, fpm_t fpmr) svmfloat8_t zm, fpm_t fpmr)
__arm_streaming __arm_inout("za") { __arm_streaming __arm_inout("za") {
- SVE_ACLE_FUNC(svdot_lane_za16,_mf8,_vg1x2_fpm)(slice, zn, zm, 3, fpmr);+ SVE_ACLE_FUNC(svdot_lane_za16,_mf8,_vg1x2_fpm,,)(slice, zn, zm, 3, fpmr);
} }
// CHECK-LABEL: define dso_local void @test_svdot_lane_za16_f8_vg1x4( // CHECK-LABEL: define dso_local void @test_svdot_lane_za16_f8_vg1x4(
@@ -92,5 +92,165 @@ void test_svdot_lane_za16_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
void test_svdot_lane_za16_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn, void test_svdot_lane_za16_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
svmfloat8_t zm, fpm_t fpmr) svmfloat8_t zm, fpm_t fpmr)
__arm_streaming __arm_inout("za") { __arm_streaming __arm_inout("za") {
- SVE_ACLE_FUNC(svdot_lane_za16,_mf8,_vg1x4_fpm)(slice, zn, zm, 3, fpmr);+ SVE_ACLE_FUNC(svdot_lane_za16,_mf8,_vg1x4_fpm,,)(slice, zn, zm, 3, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_single_za32_f8_vg1x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za32.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z31test_svdot_single_za32_f8_vg1x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za32.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_single_za32_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,_single,_za32,_mf8,_vg1x2_fpm)(slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_single_za32_f8_vg1x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z31test_svdot_single_za32_f8_vg1x4j13svmfloat8x4_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_single_za32_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
+ svmfloat8_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,_single,_za32,_mf8,_vg1x4_fpm)(slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_multi_za32_f8_vg1x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za32.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z30test_svdot_multi_za32_f8_vg1x2j13svmfloat8x2_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za32.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_multi_za32_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8x2_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,,_za32,_mf8,_vg1x2_fpm) (slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_multi_za32_f8_vg1x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z30test_svdot_multi_za32_f8_vg1x4j13svmfloat8x4_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_multi_za32_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
+ svmfloat8x4_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,,_za32,_mf8,_vg1x4_fpm)(slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_single_za16_f8_vg1x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za16.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z31test_svdot_single_za16_f8_vg1x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za16.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_single_za16_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,_single,_za16,_mf8,_vg1x2_fpm)(slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_single_za16_f8_vg1x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za16.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z31test_svdot_single_za16_f8_vg1x4j13svmfloat8x4_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.single.za16.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_single_za16_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
+ svmfloat8_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,_single,_za16,_mf8,_vg1x4_fpm)(slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_multi_za16_f8_vg1x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za16.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z30test_svdot_multi_za16_f8_vg1x2j13svmfloat8x2_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za16.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_multi_za16_f8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8x2_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,,_za16,_mf8,_vg1x2_fpm) (slice, zn, zm, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svdot_multi_za16_f8_vg1x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za16.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z30test_svdot_multi_za16_f8_vg1x4j13svmfloat8x4_tS_m(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZN_COERCE2:%.*]], <vscale x 16 x i8> [[ZN_COERCE3:%.*]], <vscale x 16 x i8> [[ZM_COERCE0:%.*]], <vscale x 16 x i8> [[ZM_COERCE1:%.*]], <vscale x 16 x i8> [[ZM_COERCE2:%.*]], <vscale x 16 x i8> [[ZM_COERCE3:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: [[ENTRY:.*:]]
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fdot.multi.za16.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZN_COERCE2]], <vscale x 16 x i8> [[ZN_COERCE3]], <vscale x 16 x i8> [[ZM_COERCE0]], <vscale x 16 x i8> [[ZM_COERCE1]], <vscale x 16 x i8> [[ZM_COERCE2]], <vscale x 16 x i8> [[ZM_COERCE3]])
+// CPP-CHECK-NEXT: ret void
+//
+void test_svdot_multi_za16_f8_vg1x4(uint32_t slice, svmfloat8x4_t zn,
+ svmfloat8x4_t zm, fpm_t fpmr)
+ __arm_streaming __arm_inout("za") {
+ SVE_ACLE_FUNC(svdot,,_za16,_mf8,_vg1x4_fpm)(slice, zn, zm, fpmr);
} }
clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_fp8_fvdot.c
@@ -0,0 +1,80 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -target-feature +sme-f8f16 -target-feature +sme-f8f32 -target-feature -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sme.h>
+
+#ifdef SVE_OVERLOADED_FORMS
+#define SVE_ACLE_FUNC(A1, A2_UNUSED, A3) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1, A2, A3) A1##A2##A3
+#endif
+
+// CHECK-LABEL: define dso_local void @test_svvdot_lane_za16_mf8_vg1x2(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fvdot.lane.za16.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 7)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z31test_svvdot_lane_za16_mf8_vg1x2j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT: entry:
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fvdot.lane.za16.vg1x2(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 7)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svvdot_lane_za16_mf8_vg1x2(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8_t zm,
+ fpm_t fpmr) __arm_streaming
+ __arm_inout("za") {
+ SVE_ACLE_FUNC(svvdot_lane_za16, _mf8, _vg1x2_fpm)(slice, zn, zm, 7, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svvdotb_lane_za32_mf8_vg1x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fvdotb.lane.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 3)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z32test_svvdotb_lane_za32_mf8_vg1x4j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: entry:
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fvdotb.lane.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 3)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svvdotb_lane_za32_mf8_vg1x4(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8_t zm,
+ fpm_t fpmr) __arm_streaming
+ __arm_inout("za") {
+ SVE_ACLE_FUNC(svvdotb_lane_za32, _mf8, _vg1x4_fpm)(slice, zn, zm, 3, fpmr);
+}
+
+// CHECK-LABEL: define dso_local void @test_svvdott_lane_za32_mf8_vg1x4(
+// CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fvdott.lane.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 3)
+// CHECK-NEXT: ret void
+//
+// CPP-CHECK-LABEL: define dso_local void @_Z32test_svvdott_lane_za32_mf8_vg1x4j13svmfloat8x2_tu13__SVMfloat8_tm(
+// CPP-CHECK-SAME: i32 noundef [[SLICE:%.*]], <vscale x 16 x i8> [[ZN_COERCE0:%.*]], <vscale x 16 x i8> [[ZN_COERCE1:%.*]], <vscale x 16 x i8> [[ZM:%.*]], i64 noundef [[FPMR:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT: entry:
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR]])
+// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.fp8.fvdott.lane.za32.vg1x4(i32 [[SLICE]], <vscale x 16 x i8> [[ZN_COERCE0]], <vscale x 16 x i8> [[ZN_COERCE1]], <vscale x 16 x i8> [[ZM]], i32 3)
+// CPP-CHECK-NEXT: ret void
+//
+void test_svvdott_lane_za32_mf8_vg1x4(uint32_t slice, svmfloat8x2_t zn,
+ svmfloat8_t zm,
+ fpm_t fpmr) __arm_streaming
+ __arm_inout("za") {
+ SVE_ACLE_FUNC(svvdott_lane_za32, _mf8, _vg1x4_fpm)(slice, zn, zm, 3, fpmr);
+}
clang/test/CodeGen/attr-counted-by.c
@@ -1043,7 +1043,7 @@ int test12_a, test12_b;
// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR11:[0-9]+]] // NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR11:[0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] // NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]]+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]]
@@ -1085,7 +1085,7 @@ int test12_a, test12_b;
// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR9:[0-9]+]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR9:[0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]]+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]]
clang/test/CodeGen/memtag-globals.cpp
@@ -10,6 +10,7 @@
// RUN: FileCheck %s --check-prefix=IGNORELIST // RUN: FileCheck %s --check-prefix=IGNORELIST
int global; int global;
+int __attribute__((__section__("my_section"))) section_global;
int __attribute__((no_sanitize("memtag"))) attributed_global; int __attribute__((no_sanitize("memtag"))) attributed_global;
int __attribute__((disable_sanitizer_instrumentation)) disable_instrumentation_global; int __attribute__((disable_sanitizer_instrumentation)) disable_instrumentation_global;
int ignorelisted_global; int ignorelisted_global;
@@ -24,6 +25,8 @@ void func() {
// CHECK: @{{.*}}extra_global{{.*}} ={{.*}} sanitize_memtag // CHECK: @{{.*}}extra_global{{.*}} ={{.*}} sanitize_memtag
// CHECK: @{{.*}}global{{.*}} ={{.*}} sanitize_memtag // CHECK: @{{.*}}global{{.*}} ={{.*}} sanitize_memtag
+// CHECK: @{{.*}}section_global{{.*}} =
+// CHECK-NOT: sanitize_memtag
// CHECK: @{{.*}}attributed_global{{.*}} = // CHECK: @{{.*}}attributed_global{{.*}} =
// CHECK-NOT: sanitize_memtag // CHECK-NOT: sanitize_memtag
// CHECK: @{{.*}}disable_instrumentation_global{{.*}} = // CHECK: @{{.*}}disable_instrumentation_global{{.*}} =
@@ -32,7 +35,7 @@ void func() {
// CHECK-NOT: sanitize_memtag // CHECK-NOT: sanitize_memtag
// CHECK: @{{.*}}static_var{{.*}} ={{.*}} sanitize_memtag // CHECK: @{{.*}}static_var{{.*}} ={{.*}} sanitize_memtag
-// CHECK: @{{.*}} = {{.*}} c"Hello, world!\00"{{.*}} sanitize_memtag+// CHECK: @{{.*}} = {{.*}} c"Hello, world!\00"{{.*}}
// CHECK: @{{.*}}external_global{{.*}} ={{.*}} sanitize_memtag // CHECK: @{{.*}}external_global{{.*}} ={{.*}} sanitize_memtag
// IGNORELIST: @{{.*}}extra_global{{.*}} ={{.*}} sanitize_memtag // IGNORELIST: @{{.*}}extra_global{{.*}} ={{.*}} sanitize_memtag
clang/test/CodeGen/ptrauth-module-flags.c
@@ -1,8 +1,13 @@
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF // RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefix=PERSONALITY
// ELFGOT: !llvm.module.flags = !{ // ELFGOT: !llvm.module.flags = !{
// ELFGOT-SAME: !1 // ELFGOT-SAME: !1
// ELFGOT: !1 = !{i32 8, !"ptrauth-elf-got", i32 1} // ELFGOT: !1 = !{i32 8, !"ptrauth-elf-got", i32 1}
+// PERSONALITY: !llvm.module.flags = !{
+// PERSONALITY-SAME: !1
+// PERSONALITY: !1 = !{i32 8, !"ptrauth-sign-personality", i32 1}
+
// OFF-NOT: "ptrauth- // OFF-NOT: "ptrauth-
clang/test/CodeGen/sanitize-type-attr.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -fsanitize=type | FileCheck -check-prefix=TYSAN %s
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -fsanitize=type -fsanitize-blacklist=%t | FileCheck -check-prefix=BL %s
+
+// The sanitize_type attribute should be attached to functions
+// when TypeSanitizer is enabled, unless no_sanitize("type") attribute
+// is present.
+
+// WITHOUT: NoTYSAN1{{.*}}) [[NOATTR:#[0-9]+]]
+// BL: NoTYSAN1{{.*}}) [[NOATTR:#[0-9]+]]
+// TYSAN: NoTYSAN1{{.*}}) [[NOATTR:#[0-9]+]]
+__attribute__((no_sanitize("type"))) int NoTYSAN1(int *a) { return *a; }
+
+// WITHOUT: NoTYSAN2{{.*}}) [[NOATTR]]
+// BL: NoTYSAN2{{.*}}) [[NOATTR]]
+// TYSAN: NoTYSAN2{{.*}}) [[NOATTR]]
+__attribute__((no_sanitize("type"))) int NoTYSAN2(int *a);
+int NoTYSAN2(int *a) { return *a; }
+
+// WITHOUT: NoTYSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// BL: NoTYSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// TYSAN: NoTYSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+__attribute__((no_sanitize("type"))) int NoTYSAN3(int *a) { return *a; }
+
+// WITHOUT: TYSANOk{{.*}}) [[NOATTR]]
+// BL: TYSANOk{{.*}}) [[NOATTR]]
+// TYSAN: TYSANOk{{.*}}) [[WITH:#[0-9]+]]
+int TYSANOk(int *a) { return *a; }
+
+// WITHOUT: TemplateTYSANOk{{.*}}) [[NOATTR]]
+// BL: TemplateTYSANOk{{.*}}) [[NOATTR]]
+// TYSAN: TemplateTYSANOk{{.*}}) [[WITH]]
+template <int i>
+int TemplateTYSANOk() { return i; }
+
+// WITHOUT: TemplateNoTYSAN{{.*}}) [[NOATTR]]
+// BL: TemplateNoTYSAN{{.*}}) [[NOATTR]]
+// TYSAN: TemplateNoTYSAN{{.*}}) [[NOATTR]]
+template <int i>
+__attribute__((no_sanitize("type"))) int TemplateNoTYSAN() { return i; }
+
+int force_instance = TemplateTYSANOk<42>() + TemplateNoTYSAN<42>();
+
+// Check that __cxx_global_var_init* get the sanitize_type attribute.
+int global1 = 0;
+int global2 = *(int *)((char *)&global1 + 1);
+// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
+// BL: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
+// TYSAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
+
+// Make sure that we don't add globals to the list for which we don't have a
+// specific type description.
+// FIXME: We now have a type description for this type and a global is added. Should it?
+struct SX {
+ int a, b;
+};
+SX sx;
+
+void consumer(const char *);
+
+void char_caller() {
+ // TYSAN: void @_Z11char_callerv()
+ // TYSAN-NEXT: entry:
+ // TYSAN-NEXT: call void @_Z8consumerPKc(ptr noundef @.str)
+ // TYSAN-NEXT: ret void
+
+ consumer("foo");
+}
+
+// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+
+// BL: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+
+// TYSAN: attributes [[NOATTR]] = { mustprogress noinline nounwind{{.*}} }
+// TYSAN: attributes [[WITH]] = { noinline nounwind sanitize_type{{.*}} }
+
+// TYSAN-DAG: !llvm.tysan.globals = !{[[G1MD:![0-9]+]], [[G2MD:![0-9]+]], [[G3MD:![0-9]+]], [[SXMD:![0-9]+]]}
+// TYSAN-DAG: [[G1MD]] = !{ptr @force_instance, [[INTMD:![0-9]+]]}
+// TYSAN-DAG: [[INTMD]] = !{!"int",
+// TYSAN-DAG: [[G2MD]] = !{ptr @global1, [[INTMD]]}
+// TYSAN-DAG: [[G3MD]] = !{ptr @global2, [[INTMD]]}
+// TYSAN-DAG: [[SXMD]] = !{ptr @sx, [[SXTYMD:![0-9]+]]}
+// TYSAN-DAG: [[SXTYMD]] = !{!"_ZTS2SX", [[INTMD]], i64 0, !1, i64 4}
+// TYSAN-DAG: Simple C++ TBAA
clang/test/CodeGen/union-tbaa1.c
@@ -16,17 +16,17 @@ void bar(vect32 p[][2]);
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR]], i32 [[TMP0]] // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR]], i32 [[TMP0]]
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
// CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP1]], [[NUM]] // CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP1]], [[NUM]]
-// CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP0]]+// CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP0]]
// CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 8, !tbaa [[TBAA6:![0-9]+]] // CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 8, !tbaa [[TBAA6:![0-9]+]]
// CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR]], i32 [[TMP0]], i32 1 // CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR]], i32 [[TMP0]], i32 1
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]]
// CHECK-NEXT: [[MUL6:%.*]] = mul i32 [[TMP2]], [[NUM]] // CHECK-NEXT: [[MUL6:%.*]] = mul i32 [[TMP2]], [[NUM]]
-// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP0]], i32 1+// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP0]], i32 1
// CHECK-NEXT: store i32 [[MUL6]], ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA6]] // CHECK-NEXT: store i32 [[MUL6]], ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA6]]
// CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[MUL]], 16 // CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[MUL]], 16
// CHECK-NEXT: store i32 [[TMP3]], ptr [[VEC]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: store i32 [[TMP3]], ptr [[VEC]], align 4, !tbaa [[TBAA2]]
// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[INDEX]], align 4, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[INDEX]], align 4, !tbaa [[TBAA2]]
-// CHECK-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds nuw [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP4]], i32 1+// CHECK-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds [4 x [2 x %union.vect32]], ptr [[TMP]], i32 0, i32 [[TMP4]], i32 1
// CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX14]], i32 2 // CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX14]], i32 2
// CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX15]], align 2, !tbaa [[TBAA6]] // CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX15]], align 2, !tbaa [[TBAA6]]
// CHECK-NEXT: [[CONV16:%.*]] = zext i16 [[TMP5]] to i32 // CHECK-NEXT: [[CONV16:%.*]] = zext i16 [[TMP5]] to i32
clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
@@ -31,7 +31,6 @@ void test_lambda() {
//CHECK: define dso_local void @{{.*}}test_lambda{{.*}}() #0 { //CHECK: define dso_local void @{{.*}}test_lambda{{.*}}() #0 {
//CHECK: entry: //CHECK: entry:
//CHECK: %agg.tmp = alloca %class.anon, align 1 //CHECK: %agg.tmp = alloca %class.anon, align 1
-//CHECK: %ref.tmp = alloca %class.anon, align 1
//CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() //CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"()
//CHECK: ret void //CHECK: ret void
//CHECK: } //CHECK: }
clang/test/CodeGenCXX/default-arguments.cpp
@@ -12,6 +12,17 @@ void g() {
} }
} }
+namespace GH113324 {
+struct S1 {
+ friend void f(S1, int = 42) {}
+};
+
+void test() {
+ S1 s1;
+ f(s1);
+}
+};
+
struct A1 { struct A1 {
A1(); A1();
~A1(); ~A1();
clang/test/CodeGenCXX/matrix-type.cpp
@@ -368,3 +368,36 @@ void test_use_matrix_2() {
selector<2> r5 = use_matrix_3(m1); selector<2> r5 = use_matrix_3(m1);
} }
+
+// CHECK-LABEL: define void @_Z22test_pseudo_destructorv()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %a = alloca [25 x double], align 8
+// CHECK-NEXT: %b = alloca [12 x float], align 4
+// CHECK-NEXT: %0 = load <25 x double>, ptr %a, align 8
+// CHECK-NEXT: call void @_Z17pseudo_destructorIu11matrix_typeILm5ELm5EdEEvT_(<25 x double> %0)
+// CHECK-NEXT: %1 = load <12 x float>, ptr %b, align 4
+// CHECK-NEXT: call void @_Z17pseudo_destructorIu11matrix_typeILm3ELm4EfEEvT_(<12 x float> %1)
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define linkonce_odr void @_Z17pseudo_destructorIu11matrix_typeILm5ELm5EdEEvT_(<25 x double> %t)
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %t.addr = alloca [25 x double], align 8
+// CHECK-NEXT: store <25 x double> %t, ptr %t.addr, align 8
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define linkonce_odr void @_Z17pseudo_destructorIu11matrix_typeILm3ELm4EfEEvT_(<12 x float> %t)
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %t.addr = alloca [12 x float], align 4
+// CHECK-NEXT: store <12 x float> %t, ptr %t.addr, align 4
+// CHECK-NEXT: ret void
+template <typename T>
+void pseudo_destructor(T t) {
+ t.~T();
+}
+
+void test_pseudo_destructor() {
+ dx5x5_t a;
+ fx3x4_t b;
+ pseudo_destructor(a);
+ pseudo_destructor(b);
+}
clang/test/CodeGenCXX/matrix-vector-bit-int.cpp
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -fenable-matrix %s -emit-llvm -triple x86_64-unknown-linux -disable-llvm-passes -o - -std=c++11 | FileCheck %s
+
+using i8x3 = _BitInt(8) __attribute__((ext_vector_type(3)));
+using i8x3x3 = _BitInt(8) __attribute__((matrix_type(3, 3)));
+using i32x3 = _BitInt(32) __attribute__((ext_vector_type(3)));
+using i32x3x3 = _BitInt(32) __attribute__((matrix_type(3, 3)));
+using i512x3 = _BitInt(512) __attribute__((ext_vector_type(3)));
+using i512x3x3 = _BitInt(512) __attribute__((matrix_type(3, 3)));
+
+// CHECK-LABEL: define dso_local i32 @_Z2v1Dv3_DB8_(i32 %a.coerce)
+i8x3 v1(i8x3 a) {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %retval = alloca <3 x i8>, align 4
+ // CHECK-NEXT: %a = alloca <3 x i8>, align 4
+ // CHECK-NEXT: %a.addr = alloca <3 x i8>, align 4
+ // CHECK-NEXT: store i32 %a.coerce, ptr %a, align 4
+ // CHECK-NEXT: %loadVec4 = load <4 x i8>, ptr %a, align 4
+ // CHECK-NEXT: %a1 = shufflevector <4 x i8> %loadVec4, <4 x i8> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %extractVec = shufflevector <3 x i8> %a1, <3 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison>
+ // CHECK-NEXT: store <4 x i8> %extractVec, ptr %a.addr, align 4
+ // CHECK-NEXT: %loadVec42 = load <4 x i8>, ptr %a.addr, align 4
+ // CHECK-NEXT: %extractVec3 = shufflevector <4 x i8> %loadVec42, <4 x i8> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %loadVec44 = load <4 x i8>, ptr %a.addr, align 4
+ // CHECK-NEXT: %extractVec5 = shufflevector <4 x i8> %loadVec44, <4 x i8> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %add = add <3 x i8> %extractVec3, %extractVec5
+ // CHECK-NEXT: store <3 x i8> %add, ptr %retval, align 4
+ // CHECK-NEXT: %0 = load i32, ptr %retval, align 4
+ // CHECK-NEXT: ret i32 %0
+ return a + a;
+}
+
+// CHECK-LABEL: define dso_local noundef <3 x i32> @_Z2v2Dv3_DB32_(<3 x i32> noundef %a)
+i32x3 v2(i32x3 a) {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %a.addr = alloca <3 x i32>, align 16
+ // CHECK-NEXT: %extractVec = shufflevector <3 x i32> %a, <3 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison>
+ // CHECK-NEXT: store <4 x i32> %extractVec, ptr %a.addr, align 16
+ // CHECK-NEXT: %loadVec4 = load <4 x i32>, ptr %a.addr, align 16
+ // CHECK-NEXT: %extractVec1 = shufflevector <4 x i32> %loadVec4, <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %loadVec42 = load <4 x i32>, ptr %a.addr, align 16
+ // CHECK-NEXT: %extractVec3 = shufflevector <4 x i32> %loadVec42, <4 x i32> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %add = add <3 x i32> %extractVec1, %extractVec3
+ // CHECK-NEXT: ret <3 x i32> %add
+ return a + a;
+}
+
+// CHECK-LABEL: define dso_local noundef <3 x i512> @_Z2v3Dv3_DB512_(ptr noundef byval(<3 x i512>) align 256 %0)
+i512x3 v3(i512x3 a) {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %a.addr = alloca <3 x i512>, align 256
+ // CHECK-NEXT: %loadVec4 = load <4 x i512>, ptr %0, align 256
+ // CHECK-NEXT: %a = shufflevector <4 x i512> %loadVec4, <4 x i512> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %extractVec = shufflevector <3 x i512> %a, <3 x i512> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison>
+ // CHECK-NEXT: store <4 x i512> %extractVec, ptr %a.addr, align 256
+ // CHECK-NEXT: %loadVec41 = load <4 x i512>, ptr %a.addr, align 256
+ // CHECK-NEXT: %extractVec2 = shufflevector <4 x i512> %loadVec41, <4 x i512> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %loadVec43 = load <4 x i512>, ptr %a.addr, align 256
+ // CHECK-NEXT: %extractVec4 = shufflevector <4 x i512> %loadVec43, <4 x i512> poison, <3 x i32> <i32 0, i32 1, i32 2>
+ // CHECK-NEXT: %add = add <3 x i512> %extractVec2, %extractVec4
+ // CHECK-NEXT: ret <3 x i512> %add
+ return a + a;
+}
+
+// CHECK-LABEL: define dso_local noundef <9 x i8> @_Z2m1u11matrix_typeILm3ELm3EDB8_E(<9 x i8> noundef %a)
+i8x3x3 m1(i8x3x3 a) {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %a.addr = alloca [9 x i8], align 1
+ // CHECK-NEXT: store <9 x i8> %a, ptr %a.addr, align 1
+ // CHECK-NEXT: %0 = load <9 x i8>, ptr %a.addr, align 1
+ // CHECK-NEXT: %1 = load <9 x i8>, ptr %a.addr, align 1
+ // CHECK-NEXT: %2 = add <9 x i8> %0, %1
+ // CHECK-NEXT: ret <9 x i8> %2
+ return a + a;
+}
+
+// CHECK-LABEL: define dso_local noundef <9 x i32> @_Z2m2u11matrix_typeILm3ELm3EDB32_E(<9 x i32> noundef %a)
+i32x3x3 m2(i32x3x3 a) {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %a.addr = alloca [9 x i32], align 4
+ // CHECK-NEXT: store <9 x i32> %a, ptr %a.addr, align 4
+ // CHECK-NEXT: %0 = load <9 x i32>, ptr %a.addr, align 4
+ // CHECK-NEXT: %1 = load <9 x i32>, ptr %a.addr, align 4
+ // CHECK-NEXT: %2 = add <9 x i32> %0, %1
+ // CHECK-NEXT: ret <9 x i32> %2
+ return a + a;
+}
+
+// CHECK-LABEL: define dso_local noundef <9 x i512> @_Z2m3u11matrix_typeILm3ELm3EDB512_E(<9 x i512> noundef %a)
+i512x3x3 m3(i512x3x3 a) {
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %a.addr = alloca [9 x i512], align 8
+ // CHECK-NEXT: store <9 x i512> %a, ptr %a.addr, align 8
+ // CHECK-NEXT: %0 = load <9 x i512>, ptr %a.addr, align 8
+ // CHECK-NEXT: %1 = load <9 x i512>, ptr %a.addr, align 8
+ // CHECK-NEXT: %2 = add <9 x i512> %0, %1
+ // CHECK-NEXT: ret <9 x i512> %2
+ return a + a;
+}
clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -647,7 +647,7 @@ void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
// CHECK: br i1 %{{.*}} label %{{.*}}, label %{{.*}} // CHECK: br i1 %{{.*}} label %{{.*}}, label %{{.*}}
// //
// memptr.convert: ; preds = %entry // memptr.convert: ; preds = %entry
-// CHECK: insertvalue { ptr, i32 } undef, ptr %[[mp]], 0+// CHECK: insertvalue { ptr, i32 } poison, ptr %[[mp]], 0
// CHECK: insertvalue { ptr, i32 } %{{.*}}, i32 4, 1 // CHECK: insertvalue { ptr, i32 } %{{.*}}, i32 4, 1
// CHECK: br label // CHECK: br label
// //
@@ -705,7 +705,7 @@ void (D::*convertCToD(void (C::*mp)()))() {
// CHECK: %[[nv_adj:.*]] = select i1 %[[is_nvbase]], i32 %[[nv_disp]], i32 0 // CHECK: %[[nv_adj:.*]] = select i1 %[[is_nvbase]], i32 %[[nv_disp]], i32 0
// CHECK: %[[dst_adj:.*]] = select i1 %[[is_nvbase]], i32 4, i32 0 // CHECK: %[[dst_adj:.*]] = select i1 %[[is_nvbase]], i32 4, i32 0
// CHECK: %[[adj:.*]] = sub nsw i32 %[[nv_adj]], %[[dst_adj]] // CHECK: %[[adj:.*]] = sub nsw i32 %[[nv_adj]], %[[dst_adj]]
-// CHECK: insertvalue { ptr, i32, i32 } undef, ptr {{.*}}, 0+// CHECK: insertvalue { ptr, i32, i32 } poison, ptr {{.*}}, 0
// CHECK: insertvalue { ptr, i32, i32 } {{.*}}, i32 %[[adj]], 1 // CHECK: insertvalue { ptr, i32, i32 } {{.*}}, i32 %[[adj]], 1
// CHECK: insertvalue { ptr, i32, i32 } {{.*}}, i32 {{.*}}, 2 // CHECK: insertvalue { ptr, i32, i32 } {{.*}}, i32 {{.*}}, 2
// CHECK: br label // CHECK: br label
clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -O3 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -triple spirv-vulkan-compute -x hlsl -emit-llvm -O3 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+
+// CHECK-SPIRV: %"class.hlsl::RWBuffer" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0) }
+// CHECK-DXIL: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 0, 0) }
+RWBuffer<float> Buf : register(u5, space3);
+
+[shader("compute")]
+[numthreads(1, 1, 1)]
+void main() {
+// CHECK: define void @main()
+// CHECK-NEXT: entry:
+
+// CHECK-SPIRV-NEXT: %Buf_h.i = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 0) @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
+// CHECK-SPIRV-NEXT: store target("spirv.Image", float, 5, 2, 0, 0, 2, 0) %Buf_h.i, ptr @Buf, align 8
+
+// CHECK-DXIL-NEXT: %Buf_h.i = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
+// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h.i, ptr @Buf, align 4
+
+// CHECK-NEXT: ret void
+}
clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
@@ -6,9 +6,16 @@ RWBuffer<int> Out;
[numthreads(1,1,1)] [numthreads(1,1,1)]
void main(unsigned GI : SV_GroupIndex) { void main(unsigned GI : SV_GroupIndex) {
// CHECK: define void @main() // CHECK: define void @main()
+
// CHECK: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) // CHECK: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
// CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]] // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
// CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
// CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]] // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]]
Out[GI] = In[GI]; Out[GI] = In[GI];
+
+ // CHECK: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+ // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
+ // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+ // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]]
+ Out[GI] = In.Load(GI);
} }
clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
+// RUN: dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \
+// RUN: spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+
+// Test basic lowering to runtime function call for int values.
+
+// CHECK-LABEL: define {{.*}}test
+bool test(bool p1) {
+ // CHECK-SPIRV: %[[#entry_tok0:]] = call token @llvm.experimental.convergence.entry()
+ // CHECK-SPIRV: %[[RET:.*]] = call spir_func i1 @llvm.spv.wave.all(i1 %{{[a-zA-Z0-9]+}}) [ "convergencectrl"(token %[[#entry_tok0]]) ]
+ // CHECK-DXIL: %[[RET:.*]] = call i1 @llvm.dx.wave.all(i1 %{{[a-zA-Z0-9]+}})
+ // CHECK: ret i1 %[[RET]]
+ return WaveActiveAllTrue(p1);
+}
clang/test/CodeGenOpenCL/opencl_types.cl
@@ -73,3 +73,81 @@ kernel void foo_wo_pipe(write_only pipe int p) {}
void __attribute__((overloadable)) bad1(image1d_t b, image2d_t c, image2d_t d) {} void __attribute__((overloadable)) bad1(image1d_t b, image2d_t c, image2d_t d) {}
// CHECK-SPIR-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}} // CHECK-SPIR-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}
// CHECK-AMDGCN-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}(ptr addrspace(4){{.*}}ptr addrspace(4){{.*}}ptr addrspace(4){{.*}}) // CHECK-AMDGCN-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}(ptr addrspace(4){{.*}}ptr addrspace(4){{.*}}ptr addrspace(4){{.*}})
+
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test20ocl_image1d_array_ro(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_only image1d_array_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test20ocl_image1d_array_wo(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(write_only image1d_array_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test20ocl_image1d_array_rw(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_write image1d_array_t img) {}
+
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test21ocl_image1d_buffer_ro(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_only image1d_buffer_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test21ocl_image1d_buffer_wo(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(write_only image1d_buffer_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test21ocl_image1d_buffer_rw(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_write image1d_buffer_t img) {}
+
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test20ocl_image2d_array_ro(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_only image2d_array_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test20ocl_image2d_array_wo(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(write_only image2d_array_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test20ocl_image2d_array_rw(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_write image2d_array_t img) {}
+
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image1d_ro(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_only image1d_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image1d_wo(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(write_only image1d_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image1d_rw(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_write image1d_t img) {}
+
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image2d_ro(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_only image2d_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image2d_wo(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(write_only image2d_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image2d_rw(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_write image2d_t img) {}
+
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image3d_ro(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_only image3d_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image3d_wo(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(write_only image3d_t img) {}
+
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_mangle_test14ocl_image3d_rw(ptr addrspace(4) %img)
+__attribute__((overloadable))
+void img_type_mangle_test(read_write image3d_t img) {}
clang/test/Driver/print-enabled-extensions/riscv-rocket-rv64.c
@@ -4,10 +4,10 @@
// Simple litmus test to check the frontend handling of this option is // Simple litmus test to check the frontend handling of this option is
// enabled. // enabled.
-// CHECK: Extensions enabled for the given RISC-V target +// CHECK: Extensions enabled for the given RISC-V target
// CHECK-EMPTY: // CHECK-EMPTY:
-// CHECK-NEXT: Name Version Description +// CHECK-NEXT: Name Version Description
-// CHECK-NEXT: i 2.1 'I' (Base Integer Instruction Set) +// CHECK-NEXT: i 2.1 'I' (Base Integer Instruction Set)
-// CHECK-NEXT: zicsr 2.0 'zicsr' (CSRs) +// CHECK-NEXT: zicsr 2.0 'Zicsr' (CSRs)
-// CHECK-NEXT: zifencei 2.0 'Zifencei' (fence.i) +// CHECK-NEXT: zifencei 2.0 'Zifencei' (fence.i)
// CHECK-EMPTY: // CHECK-EMPTY:
clang/test/Driver/print-supported-extensions-riscv.c
@@ -5,7 +5,7 @@
// CHECK-EMPTY: // CHECK-EMPTY:
// CHECK-NEXT: Name Version Description // CHECK-NEXT: Name Version Description
// CHECK-NEXT: i 2.1 'I' (Base Integer Instruction Set) // CHECK-NEXT: i 2.1 'I' (Base Integer Instruction Set)
-// CHECK-NEXT: e 2.0 Implements RV{32,64}E (provides 16 rather than 32 GPRs)+// CHECK-NEXT: e 2.0 'E' (Embedded Instruction Set with 16 GPRs)
// CHECK-NEXT: m 2.0 'M' (Integer Multiplication and Division) // CHECK-NEXT: m 2.0 'M' (Integer Multiplication and Division)
// CHECK-NEXT: a 2.1 'A' (Atomic Instructions) // CHECK-NEXT: a 2.1 'A' (Atomic Instructions)
// CHECK-NEXT: f 2.2 'F' (Single-Precision Floating-Point) // CHECK-NEXT: f 2.2 'F' (Single-Precision Floating-Point)
@@ -24,7 +24,7 @@
// CHECK-NEXT: ziccrse 1.0 'Ziccrse' (Main Memory Supports Forward Progress on LR/SC Sequences) // CHECK-NEXT: ziccrse 1.0 'Ziccrse' (Main Memory Supports Forward Progress on LR/SC Sequences)
// CHECK-NEXT: zicntr 2.0 'Zicntr' (Base Counters and Timers) // CHECK-NEXT: zicntr 2.0 'Zicntr' (Base Counters and Timers)
// CHECK-NEXT: zicond 1.0 'Zicond' (Integer Conditional Operations) // CHECK-NEXT: zicond 1.0 'Zicond' (Integer Conditional Operations)
-// CHECK-NEXT: zicsr 2.0 'zicsr' (CSRs)+// CHECK-NEXT: zicsr 2.0 'Zicsr' (CSRs)
// CHECK-NEXT: zifencei 2.0 'Zifencei' (fence.i) // CHECK-NEXT: zifencei 2.0 'Zifencei' (fence.i)
// CHECK-NEXT: zihintntl 1.0 'Zihintntl' (Non-Temporal Locality Hints) // CHECK-NEXT: zihintntl 1.0 'Zihintntl' (Non-Temporal Locality Hints)
// CHECK-NEXT: zihintpause 2.0 'Zihintpause' (Pause Hint) // CHECK-NEXT: zihintpause 2.0 'Zihintpause' (Pause Hint)
@@ -78,7 +78,7 @@
// CHECK-NEXT: zve64d 1.0 'Zve64d' (Vector Extensions for Embedded Processors with maximal 64 EEW, F and D extension) // CHECK-NEXT: zve64d 1.0 'Zve64d' (Vector Extensions for Embedded Processors with maximal 64 EEW, F and D extension)
// CHECK-NEXT: zve64f 1.0 'Zve64f' (Vector Extensions for Embedded Processors with maximal 64 EEW and F extension) // CHECK-NEXT: zve64f 1.0 'Zve64f' (Vector Extensions for Embedded Processors with maximal 64 EEW and F extension)
// CHECK-NEXT: zve64x 1.0 'Zve64x' (Vector Extensions for Embedded Processors with maximal 64 EEW) // CHECK-NEXT: zve64x 1.0 'Zve64x' (Vector Extensions for Embedded Processors with maximal 64 EEW)
-// CHECK-NEXT: zvfbfmin 1.0 'Zvbfmin' (Vector BF16 Converts)+// CHECK-NEXT: zvfbfmin 1.0 'Zvfbfmin' (Vector BF16 Converts)
// CHECK-NEXT: zvfbfwma 1.0 'Zvfbfwma' (Vector BF16 widening mul-add) // CHECK-NEXT: zvfbfwma 1.0 'Zvfbfwma' (Vector BF16 widening mul-add)
// CHECK-NEXT: zvfh 1.0 'Zvfh' (Vector Half-Precision Floating-Point) // CHECK-NEXT: zvfh 1.0 'Zvfh' (Vector Half-Precision Floating-Point)
// CHECK-NEXT: zvfhmin 1.0 'Zvfhmin' (Vector Half-Precision Floating-Point Minimal) // CHECK-NEXT: zvfhmin 1.0 'Zvfhmin' (Vector Half-Precision Floating-Point Minimal)
@@ -87,7 +87,7 @@
// CHECK-NEXT: zvkn 1.0 'Zvkn' (shorthand for 'Zvkned', 'Zvknhb', 'Zvkb', and 'Zvkt') // CHECK-NEXT: zvkn 1.0 'Zvkn' (shorthand for 'Zvkned', 'Zvknhb', 'Zvkb', and 'Zvkt')
// CHECK-NEXT: zvknc 1.0 'Zvknc' (shorthand for 'Zvknc' and 'Zvbc') // CHECK-NEXT: zvknc 1.0 'Zvknc' (shorthand for 'Zvknc' and 'Zvbc')
// CHECK-NEXT: zvkned 1.0 'Zvkned' (Vector AES Encryption & Decryption (Single Round)) // CHECK-NEXT: zvkned 1.0 'Zvkned' (Vector AES Encryption & Decryption (Single Round))
-// CHECK-NEXT: zvkng 1.0 'zvkng' (shorthand for 'Zvkn' and 'Zvkg')+// CHECK-NEXT: zvkng 1.0 'Zvkng' (shorthand for 'Zvkn' and 'Zvkg')
// CHECK-NEXT: zvknha 1.0 'Zvknha' (Vector SHA-2 (SHA-256 only)) // CHECK-NEXT: zvknha 1.0 'Zvknha' (Vector SHA-2 (SHA-256 only))
// CHECK-NEXT: zvknhb 1.0 'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512)) // CHECK-NEXT: zvknhb 1.0 'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512))
// CHECK-NEXT: zvks 1.0 'Zvks' (shorthand for 'Zvksed', 'Zvksh', 'Zvkb', and 'Zvkt') // CHECK-NEXT: zvks 1.0 'Zvks' (shorthand for 'Zvksed', 'Zvksh', 'Zvkb', and 'Zvkt')
@@ -96,25 +96,25 @@
// CHECK-NEXT: zvksg 1.0 'Zvksg' (shorthand for 'Zvks' and 'Zvkg') // CHECK-NEXT: zvksg 1.0 'Zvksg' (shorthand for 'Zvks' and 'Zvkg')
// CHECK-NEXT: zvksh 1.0 'Zvksh' (SM3 Hash Function Instructions) // CHECK-NEXT: zvksh 1.0 'Zvksh' (SM3 Hash Function Instructions)
// CHECK-NEXT: zvkt 1.0 'Zvkt' (Vector Data-Independent Execution Latency) // CHECK-NEXT: zvkt 1.0 'Zvkt' (Vector Data-Independent Execution Latency)
-// CHECK-NEXT: zvl1024b 1.0 'Zvl' (Minimum Vector Length) 1024+// CHECK-NEXT: zvl1024b 1.0 'Zvl1024b' (Minimum Vector Length 1024)
-// CHECK-NEXT: zvl128b 1.0 'Zvl' (Minimum Vector Length) 128+// CHECK-NEXT: zvl128b 1.0 'Zvl128b' (Minimum Vector Length 128)
-// CHECK-NEXT: zvl16384b 1.0 'Zvl' (Minimum Vector Length) 16384+// CHECK-NEXT: zvl16384b 1.0 'Zvl16384b' (Minimum Vector Length 16384)
-// CHECK-NEXT: zvl2048b 1.0 'Zvl' (Minimum Vector Length) 2048+// CHECK-NEXT: zvl2048b 1.0 'Zvl2048b' (Minimum Vector Length 2048)
-// CHECK-NEXT: zvl256b 1.0 'Zvl' (Minimum Vector Length) 256+// CHECK-NEXT: zvl256b 1.0 'Zvl256b' (Minimum Vector Length 256)
-// CHECK-NEXT: zvl32768b 1.0 'Zvl' (Minimum Vector Length) 32768+// CHECK-NEXT: zvl32768b 1.0 'Zvl32768b' (Minimum Vector Length 32768)
-// CHECK-NEXT: zvl32b 1.0 'Zvl' (Minimum Vector Length) 32+// CHECK-NEXT: zvl32b 1.0 'Zvl32b' (Minimum Vector Length 32)
-// CHECK-NEXT: zvl4096b 1.0 'Zvl' (Minimum Vector Length) 4096+// CHECK-NEXT: zvl4096b 1.0 'Zvl4096b' (Minimum Vector Length 4096)
-// CHECK-NEXT: zvl512b 1.0 'Zvl' (Minimum Vector Length) 512+// CHECK-NEXT: zvl512b 1.0 'Zvl512b' (Minimum Vector Length 512)
-// CHECK-NEXT: zvl64b 1.0 'Zvl' (Minimum Vector Length) 64+// CHECK-NEXT: zvl64b 1.0 'Zvl64b' (Minimum Vector Length 64)
-// CHECK-NEXT: zvl65536b 1.0 'Zvl' (Minimum Vector Length) 65536+// CHECK-NEXT: zvl65536b 1.0 'Zvl65536b' (Minimum Vector Length 65536)
-// CHECK-NEXT: zvl8192b 1.0 'Zvl' (Minimum Vector Length) 8192+// CHECK-NEXT: zvl8192b 1.0 'Zvl8192b' (Minimum Vector Length 8192)
// CHECK-NEXT: zhinx 1.0 'Zhinx' (Half Float in Integer) // CHECK-NEXT: zhinx 1.0 'Zhinx' (Half Float in Integer)
// CHECK-NEXT: zhinxmin 1.0 'Zhinxmin' (Half Float in Integer Minimal) // CHECK-NEXT: zhinxmin 1.0 'Zhinxmin' (Half Float in Integer Minimal)
// CHECK-NEXT: sha 1.0 'Sha' (Augmented Hypervisor) // CHECK-NEXT: sha 1.0 'Sha' (Augmented Hypervisor)
// CHECK-NEXT: shcounterenw 1.0 'Shcounterenw' (Support writeable hcounteren enable bit for any hpmcounter that is not read-only zero) // CHECK-NEXT: shcounterenw 1.0 'Shcounterenw' (Support writeable hcounteren enable bit for any hpmcounter that is not read-only zero)
-// CHECK-NEXT: shgatpa 1.0 'Sgatpa' (SvNNx4 mode supported for all modes supported by satp, as well as Bare)+// CHECK-NEXT: shgatpa 1.0 'Shgatpa' (SvNNx4 mode supported for all modes supported by satp, as well as Bare)
// CHECK-NEXT: shtvala 1.0 'Shtvala' (htval provides all needed values) // CHECK-NEXT: shtvala 1.0 'Shtvala' (htval provides all needed values)
-// CHECK-NEXT: shvsatpa 1.0 'Svsatpa' (vsatp supports all modes supported by satp)+// CHECK-NEXT: shvsatpa 1.0 'Shvsatpa' (vsatp supports all modes supported by satp)
// CHECK-NEXT: shvstvala 1.0 'Shvstvala' (vstval provides all needed values) // CHECK-NEXT: shvstvala 1.0 'Shvstvala' (vstval provides all needed values)
// CHECK-NEXT: shvstvecd 1.0 'Shvstvecd' (vstvec supports Direct mode) // CHECK-NEXT: shvstvecd 1.0 'Shvstvecd' (vstvec supports Direct mode)
// CHECK-NEXT: smaia 1.0 'Smaia' (Advanced Interrupt Architecture Machine Level) // CHECK-NEXT: smaia 1.0 'Smaia' (Advanced Interrupt Architecture Machine Level)
@@ -145,11 +145,11 @@
// CHECK-NEXT: supm 1.0 'Supm' (Indicates User-mode Pointer Masking) // CHECK-NEXT: supm 1.0 'Supm' (Indicates User-mode Pointer Masking)
// CHECK-NEXT: svade 1.0 'Svade' (Raise exceptions on improper A/D bits) // CHECK-NEXT: svade 1.0 'Svade' (Raise exceptions on improper A/D bits)
// CHECK-NEXT: svadu 1.0 'Svadu' (Hardware A/D updates) // CHECK-NEXT: svadu 1.0 'Svadu' (Hardware A/D updates)
-// CHECK-NEXT: svbare 1.0 'Svbare' $(satp mode Bare supported)+// CHECK-NEXT: svbare 1.0 'Svbare' (satp mode Bare supported)
// CHECK-NEXT: svinval 1.0 'Svinval' (Fine-Grained Address-Translation Cache Invalidation) // CHECK-NEXT: svinval 1.0 'Svinval' (Fine-Grained Address-Translation Cache Invalidation)
// CHECK-NEXT: svnapot 1.0 'Svnapot' (NAPOT Translation Contiguity) // CHECK-NEXT: svnapot 1.0 'Svnapot' (NAPOT Translation Contiguity)
// CHECK-NEXT: svpbmt 1.0 'Svpbmt' (Page-Based Memory Types) // CHECK-NEXT: svpbmt 1.0 'Svpbmt' (Page-Based Memory Types)
-// CHECK-NEXT: svvptc 1.0 'svvptc' (Obviating Memory-Management Instructions after Marking PTEs Valid)+// CHECK-NEXT: svvptc 1.0 'Svvptc' (Obviating Memory-Management Instructions after Marking PTEs Valid)
// CHECK-NEXT: xcvalu 1.0 'XCValu' (CORE-V ALU Operations) // CHECK-NEXT: xcvalu 1.0 'XCValu' (CORE-V ALU Operations)
// CHECK-NEXT: xcvbi 1.0 'XCVbi' (CORE-V Immediate Branching) // CHECK-NEXT: xcvbi 1.0 'XCVbi' (CORE-V Immediate Branching)
// CHECK-NEXT: xcvbitmanip 1.0 'XCVbitmanip' (CORE-V Bit Manipulation) // CHECK-NEXT: xcvbitmanip 1.0 'XCVbitmanip' (CORE-V Bit Manipulation)
clang/test/Driver/sanitizer-ld.c
@@ -15,7 +15,7 @@
// CHECK-ASAN-LINUX: "-lpthread" // CHECK-ASAN-LINUX: "-lpthread"
// CHECK-ASAN-LINUX: "-lrt" // CHECK-ASAN-LINUX: "-lrt"
// CHECK-ASAN-LINUX: "-ldl" // CHECK-ASAN-LINUX: "-ldl"
-// CHECK-ASAN-LINUX-NOT: "-lresolv"+// CHECK-ASAN-LINUX: "-lresolv"
// RUN: %clang -fsanitize=address -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: %clang -fsanitize=address -fno-sanitize-link-runtime -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -132,18 +132,81 @@
// RUN: -resource-dir=%S/Inputs/empty_resource_dir \ // RUN: -resource-dir=%S/Inputs/empty_resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX %s // RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX %s
-//+
-// CHECK-ASAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"+// RUN: %clangxx -### %s 2>&1 \
+// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \
+// RUN: -resource-dir=%S/Inputs/empty_resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: -fsanitize-link-c++-runtime \
+// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX %s
+
// CHECK-ASAN-LINUX-CXX-NOT: "-lc" // CHECK-ASAN-LINUX-CXX-NOT: "-lc"
-// CHECK-ASAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive"
-// CHECK-ASAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan_cxx.a" "--no-whole-archive"
// CHECK-ASAN-LINUX-CXX-NOT: "--dynamic-list" // CHECK-ASAN-LINUX-CXX-NOT: "--dynamic-list"
-// CHECK-ASAN-LINUX-CXX: "--export-dynamic"+// CHECK-ASAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
-// CHECK-ASAN-LINUX-CXX: stdc+++// CHECK-ASAN-LINUX-CXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive"
-// CHECK-ASAN-LINUX-CXX: "-lpthread"+// CHECK-ASAN-LINUX-CXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan_cxx.a" "--no-whole-archive"
-// CHECK-ASAN-LINUX-CXX: "-lrt"+// CHECK-ASAN-LINUX-CXX-SAME: "--export-dynamic"
-// CHECK-ASAN-LINUX-CXX: "-ldl"+// CHECK-ASAN-LINUX-CXX-SAME: stdc++
-// CHECK-ASAN-LINUX-CXX-NOT: "-lresolv"+// CHECK-ASAN-LINUX-CXX-SAME: "-lpthread"
+// CHECK-ASAN-LINUX-CXX-SAME: "-lrt"
+// CHECK-ASAN-LINUX-CXX-SAME: "-ldl"
+// CHECK-ASAN-LINUX-CXX-SAME: "-lresolv"
+
+// RUN: %clang -### %s 2>&1 \
+// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \
+// RUN: -resource-dir=%S/Inputs/empty_resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: -fno-sanitize-link-c++-runtime \
+// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CNOCXX %s
+
+// CHECK-ASAN-LINUX-CNOCXX-NOT: "-lc"
+// CHECK-ASAN-LINUX-CNOCXX-NOT: libclang_rt.asan_cxx
+// CHECK-ASAN-LINUX-CNOCXX-NOT: "--dynamic-list"
+// CHECK-ASAN-LINUX-CNOCXX-NOT: stdc++
+// CHECK-ASAN-LINUX-CNOCXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-ASAN-LINUX-CNOCXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive"
+// CHECK-ASAN-LINUX-CNOCXX-SAME: "--export-dynamic"
+// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lpthread"
+// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lrt"
+// CHECK-ASAN-LINUX-CNOCXX-SAME: "-ldl"
+// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lresolv"
+
+// RUN: %clangxx -### %s 2>&1 \
+// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \
+// RUN: -resource-dir=%S/Inputs/empty_resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: -fno-sanitize-link-c++-runtime \
+// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-NOCXX %s
+
+// CHECK-ASAN-LINUX-NOCXX-NOT: "-lc"
+// CHECK-ASAN-LINUX-NOCXX-NOT: libclang_rt.asan_cxx
+// CHECK-ASAN-LINUX-NOCXX-NOT: "--dynamic-list"
+// CHECK-ASAN-LINUX-NOCXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-ASAN-LINUX-NOCXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive"
+// CHECK-ASAN-LINUX-NOCXX-SAME: "--export-dynamic"
+// CHECK-ASAN-LINUX-NOCXX-SAME: stdc++
+// CHECK-ASAN-LINUX-NOCXX-SAME: "-lpthread"
+// CHECK-ASAN-LINUX-NOCXX-SAME: "-lrt"
+// CHECK-ASAN-LINUX-NOCXX-SAME: "-ldl"
+// CHECK-ASAN-LINUX-NOCXX-SAME: "-lresolv"
+
+// RUN: %clangxx -### %s 2>&1 \
+// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \
+// RUN: -resource-dir=%S/Inputs/empty_resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: -nostdlib++ \
+// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-NOSTDCXX %s
+
+// CHECK-ASAN-LINUX-NOSTDCXX-NOT: "-lc"
+// CHECK-ASAN-LINUX-NOSTDCXX-NOT: libclang_rt.asan_cxx
+// CHECK-ASAN-LINUX-NOSTDCXX-NOT: "--dynamic-list"
+// CHECK-ASAN-LINUX-NOSTDCXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive"
+// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "--export-dynamic"
+// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lpthread"
+// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lrt"
+// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-ldl"
+// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lresolv"
// RUN: %clang -### %s -o /dev/null -fsanitize=address \ // RUN: %clang -### %s -o /dev/null -fsanitize=address \
// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \
@@ -274,6 +337,29 @@
// CHECK-ASAN-ANDROID-SHARED-NOT: "-lpthread" // CHECK-ASAN-ANDROID-SHARED-NOT: "-lpthread"
// CHECK-ASAN-ANDROID-SHARED-NOT: "-lresolv" // CHECK-ASAN-ANDROID-SHARED-NOT: "-lresolv"
+
+// RUN: %clangxx %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux -fuse-ld=ld -stdlib=platform -lstdc++ \
+// RUN: -fsanitize=type \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-TYSAN-LINUX-CXX %s
+//
+// CHECK-TYSAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-TYSAN-LINUX-CXX-NOT: stdc++
+// CHECK-TYSAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.tysan{{[^.]*}}.a" "--no-whole-archive"
+// CHECK-TYSAN-LINUX-CXX: stdc++
+
+// RUN: %clangxx -fsanitize=type -### %s 2>&1 \
+// RUN: -mmacosx-version-min=10.6 \
+// RUN: --target=x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-TYSAN-DARWIN-CXX %s
+// CHECK-TYSAN-DARWIN-CXX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-TYSAN-DARWIN-CXX: libclang_rt.tysan_osx_dynamic.dylib
+// CHECK-TYSAN-DARWIN-CXX-NOT: -lc++abi
+
// RUN: %clangxx -### %s 2>&1 \ // RUN: %clangxx -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld -stdlib=platform -lstdc++ \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -stdlib=platform -lstdc++ \
// RUN: -fsanitize=thread \ // RUN: -fsanitize=thread \
@@ -292,7 +378,7 @@
// CHECK-TSAN-LINUX-CXX: "-lpthread" // CHECK-TSAN-LINUX-CXX: "-lpthread"
// CHECK-TSAN-LINUX-CXX: "-lrt" // CHECK-TSAN-LINUX-CXX: "-lrt"
// CHECK-TSAN-LINUX-CXX: "-ldl" // CHECK-TSAN-LINUX-CXX: "-ldl"
-// CHECK-TSAN-LINUX-CXX-NOT: "-lresolv"+// CHECK-TSAN-LINUX-CXX: "-lresolv"
// RUN: %clang -fsanitize=thread -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: %clang -fsanitize=thread -fno-sanitize-link-runtime -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -365,7 +451,7 @@
// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx
// CHECK-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-LINUX-NOT: "-lstdc++"
// CHECK-UBSAN-LINUX: "-lpthread" // CHECK-UBSAN-LINUX: "-lpthread"
-// CHECK-UBSAN-LINUX-NOT: "-lresolv"+// CHECK-UBSAN-LINUX: "-lresolv"
// RUN: %clang -fsanitize=undefined -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: %clang -fsanitize=undefined -fno-sanitize-link-runtime -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -438,7 +524,7 @@
// CHECK-UBSAN-LINUX-CXX: "-lstdc++" // CHECK-UBSAN-LINUX-CXX: "-lstdc++"
// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan // CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
// CHECK-UBSAN-LINUX-CXX: "-lpthread" // CHECK-UBSAN-LINUX-CXX: "-lpthread"
-// CHECK-UBSAN-LINUX-CXX-NOT: "-lresolv"+// CHECK-UBSAN-LINUX-CXX: "-lresolv"
// RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \
// RUN: --target=i386-unknown-linux -fuse-ld=ld \ // RUN: --target=i386-unknown-linux -fuse-ld=ld \
@@ -448,7 +534,7 @@
// CHECK-UBSAN-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-UBSAN-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}"
// CHECK-UBSAN-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_minimal.a" "--no-whole-archive" // CHECK-UBSAN-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_minimal.a" "--no-whole-archive"
// CHECK-UBSAN-MINIMAL-LINUX: "-lpthread" // CHECK-UBSAN-MINIMAL-LINUX: "-lpthread"
-// CHECK-UBSAN-MINIMAL-LINUX-NOT: "-lresolv"+// CHECK-UBSAN-MINIMAL-LINUX: "-lresolv"
// RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \ // RUN: %clang -fsanitize=undefined -fsanitize-minimal-runtime -### %s 2>&1 \
// RUN: --target=x86_64-apple-darwin -fuse-ld=ld \ // RUN: --target=x86_64-apple-darwin -fuse-ld=ld \
@@ -485,7 +571,7 @@
// CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.ubsan // CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.ubsan
// CHECK-ASAN-UBSAN-LINUX-NOT: "-lstdc++" // CHECK-ASAN-UBSAN-LINUX-NOT: "-lstdc++"
// CHECK-ASAN-UBSAN-LINUX: "-lpthread" // CHECK-ASAN-UBSAN-LINUX: "-lpthread"
-// CHECK-ASAN-UBSAN-LINUX-NOT: "-lresolv"+// CHECK-ASAN-UBSAN-LINUX: "-lresolv"
// RUN: %clangxx -fsanitize=address,undefined -### %s 2>&1 \ // RUN: %clangxx -fsanitize=address,undefined -### %s 2>&1 \
// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \
@@ -498,7 +584,7 @@
// CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan // CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.ubsan
// CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++" // CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++"
// CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread" // CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread"
-// CHECK-ASAN-UBSAN-LINUX-CXX-NOT: "-lresolv"+// CHECK-ASAN-UBSAN-LINUX-CXX: "-lresolv"
// RUN: %clangxx -fsanitize=memory,undefined -### %s 2>&1 \ // RUN: %clangxx -fsanitize=memory,undefined -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -541,7 +627,7 @@
// CHECK-LSAN-LINUX: libclang_rt.lsan.a" // CHECK-LSAN-LINUX: libclang_rt.lsan.a"
// CHECK-LSAN-LINUX: "-lpthread" // CHECK-LSAN-LINUX: "-lpthread"
// CHECK-LSAN-LINUX: "-ldl" // CHECK-LSAN-LINUX: "-ldl"
-// CHECK-LSAN-LINUX-NOT: "-lresolv"+// CHECK-LSAN-LINUX: "-lresolv"
// RUN: %clang -fsanitize=leak -fno-sanitize-link-runtime -### %s 2>&1 \ // RUN: %clang -fsanitize=leak -fno-sanitize-link-runtime -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -564,7 +650,7 @@
// CHECK-LSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-LSAN-COV-LINUX-NOT: libclang_rt.ubsan
// CHECK-LSAN-COV-LINUX: "-lpthread" // CHECK-LSAN-COV-LINUX: "-lpthread"
// CHECK-LSAN-COV-LINUX: "-ldl" // CHECK-LSAN-COV-LINUX: "-ldl"
-// CHECK-LSAN-COV-LINUX-NOT: "-lresolv"+// CHECK-LSAN-COV-LINUX: "-lresolv"
// RUN: %clang -fsanitize=leak,address -### %s 2>&1 \ // RUN: %clang -fsanitize=leak,address -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -586,7 +672,7 @@
// CHECK-ASAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-ASAN-COV-LINUX-NOT: libclang_rt.ubsan
// CHECK-ASAN-COV-LINUX-NOT: "-lstdc++" // CHECK-ASAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-ASAN-COV-LINUX: "-lpthread" // CHECK-ASAN-COV-LINUX: "-lpthread"
-// CHECK-ASAN-COV-LINUX-NOT: "-lresolv"+// CHECK-ASAN-COV-LINUX: "-lresolv"
// RUN: %clang -fsanitize=memory -fsanitize-coverage=func -### %s 2>&1 \ // RUN: %clang -fsanitize=memory -fsanitize-coverage=func -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -610,7 +696,7 @@
// CHECK-DFSAN-COV-LINUX-NOT: libclang_rt.ubsan // CHECK-DFSAN-COV-LINUX-NOT: libclang_rt.ubsan
// CHECK-DFSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-DFSAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-DFSAN-COV-LINUX: "-lpthread" // CHECK-DFSAN-COV-LINUX: "-lpthread"
-// CHECK-DFSAN-COV-LINUX-NOT: "-lresolv"+// CHECK-DFSAN-COV-LINUX: "-lresolv"
// RUN: %clang -fsanitize=undefined -fsanitize-coverage=func -### %s 2>&1 \ // RUN: %clang -fsanitize=undefined -fsanitize-coverage=func -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -621,7 +707,7 @@
// CHECK-UBSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone.a" "--no-whole-archive" // CHECK-UBSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone.a" "--no-whole-archive"
// CHECK-UBSAN-COV-LINUX-NOT: "-lstdc++" // CHECK-UBSAN-COV-LINUX-NOT: "-lstdc++"
// CHECK-UBSAN-COV-LINUX: "-lpthread" // CHECK-UBSAN-COV-LINUX: "-lpthread"
-// CHECK-UBSAN-COV-LINUX-NOT: "-lresolv"+// CHECK-UBSAN-COV-LINUX: "-lresolv"
// RUN: %clang -fsanitize-coverage=func -### %s 2>&1 \ // RUN: %clang -fsanitize-coverage=func -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -632,7 +718,7 @@
// CHECK-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone.a" "--no-whole-archive" // CHECK-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone.a" "--no-whole-archive"
// CHECK-COV-LINUX-NOT: "-lstdc++" // CHECK-COV-LINUX-NOT: "-lstdc++"
// CHECK-COV-LINUX: "-lpthread" // CHECK-COV-LINUX: "-lpthread"
-// CHECK-COV-LINUX-NOT: "-lresolv"+// CHECK-COV-LINUX: "-lresolv"
// RUN: %clang -### %s 2>&1 \ // RUN: %clang -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical \
@@ -644,8 +730,7 @@
// CHECK-NSAN-LINUX-NOT: "-lc" // CHECK-NSAN-LINUX-NOT: "-lc"
// CHECK-NSAN-LINUX-NOT: libclang_rt.ubsan // CHECK-NSAN-LINUX-NOT: libclang_rt.ubsan
// CHECK-NSAN-LINUX: libclang_rt.nsan.a" // CHECK-NSAN-LINUX: libclang_rt.nsan.a"
-// CHECK-NSAN-LINUX: "-lpthread" "-lrt" "-lm" "-ldl"+// CHECK-NSAN-LINUX: "-lpthread" "-lrt" "-lm" "-ldl" "-lresolv"
-// CHECK-NSAN-LINUX-NOT: "-lresolv"
// RUN: %clang -### %s 2>&1 --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical -shared-libsan \ // RUN: %clang -### %s 2>&1 --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical -shared-libsan \
// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -resource-dir=%S/Inputs/resource_dir \
@@ -758,7 +843,7 @@
// CHECK-SAFESTACK-LINUX: libclang_rt.safestack.a" // CHECK-SAFESTACK-LINUX: libclang_rt.safestack.a"
// CHECK-SAFESTACK-LINUX: "-lpthread" // CHECK-SAFESTACK-LINUX: "-lpthread"
// CHECK-SAFESTACK-LINUX: "-ldl" // CHECK-SAFESTACK-LINUX: "-ldl"
-// CHECK-SAFESTACK-LINUX-NOT: "-lresolv"+// CHECK-SAFESTACK-LINUX: "-lresolv"
// RUN: %clang -fsanitize=shadow-call-stack -### %s 2>&1 \ // RUN: %clang -fsanitize=shadow-call-stack -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld \
@@ -958,7 +1043,7 @@
// CHECK-SCUDO-LINUX-NOT: "-lstdc++" // CHECK-SCUDO-LINUX-NOT: "-lstdc++"
// CHECK-SCUDO-LINUX: "-lpthread" // CHECK-SCUDO-LINUX: "-lpthread"
// CHECK-SCUDO-LINUX: "-ldl" // CHECK-SCUDO-LINUX: "-ldl"
-// CHECK-SCUDO-LINUX-NOT: "-lresolv"+// CHECK-SCUDO-LINUX: "-lresolv"
// RUN: %clang -### %s -o %t.so -shared 2>&1 \ // RUN: %clang -### %s -o %t.so -shared 2>&1 \
// RUN: --target=i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \
@@ -1019,7 +1104,7 @@
// CHECK-HWASAN-X86-64-LINUX: "-lpthread" // CHECK-HWASAN-X86-64-LINUX: "-lpthread"
// CHECK-HWASAN-X86-64-LINUX: "-lrt" // CHECK-HWASAN-X86-64-LINUX: "-lrt"
// CHECK-HWASAN-X86-64-LINUX: "-ldl" // CHECK-HWASAN-X86-64-LINUX: "-ldl"
-// CHECK-HWASAN-X86-64-LINUX-NOT: "-lresolv"+// CHECK-HWASAN-X86-64-LINUX: "-lresolv"
// RUN: %clang -### %s 2>&1 \ // RUN: %clang -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ // RUN: --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
@@ -1068,7 +1153,7 @@
// CHECK-HWASAN-AARCH64-LINUX: "-lpthread" // CHECK-HWASAN-AARCH64-LINUX: "-lpthread"
// CHECK-HWASAN-AARCH64-LINUX: "-lrt" // CHECK-HWASAN-AARCH64-LINUX: "-lrt"
// CHECK-HWASAN-AARCH64-LINUX: "-ldl" // CHECK-HWASAN-AARCH64-LINUX: "-ldl"
-// CHECK-HWASAN-AARCH64-LINUX-NOT: "-lresolv"+// CHECK-HWASAN-AARCH64-LINUX: "-lresolv"
// RUN: %clang -### %s 2>&1 \ // RUN: %clang -### %s 2>&1 \
// RUN: --target=aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ // RUN: --target=aarch64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \
clang/test/Driver/unknown-arg-drivermodes.test
@@ -0,0 +1,55 @@
+// RUN: %clang_cl \
+// RUN: --config \
+// RUN: -fdiagnostics-color=auto \
+// RUN: -fno-record-command-line \
+// RUN: -frecord-command-line \
+// RUN: -nodefaultlibs \
+// RUN: -nostdlib \
+// RUN: -rpath \
+// RUN: -shared \
+// RUN: -static \
+// RUN: -stdlib \
+// RUN: -Xoffload-linker \
+// RUN: -### -x c++ -c - < /dev/null 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CL --implicit-check-not="warning:"
+
+// RUN: not %clang_dxc \
+// RUN: --config \
+// RUN: -fdiagnostics-color=auto \
+// RUN: -fno-record-command-line \
+// RUN: -frecord-command-line \
+// RUN: -nodefaultlibs \
+// RUN: -nostdlib \
+// RUN: -rpath \
+// RUN: -shared \
+// RUN: -static \
+// RUN: -stdlib \
+// RUN: -Xlinker \
+// RUN: -Xoffload-linker \
+// RUN: -### -T lib_6_3 -Vd - < /dev/null 2>&1 \
+// RUN: | FileCheck %s --check-prefix=DXC --implicit-check-not="error:"
+
+// CL: warning: unknown argument ignored in clang-cl: '--config'
+// CL: warning: unknown argument ignored in clang-cl: '-fdiagnostics-color=auto'
+// CL: warning: unknown argument ignored in clang-cl: '-fno-record-command-line'
+// CL: warning: unknown argument ignored in clang-cl: '-frecord-command-line'
+// CL: warning: unknown argument ignored in clang-cl: '-nodefaultlibs'
+// CL: warning: unknown argument ignored in clang-cl: '-nostdlib'
+// CL: warning: unknown argument ignored in clang-cl: '-rpath'
+// CL: warning: unknown argument ignored in clang-cl: '-shared'
+// CL: warning: unknown argument ignored in clang-cl: '-static'
+// CL: warning: unknown argument ignored in clang-cl: '-stdlib'
+// CL: warning: unknown argument ignored in clang-cl: '-Xoffload-linker'
+
+// DXC: error: unknown argument: '--config'
+// DXC: error: unknown argument: '-fdiagnostics-color=auto'
+// DXC: error: unknown argument: '-fno-record-command-line'
+// DXC: error: unknown argument: '-frecord-command-line'
+// DXC: error: unknown argument: '-nodefaultlibs'
+// DXC: error: unknown argument: '-nostdlib'
+// DXC: error: unknown argument: '-rpath'
+// DXC: error: unknown argument: '-shared'
+// DXC: error: unknown argument: '-static'
+// DXC: error: unknown argument: '-stdlib'
+// DXC: error: unknown argument: '-Xlinker'
+// DXC: error: unknown argument: '-Xoffload-linker'
clang/test/ExtractAPI/objc_external_category.m
@@ -46,7 +46,7 @@ module ExternalModule {
// Symbol graph from the build without extension SGFs should be identical to main symbol graph with extension SGFs // Symbol graph from the build without extension SGFs should be identical to main symbol graph with extension SGFs
// RUN: diff %t/symbols/Module.symbols.json %t/ModuleNoExt.symbols.json // RUN: diff %t/symbols/Module.symbols.json %t/ModuleNoExt.symbols.json
-// RUN: FileCheck %s --input-file %t/symbols/ExternalModule@Module.symbols.json --check-prefix EXT+// RUN: FileCheck %s --input-file %t/symbols/Module@ExternalModule.symbols.json --check-prefix EXT
// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface" // EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface" // EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface" // EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
@@ -55,3 +55,10 @@ module ExternalModule {
// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod" // EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
// EXT-NOT: "!testLabel": "c:objc(cs)ExtInterface" // EXT-NOT: "!testLabel": "c:objc(cs)ExtInterface"
// EXT-NOT: "!testLabel": "c:objc(cs)ModInterface" // EXT-NOT: "!testLabel": "c:objc(cs)ModInterface"
+
+// Ensure that the 'module' metadata for the extension symbol graph should still reference the
+// declaring module
+
+// RUN: FileCheck %s --input-file %t/symbols/Module@ExternalModule.symbols.json --check-prefix META
+// META: "module": {
+// META-NEXT: "name": "Module",
clang/test/Format/lit.local.cfg
@@ -1,3 +1,6 @@
+import platform
+import lit.formats
+
# Suffixes supported by clang-format. # Suffixes supported by clang-format.
config.suffixes = [ config.suffixes = [
".c", ".c",
@@ -19,3 +22,8 @@ config.suffixes = [
".td", ".td",
".test" ".test"
] ]
+
+# AIX 'diff' command doesn't support --strip-trailing-cr, but the internal
+# python implementation does, so use that for cross platform compatibility
+if platform.system() == "AIX":
+ config.test_format = lit.formats.ShTest()
clang/test/Headers/crash-instantiated-in-scope-cxx-modules4.cpp
@@ -0,0 +1,110 @@
+// RUN: rm -fR %t
+// RUN: split-file %s %t
+// RUN: cd %t
+// RUN: %clang_cc1 -verify -std=c++20 -x c++ -fmodule-map-file=modules.map -fmodule-name=foo1 -emit-module modules.map -o foo1.pcm
+// RUN: %clang_cc1 -verify -std=c++20 -x c++ -fmodule-map-file=modules.map -fmodule-name=foo2 -emit-module modules.map -o foo2.pcm
+// RUN: %clang_cc1 -verify -std=c++20 -x c++ -fmodule-map-file=modules.map -fmodule-file=foo1.pcm -fmodule-file=foo2.pcm server.cc
+
+//--- functional
+#pragma once
+
+namespace std {
+template <class> class function {};
+} // namespace std
+
+//--- foo.h
+#pragma once
+
+class MethodHandler {
+ public:
+ virtual ~MethodHandler() {}
+ struct HandlerParameter {
+ HandlerParameter();
+ };
+ virtual void RunHandler(const HandlerParameter &param);
+};
+
+template <class RequestType, class ResponseType>
+class CallbackUnaryHandler : public MethodHandler {
+ public:
+ explicit CallbackUnaryHandler();
+
+ void RunHandler(const HandlerParameter &param) final {
+ void *call = nullptr;
+ (void)[call](bool){};
+ }
+};
+
+//--- foo1.h
+// expected-no-diagnostics
+#pragma once
+
+#include "functional"
+
+#include "foo.h"
+
+class A;
+
+class ClientAsyncResponseReaderHelper {
+ public:
+ using t = std::function<void(A)>;
+ static void SetupRequest(t finish);
+};
+
+//--- foo2.h
+// expected-no-diagnostics
+#pragma once
+
+#include "foo.h"
+
+template <class BaseClass>
+class a : public BaseClass {
+ public:
+ a() { [[maybe_unused]] CallbackUnaryHandler<int, int> a; }
+};
+
+//--- modules.map
+module "foo" {
+ export *
+ module "foo.h" {
+ export *
+ textual header "foo.h"
+ }
+}
+
+module "foo1" {
+ export *
+ module "foo1.h" {
+ export *
+ header "foo1.h"
+ }
+
+ use "foo"
+}
+
+module "foo2" {
+ export *
+ module "foo2.h" {
+ export *
+ header "foo2.h"
+ }
+
+ use "foo"
+}
+
+//--- server.cc
+// expected-no-diagnostics
+#include "functional"
+
+#include "foo1.h"
+#include "foo2.h"
+
+std::function<void()> on_emit;
+
+template <class RequestType, class ResponseType>
+class CallbackUnaryHandler;
+
+class s {};
+class hs final : public a<s> {
+ explicit hs() {}
+};
clang/test/Lexer/cxx-features.cpp
@@ -81,7 +81,7 @@
#error "wrong value for __cpp_named_character_escapes" #error "wrong value for __cpp_named_character_escapes"
#endif #endif
-#if check(explicit_this_parameter, 0, 0, 0, 0, 0, 0, 0)+#if check(explicit_this_parameter, 0, 0, 0, 0, 0, 202110L, 202110L)
#error "wrong value for __cpp_explicit_this_parameter" #error "wrong value for __cpp_explicit_this_parameter"
#endif #endif
clang/test/Modules/ExtDebugInfo.m
@@ -75,7 +75,8 @@ int foo(ObjCClass *c) {
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass", // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass",
// CHECK-SAME: scope: ![[MOD]], // CHECK-SAME: scope: ![[MOD]],
-// CHECK-SAME: flags: DIFlagFwdDecl)+// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: runtimeLang: DW_LANG_ObjC)
// CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, // CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type,
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,
clang/test/Modules/ModuleDebugInfo.m
@@ -39,6 +39,7 @@
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "FwdDecl", // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "FwdDecl",
// CHECK-SAME: scope: ![[MODULE]], // CHECK-SAME: scope: ![[MODULE]],
+// CHECK-SAME: runtimeLang: DW_LANG_ObjC
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass", // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass",
// CHECK-SAME: scope: ![[MODULE]], // CHECK-SAME: scope: ![[MODULE]],
clang/test/Modules/friend-inline-function-body.cpp
@@ -0,0 +1,111 @@
+// RUN: rm -fR %t
+// RUN: split-file %s %t
+// RUN: cd %t
+// RUN: %clang_cc1 -std=c++20 -fmodule-map-file=modules.map -xc++ -emit-module -fmodule-name=internal modules.map -o internal.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-map-file=modules.map -xc++ -emit-module -fmodule-name=interface modules.map -o interface.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-map-file=modules.map -xc++ -emit-module -fmodule-name=foo modules.map -o foo.pcm -fmodule-file=interface.pcm -fmodule-file=internal.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-map-file=modules.map -O1 -emit-obj main.cc -verify -fmodule-file=foo.pcm
+
+//--- modules.map
+module "interface" {
+ export *
+ module "interface.h" {
+ export *
+ header "interface.h"
+ }
+}
+
+module "internal" {
+ export *
+ module "internal.h" {
+ export *
+ header "internal.h"
+ }
+}
+
+module "foo" {
+ export *
+ module "foo.h" {
+ export *
+ header "foo.h"
+ }
+}
+
+//--- foo.h
+#ifndef FOO_H
+#define FOO_H
+
+#include "strong_int.h"
+
+DEFINE_STRONG_INT_TYPE(CallbackId, int);
+
+#define CALL_HASH(id) \
+ (void)[&]() { AbslHashValue(0, id); };
+
+void test(CallbackId id) {
+ CALL_HASH(id);
+}
+
+#include "internal.h"
+#include "interface.h"
+
+#endif
+
+//--- interface.h
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+#include "strong_int.h"
+
+DEFINE_STRONG_INT_TYPE(EndpointToken, int);
+
+#endif
+
+//--- internal.h
+#ifndef INTERNAL_H
+#define INTERNAL_H
+
+#include "strong_int.h"
+
+DEFINE_STRONG_INT_TYPE(OrderedListSortKey, int);
+DEFINE_STRONG_INT_TYPE(OrderedListId, int);
+
+#endif
+
+//--- strong_int.h
+#ifndef STRONG_INT_H
+#define STRONG_INT_H
+
+namespace util_intops {
+
+template <typename TagType, typename NativeType>
+class StrongInt2;
+
+template <typename TagType, typename NativeType>
+class StrongInt2 {
+ public:
+ template <typename H>
+ friend H AbslHashValue(H h, const StrongInt2& i) {
+ return h;
+ }
+};
+
+} // namespace util_intops
+
+#define DEFINE_STRONG_INT_TYPE(type_name, value_type) \
+ struct type_name##_strong_int_tag_ {}; \
+ typedef ::util_intops::StrongInt2<type_name##_strong_int_tag_, value_type> \
+ type_name;
+
+#endif
+
+//--- main.cc
+// expected-no-diagnostics
+#include "foo.h"
+
+#include "strong_int.h"
+
+DEFINE_STRONG_INT_TYPE(ArchiveId2, int);
+void partial(ArchiveId2 id) {
+ CALL_HASH(id);
+}
clang/test/OpenMP/amdgpu_threadprivate.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -aux-triple x86_64-unknown-linux-gnu -target-cpu gfx906 -fopenmp -nogpulib -fopenmp-is-target-device -emit-llvm %s -o - | FileCheck %s
+
+// Don't crash with assertions build.
+
+// CHECK: @MyGlobVar = external thread_local addrspace(1) global i32, align 4
+// CHECK: define weak_odr hidden noundef ptr @_ZTW9MyGlobVar() #0 comdat {
+// CHECK-NEXT: %1 = call align 4 ptr addrspace(1) @llvm.threadlocal.address.p1(ptr addrspace(1) align 4 @MyGlobVar)
+// CHECK-NEXT: %2 = addrspacecast ptr addrspace(1) %1 to ptr
+// CHECK-NEXT: ret ptr %2
+// CHECK-NEXT: }
+int MyGlobVar;
+#pragma omp threadprivate(MyGlobVar)
+int main() {
+ MyGlobVar = 1;
+}
+
clang/test/OpenMP/declare_mapper_codegen.cpp
@@ -86,19 +86,9 @@ public:
#pragma omp declare mapper(id: C s) map(s.a, s.b[0:2]) #pragma omp declare mapper(id: C s) map(s.a, s.b[0:2])
-// CK0: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})+// CK0: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
-// CK0: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK0: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK0: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK0: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK0: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK0-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
// CK0-64-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16 // CK0-64-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16
// CK0-32-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 8 // CK0-32-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 8
-// CK0-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK0-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK0-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK0-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
// CK0-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1 // CK0-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
// CK0-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]] // CK0-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
// CK0-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]] // CK0-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
@@ -597,18 +587,8 @@ public:
#pragma omp declare mapper(id: C<int> s) map(s.a) #pragma omp declare mapper(id: C<int> s) map(s.a)
-// CK1-LABEL: define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id{{.*}}(ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})+// CK1: define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id{{.*}}(ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
-// CK1: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK1: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK1: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK1: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK1: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK1-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
// CK1-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 4 // CK1-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 4
-// CK1-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK1-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK1-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK1-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
// CK1-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]] // CK1-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
// CK1-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1 // CK1-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
// CK1-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]] // CK1-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
@@ -717,18 +697,8 @@ public:
// CK2: define {{.*}}void [[BMPRFUNC:@[.]omp_mapper[.].*B[.]default]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}}) // CK2: define {{.*}}void [[BMPRFUNC:@[.]omp_mapper[.].*B[.]default]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})
-// CK2-LABEL: define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id(ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})+// CK2: define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id(ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
-// CK2: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK2: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK2: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK2: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK2: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK2-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
// CK2-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16 // CK2-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16
-// CK2-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK2-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK2-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK2-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
// CK2-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]] // CK2-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
// CK2-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1 // CK2-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
// CK2-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]] // CK2-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
@@ -921,19 +891,9 @@ public:
#pragma omp declare mapper(id: C s) map(s.a, s.b[0:2]) #pragma omp declare mapper(id: C s) map(s.a, s.b[0:2])
-// CK4: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})+// CK4: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
-// CK4: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK4: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK4: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK4: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK4: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK4-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
// CK4-64-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16 // CK4-64-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16
// CK4-32-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 8 // CK4-32-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 8
-// CK4-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK4-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK4-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK4-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
// CK4-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]] // CK4-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
// CK4-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1 // CK4-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
// CK4-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]] // CK4-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
clang/test/OpenMP/target_map_names.cpp
@@ -201,9 +201,7 @@ void secondMapNameInClause() {
// DEBUG: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]] // DEBUG: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
// CHECK-NOT: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]] // CHECK-NOT: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
-// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[NAME_ARG:%.+]])+// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[MAPPER_NAME:%.+]])
-// DEBUG: store ptr [[NAME_ARG]], ptr [[NAME_STACK:%.+]]
-// DEBUG: [[MAPPER_NAME:%.+]] = load ptr, ptr [[NAME_STACK]]
// DEBUG: call void @__tgt_push_mapper_component(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, ptr [[MAPPER_NAME]]) // DEBUG: call void @__tgt_push_mapper_component(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, ptr [[MAPPER_NAME]])
#endif #endif
clang/test/OpenMP/target_map_names_attr.cpp
@@ -186,9 +186,7 @@ void secondMapNameInClause() {
// DEBUG: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]] // DEBUG: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
// CHECK-NOT: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]] // CHECK-NOT: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
-// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[NAME_ARG:%.+]])+// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[MAPPER_NAME:%.+]])
-// DEBUG: store ptr [[NAME_ARG]], ptr [[NAME_STACK:%.+]]
-// DEBUG: [[MAPPER_NAME:%.+]] = load ptr, ptr [[NAME_STACK]]
// DEBUG: call void @__tgt_push_mapper_component(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, ptr [[MAPPER_NAME]]) // DEBUG: call void @__tgt_push_mapper_component(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, ptr [[MAPPER_NAME]])
#endif #endif
clang/test/OpenMP/target_map_nest_defalut_mapper_codegen.cpp
@@ -109,30 +109,12 @@ void foo() {
// CHECK-LABEL: define {{[^@]+}}@.omp_mapper._ZTS1D.default // CHECK-LABEL: define {{[^@]+}}@.omp_mapper._ZTS1D.default
// CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]], i64 noundef [[TMP3:%.*]], i64 noundef [[TMP4:%.*]], ptr noundef [[TMP5:%.*]]) #[[ATTR2:[0-9]+]] { // CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]], i64 noundef [[TMP3:%.*]], i64 noundef [[TMP4:%.*]], ptr noundef [[TMP5:%.*]]) #[[ATTR2:[0-9]+]] {
// CHECK-NEXT: entry: // CHECK-NEXT: entry:
-// CHECK-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8+// CHECK-NEXT: [[TMP10:%.*]] = udiv exact i64 [[TMP3]], 12
-// CHECK-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8+// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_D:%.*]], ptr [[TMP2]], i64 [[TMP10]]
-// CHECK-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[DOTADDR3:%.*]] = alloca i64, align 8
-// CHECK-NEXT: [[DOTADDR4:%.*]] = alloca i64, align 8
-// CHECK-NEXT: [[DOTADDR5:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
-// CHECK-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
-// CHECK-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 8
-// CHECK-NEXT: store i64 [[TMP3]], ptr [[DOTADDR3]], align 8
-// CHECK-NEXT: store i64 [[TMP4]], ptr [[DOTADDR4]], align 8
-// CHECK-NEXT: store ptr [[TMP5]], ptr [[DOTADDR5]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[DOTADDR3]], align 8
-// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTADDR]], align 8
-// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
-// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 8
-// CHECK-NEXT: [[TMP10:%.*]] = udiv exact i64 [[TMP6]], 12
-// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_D:%.*]], ptr [[TMP9]], i64 [[TMP10]]
-// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTADDR4]], align 8
-// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTADDR5]], align 8
// CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY:%.*]] = icmp sgt i64 [[TMP10]], 1 // CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[TMP12]], 8+// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[TMP4]], 8
-// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP8]], [[TMP9]]+// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP1]], [[TMP2]]
-// CHECK-NEXT: [[TMP16:%.*]] = and i64 [[TMP12]], 16+// CHECK-NEXT: [[TMP16:%.*]] = and i64 [[TMP4]], 16
// CHECK-NEXT: [[TMP17:%.*]] = icmp ne i64 [[TMP16]], 0 // CHECK-NEXT: [[TMP17:%.*]] = icmp ne i64 [[TMP16]], 0
// CHECK-NEXT: [[TMP18:%.*]] = and i1 [[TMP15]], [[TMP17]] // CHECK-NEXT: [[TMP18:%.*]] = and i1 [[TMP15]], [[TMP17]]
// CHECK-NEXT: [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_ISARRAY]], [[TMP18]] // CHECK-NEXT: [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_ISARRAY]], [[TMP18]]
@@ -141,15 +123,15 @@ void foo() {
// CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__INIT:%.*]], label [[OMP_ARRAYMAP_HEAD:%.*]] // CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__INIT:%.*]], label [[OMP_ARRAYMAP_HEAD:%.*]]
// CHECK: .omp.array..init: // CHECK: .omp.array..init:
// CHECK-NEXT: [[TMP21:%.*]] = mul nuw i64 [[TMP10]], 12 // CHECK-NEXT: [[TMP21:%.*]] = mul nuw i64 [[TMP10]], 12
-// CHECK-NEXT: [[TMP22:%.*]] = and i64 [[TMP12]], -4+// CHECK-NEXT: [[TMP22:%.*]] = and i64 [[TMP4]], -4
// CHECK-NEXT: [[TMP23:%.*]] = or i64 [[TMP22]], 512 // CHECK-NEXT: [[TMP23:%.*]] = or i64 [[TMP22]], 512
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP13]])+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP5]])
// CHECK-NEXT: br label [[OMP_ARRAYMAP_HEAD]] // CHECK-NEXT: br label [[OMP_ARRAYMAP_HEAD]]
// CHECK: omp.arraymap.head: // CHECK: omp.arraymap.head:
-// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP9]], [[TMP11]]+// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP2]], [[TMP11]]
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISEMPTY]], label [[OMP_DONE:%.*]], label [[OMP_ARRAYMAP_BODY:%.*]] // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISEMPTY]], label [[OMP_DONE:%.*]], label [[OMP_ARRAYMAP_BODY:%.*]]
// CHECK: omp.arraymap.body: // CHECK: omp.arraymap.body:
-// CHECK-NEXT: [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP9]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END25:%.*]] ]+// CHECK-NEXT: [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP2]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END25:%.*]] ]
// CHECK-NEXT: [[E:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 0 // CHECK-NEXT: [[E:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 0
// CHECK-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 1 // CHECK-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 1
// CHECK-NEXT: [[H:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 2 // CHECK-NEXT: [[H:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 2
@@ -158,10 +140,10 @@ void foo() {
// CHECK-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[E]] to i64 // CHECK-NEXT: [[TMP26:%.*]] = ptrtoint ptr [[E]] to i64
// CHECK-NEXT: [[TMP27:%.*]] = sub i64 [[TMP25]], [[TMP26]] // CHECK-NEXT: [[TMP27:%.*]] = sub i64 [[TMP25]], [[TMP26]]
// CHECK-NEXT: [[TMP28:%.*]] = sdiv exact i64 [[TMP27]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) // CHECK-NEXT: [[TMP28:%.*]] = sdiv exact i64 [[TMP27]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-NEXT: [[TMP29:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP7]])+// CHECK-NEXT: [[TMP29:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP0]])
// CHECK-NEXT: [[TMP30:%.*]] = shl i64 [[TMP29]], 48 // CHECK-NEXT: [[TMP30:%.*]] = shl i64 [[TMP29]], 48
// CHECK-NEXT: [[TMP31:%.*]] = add nuw i64 0, [[TMP30]] // CHECK-NEXT: [[TMP31:%.*]] = add nuw i64 0, [[TMP30]]
-// CHECK-NEXT: [[TMP32:%.*]] = and i64 [[TMP12]], 3+// CHECK-NEXT: [[TMP32:%.*]] = and i64 [[TMP4]], 3
// CHECK-NEXT: [[TMP33:%.*]] = icmp eq i64 [[TMP32]], 0 // CHECK-NEXT: [[TMP33:%.*]] = icmp eq i64 [[TMP32]], 0
// CHECK-NEXT: br i1 [[TMP33]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_ELSE:%.*]] // CHECK-NEXT: br i1 [[TMP33]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_ELSE:%.*]]
// CHECK: omp.type.alloc: // CHECK: omp.type.alloc:
@@ -181,87 +163,87 @@ void foo() {
// CHECK-NEXT: br label [[OMP_TYPE_END]] // CHECK-NEXT: br label [[OMP_TYPE_END]]
// CHECK: omp.type.end: // CHECK: omp.type.end:
// CHECK-NEXT: [[OMP_MAPTYPE:%.*]] = phi i64 [ [[TMP34]], [[OMP_TYPE_ALLOC]] ], [ [[TMP36]], [[OMP_TYPE_TO]] ], [ [[TMP38]], [[OMP_TYPE_FROM]] ], [ [[TMP31]], [[OMP_TYPE_TO_ELSE]] ] // CHECK-NEXT: [[OMP_MAPTYPE:%.*]] = phi i64 [ [[TMP34]], [[OMP_TYPE_ALLOC]] ], [ [[TMP36]], [[OMP_TYPE_TO]] ], [ [[TMP38]], [[OMP_TYPE_FROM]] ], [ [[TMP31]], [[OMP_TYPE_TO_ELSE]] ]
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 [[TMP28]], i64 [[OMP_MAPTYPE]], ptr null)+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 [[TMP28]], i64 [[OMP_MAPTYPE]], ptr null)
// CHECK-NEXT: [[TMP39:%.*]] = add nuw i64 281474976711171, [[TMP30]] // CHECK-NEXT: [[TMP39:%.*]] = add nuw i64 281474976711171, [[TMP30]]
-// CHECK-NEXT: [[TMP40:%.*]] = and i64 [[TMP12]], 3+// CHECK-NEXT: [[TMP40:%.*]] = and i64 [[TMP4]], 3
// CHECK-NEXT: [[TMP41:%.*]] = icmp eq i64 [[TMP40]], 0 // CHECK-NEXT: [[TMP41:%.*]] = icmp eq i64 [[TMP40]], 0
// CHECK-NEXT: br i1 [[TMP41]], label [[OMP_TYPE_ALLOC6:%.*]], label [[OMP_TYPE_ALLOC_ELSE7:%.*]] // CHECK-NEXT: br i1 [[TMP41]], label [[OMP_TYPE_ALLOC6:%.*]], label [[OMP_TYPE_ALLOC_ELSE7:%.*]]
-// CHECK: omp.type.alloc6:+// CHECK: omp.type.alloc1:
// CHECK-NEXT: [[TMP42:%.*]] = and i64 [[TMP39]], -4 // CHECK-NEXT: [[TMP42:%.*]] = and i64 [[TMP39]], -4
// CHECK-NEXT: br label [[OMP_TYPE_END11:%.*]] // CHECK-NEXT: br label [[OMP_TYPE_END11:%.*]]
-// CHECK: omp.type.alloc.else7:+// CHECK: omp.type.alloc.else2:
// CHECK-NEXT: [[TMP43:%.*]] = icmp eq i64 [[TMP40]], 1 // CHECK-NEXT: [[TMP43:%.*]] = icmp eq i64 [[TMP40]], 1
// CHECK-NEXT: br i1 [[TMP43]], label [[OMP_TYPE_TO8:%.*]], label [[OMP_TYPE_TO_ELSE9:%.*]] // CHECK-NEXT: br i1 [[TMP43]], label [[OMP_TYPE_TO8:%.*]], label [[OMP_TYPE_TO_ELSE9:%.*]]
-// CHECK: omp.type.to8:+// CHECK: omp.type.to3:
// CHECK-NEXT: [[TMP44:%.*]] = and i64 [[TMP39]], -3 // CHECK-NEXT: [[TMP44:%.*]] = and i64 [[TMP39]], -3
// CHECK-NEXT: br label [[OMP_TYPE_END11]] // CHECK-NEXT: br label [[OMP_TYPE_END11]]
-// CHECK: omp.type.to.else9:+// CHECK: omp.type.to.else4:
// CHECK-NEXT: [[TMP45:%.*]] = icmp eq i64 [[TMP40]], 2 // CHECK-NEXT: [[TMP45:%.*]] = icmp eq i64 [[TMP40]], 2
// CHECK-NEXT: br i1 [[TMP45]], label [[OMP_TYPE_FROM10:%.*]], label [[OMP_TYPE_END11]] // CHECK-NEXT: br i1 [[TMP45]], label [[OMP_TYPE_FROM10:%.*]], label [[OMP_TYPE_END11]]
-// CHECK: omp.type.from10:+// CHECK: omp.type.from5:
// CHECK-NEXT: [[TMP46:%.*]] = and i64 [[TMP39]], -2 // CHECK-NEXT: [[TMP46:%.*]] = and i64 [[TMP39]], -2
// CHECK-NEXT: br label [[OMP_TYPE_END11]] // CHECK-NEXT: br label [[OMP_TYPE_END11]]
-// CHECK: omp.type.end11:+// CHECK: omp.type.end6:
// CHECK-NEXT: [[OMP_MAPTYPE12:%.*]] = phi i64 [ [[TMP42]], [[OMP_TYPE_ALLOC6]] ], [ [[TMP44]], [[OMP_TYPE_TO8]] ], [ [[TMP46]], [[OMP_TYPE_FROM10]] ], [ [[TMP39]], [[OMP_TYPE_TO_ELSE9]] ] // CHECK-NEXT: [[OMP_MAPTYPE12:%.*]] = phi i64 [ [[TMP42]], [[OMP_TYPE_ALLOC6]] ], [ [[TMP44]], [[OMP_TYPE_TO8]] ], [ [[TMP46]], [[OMP_TYPE_FROM10]] ], [ [[TMP39]], [[OMP_TYPE_TO_ELSE9]] ]
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 4, i64 [[OMP_MAPTYPE12]], ptr null)+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 4, i64 [[OMP_MAPTYPE12]], ptr null)
// CHECK-NEXT: [[TMP47:%.*]] = add nuw i64 281474976711171, [[TMP30]] // CHECK-NEXT: [[TMP47:%.*]] = add nuw i64 281474976711171, [[TMP30]]
-// CHECK-NEXT: [[TMP48:%.*]] = and i64 [[TMP12]], 3+// CHECK-NEXT: [[TMP48:%.*]] = and i64 [[TMP4]], 3
// CHECK-NEXT: [[TMP49:%.*]] = icmp eq i64 [[TMP48]], 0 // CHECK-NEXT: [[TMP49:%.*]] = icmp eq i64 [[TMP48]], 0
// CHECK-NEXT: br i1 [[TMP49]], label [[OMP_TYPE_ALLOC13:%.*]], label [[OMP_TYPE_ALLOC_ELSE14:%.*]] // CHECK-NEXT: br i1 [[TMP49]], label [[OMP_TYPE_ALLOC13:%.*]], label [[OMP_TYPE_ALLOC_ELSE14:%.*]]
-// CHECK: omp.type.alloc13:+// CHECK: omp.type.alloc8:
// CHECK-NEXT: [[TMP50:%.*]] = and i64 [[TMP47]], -4 // CHECK-NEXT: [[TMP50:%.*]] = and i64 [[TMP47]], -4
// CHECK-NEXT: br label [[OMP_TYPE_END18:%.*]] // CHECK-NEXT: br label [[OMP_TYPE_END18:%.*]]
-// CHECK: omp.type.alloc.else14:+// CHECK: omp.type.alloc.else9:
// CHECK-NEXT: [[TMP51:%.*]] = icmp eq i64 [[TMP48]], 1 // CHECK-NEXT: [[TMP51:%.*]] = icmp eq i64 [[TMP48]], 1
// CHECK-NEXT: br i1 [[TMP51]], label [[OMP_TYPE_TO15:%.*]], label [[OMP_TYPE_TO_ELSE16:%.*]] // CHECK-NEXT: br i1 [[TMP51]], label [[OMP_TYPE_TO15:%.*]], label [[OMP_TYPE_TO_ELSE16:%.*]]
-// CHECK: omp.type.to15:+// CHECK: omp.type.to10:
// CHECK-NEXT: [[TMP52:%.*]] = and i64 [[TMP47]], -3 // CHECK-NEXT: [[TMP52:%.*]] = and i64 [[TMP47]], -3
// CHECK-NEXT: br label [[OMP_TYPE_END18]] // CHECK-NEXT: br label [[OMP_TYPE_END18]]
-// CHECK: omp.type.to.else16:+// CHECK: omp.type.to.else11:
// CHECK-NEXT: [[TMP53:%.*]] = icmp eq i64 [[TMP48]], 2 // CHECK-NEXT: [[TMP53:%.*]] = icmp eq i64 [[TMP48]], 2
// CHECK-NEXT: br i1 [[TMP53]], label [[OMP_TYPE_FROM17:%.*]], label [[OMP_TYPE_END18]] // CHECK-NEXT: br i1 [[TMP53]], label [[OMP_TYPE_FROM17:%.*]], label [[OMP_TYPE_END18]]
-// CHECK: omp.type.from17:+// CHECK: omp.type.from12:
// CHECK-NEXT: [[TMP54:%.*]] = and i64 [[TMP47]], -2 // CHECK-NEXT: [[TMP54:%.*]] = and i64 [[TMP47]], -2
// CHECK-NEXT: br label [[OMP_TYPE_END18]] // CHECK-NEXT: br label [[OMP_TYPE_END18]]
-// CHECK: omp.type.end18:+// CHECK: omp.type.end13:
// CHECK-NEXT: [[OMP_MAPTYPE19:%.*]] = phi i64 [ [[TMP50]], [[OMP_TYPE_ALLOC13]] ], [ [[TMP52]], [[OMP_TYPE_TO15]] ], [ [[TMP54]], [[OMP_TYPE_FROM17]] ], [ [[TMP47]], [[OMP_TYPE_TO_ELSE16]] ] // CHECK-NEXT: [[OMP_MAPTYPE19:%.*]] = phi i64 [ [[TMP50]], [[OMP_TYPE_ALLOC13]] ], [ [[TMP52]], [[OMP_TYPE_TO15]] ], [ [[TMP54]], [[OMP_TYPE_FROM17]] ], [ [[TMP47]], [[OMP_TYPE_TO_ELSE16]] ]
-// CHECK-NEXT: call void @.omp_mapper._ZTS1C.default(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[F]], i64 4, i64 [[OMP_MAPTYPE19]], ptr null) #[[ATTR3]]+// CHECK-NEXT: call void @.omp_mapper._ZTS1C.default(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[F]], i64 4, i64 [[OMP_MAPTYPE19]], ptr null) #[[ATTR3]]
// CHECK-NEXT: [[TMP55:%.*]] = add nuw i64 281474976711171, [[TMP30]] // CHECK-NEXT: [[TMP55:%.*]] = add nuw i64 281474976711171, [[TMP30]]
-// CHECK-NEXT: [[TMP56:%.*]] = and i64 [[TMP12]], 3+// CHECK-NEXT: [[TMP56:%.*]] = and i64 [[TMP4]], 3
// CHECK-NEXT: [[TMP57:%.*]] = icmp eq i64 [[TMP56]], 0 // CHECK-NEXT: [[TMP57:%.*]] = icmp eq i64 [[TMP56]], 0
// CHECK-NEXT: br i1 [[TMP57]], label [[OMP_TYPE_ALLOC20:%.*]], label [[OMP_TYPE_ALLOC_ELSE21:%.*]] // CHECK-NEXT: br i1 [[TMP57]], label [[OMP_TYPE_ALLOC20:%.*]], label [[OMP_TYPE_ALLOC_ELSE21:%.*]]
-// CHECK: omp.type.alloc20:+// CHECK: omp.type.alloc15:
// CHECK-NEXT: [[TMP58:%.*]] = and i64 [[TMP55]], -4 // CHECK-NEXT: [[TMP58:%.*]] = and i64 [[TMP55]], -4
// CHECK-NEXT: br label [[OMP_TYPE_END25]] // CHECK-NEXT: br label [[OMP_TYPE_END25]]
-// CHECK: omp.type.alloc.else21:+// CHECK: omp.type.alloc.else16:
// CHECK-NEXT: [[TMP59:%.*]] = icmp eq i64 [[TMP56]], 1 // CHECK-NEXT: [[TMP59:%.*]] = icmp eq i64 [[TMP56]], 1
// CHECK-NEXT: br i1 [[TMP59]], label [[OMP_TYPE_TO22:%.*]], label [[OMP_TYPE_TO_ELSE23:%.*]] // CHECK-NEXT: br i1 [[TMP59]], label [[OMP_TYPE_TO22:%.*]], label [[OMP_TYPE_TO_ELSE23:%.*]]
-// CHECK: omp.type.to22:+// CHECK: omp.type.to17:
// CHECK-NEXT: [[TMP60:%.*]] = and i64 [[TMP55]], -3 // CHECK-NEXT: [[TMP60:%.*]] = and i64 [[TMP55]], -3
// CHECK-NEXT: br label [[OMP_TYPE_END25]] // CHECK-NEXT: br label [[OMP_TYPE_END25]]
-// CHECK: omp.type.to.else23:+// CHECK: omp.type.to.else18:
// CHECK-NEXT: [[TMP61:%.*]] = icmp eq i64 [[TMP56]], 2 // CHECK-NEXT: [[TMP61:%.*]] = icmp eq i64 [[TMP56]], 2
// CHECK-NEXT: br i1 [[TMP61]], label [[OMP_TYPE_FROM24:%.*]], label [[OMP_TYPE_END25]] // CHECK-NEXT: br i1 [[TMP61]], label [[OMP_TYPE_FROM24:%.*]], label [[OMP_TYPE_END25]]
-// CHECK: omp.type.from24:+// CHECK: omp.type.from19:
// CHECK-NEXT: [[TMP62:%.*]] = and i64 [[TMP55]], -2 // CHECK-NEXT: [[TMP62:%.*]] = and i64 [[TMP55]], -2
// CHECK-NEXT: br label [[OMP_TYPE_END25]] // CHECK-NEXT: br label [[OMP_TYPE_END25]]
-// CHECK: omp.type.end25:+// CHECK: omp.type.end20:
// CHECK-NEXT: [[OMP_MAPTYPE26:%.*]] = phi i64 [ [[TMP58]], [[OMP_TYPE_ALLOC20]] ], [ [[TMP60]], [[OMP_TYPE_TO22]] ], [ [[TMP62]], [[OMP_TYPE_FROM24]] ], [ [[TMP55]], [[OMP_TYPE_TO_ELSE23]] ] // CHECK-NEXT: [[OMP_MAPTYPE26:%.*]] = phi i64 [ [[TMP58]], [[OMP_TYPE_ALLOC20]] ], [ [[TMP60]], [[OMP_TYPE_TO22]] ], [ [[TMP62]], [[OMP_TYPE_FROM24]] ], [ [[TMP55]], [[OMP_TYPE_TO_ELSE23]] ]
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[H]], i64 4, i64 [[OMP_MAPTYPE26]], ptr null)+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[H]], i64 4, i64 [[OMP_MAPTYPE26]], ptr null)
// CHECK-NEXT: [[OMP_ARRAYMAP_NEXT]] = getelementptr [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 1 // CHECK-NEXT: [[OMP_ARRAYMAP_NEXT]] = getelementptr [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 1
// CHECK-NEXT: [[OMP_ARRAYMAP_ISDONE:%.*]] = icmp eq ptr [[OMP_ARRAYMAP_NEXT]], [[TMP11]] // CHECK-NEXT: [[OMP_ARRAYMAP_ISDONE:%.*]] = icmp eq ptr [[OMP_ARRAYMAP_NEXT]], [[TMP11]]
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISDONE]], label [[OMP_ARRAYMAP_EXIT:%.*]], label [[OMP_ARRAYMAP_BODY]] // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISDONE]], label [[OMP_ARRAYMAP_EXIT:%.*]], label [[OMP_ARRAYMAP_BODY]]
// CHECK: omp.arraymap.exit: // CHECK: omp.arraymap.exit:
// CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY27:%.*]] = icmp sgt i64 [[TMP10]], 1 // CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY27:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT: [[TMP63:%.*]] = and i64 [[TMP12]], 8+// CHECK-NEXT: [[TMP63:%.*]] = and i64 [[TMP4]], 8
// CHECK-NEXT: [[DOTOMP_ARRAY__DEL__DELETE:%.*]] = icmp ne i64 [[TMP63]], 0 // CHECK-NEXT: [[DOTOMP_ARRAY__DEL__DELETE:%.*]] = icmp ne i64 [[TMP63]], 0
// CHECK-NEXT: [[TMP64:%.*]] = and i1 [[OMP_ARRAYINIT_ISARRAY27]], [[DOTOMP_ARRAY__DEL__DELETE]] // CHECK-NEXT: [[TMP64:%.*]] = and i1 [[OMP_ARRAYINIT_ISARRAY27]], [[DOTOMP_ARRAY__DEL__DELETE]]
// CHECK-NEXT: br i1 [[TMP64]], label [[DOTOMP_ARRAY__DEL:%.*]], label [[OMP_DONE]] // CHECK-NEXT: br i1 [[TMP64]], label [[DOTOMP_ARRAY__DEL:%.*]], label [[OMP_DONE]]
// CHECK: .omp.array..del: // CHECK: .omp.array..del:
// CHECK-NEXT: [[TMP65:%.*]] = mul nuw i64 [[TMP10]], 12 // CHECK-NEXT: [[TMP65:%.*]] = mul nuw i64 [[TMP10]], 12
-// CHECK-NEXT: [[TMP66:%.*]] = and i64 [[TMP12]], -4+// CHECK-NEXT: [[TMP66:%.*]] = and i64 [[TMP4]], -4
// CHECK-NEXT: [[TMP67:%.*]] = or i64 [[TMP66]], 512 // CHECK-NEXT: [[TMP67:%.*]] = or i64 [[TMP66]], 512
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP65]], i64 [[TMP67]], ptr [[TMP13]])+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP65]], i64 [[TMP67]], ptr [[TMP5]])
// CHECK-NEXT: br label [[OMP_DONE]] // CHECK-NEXT: br label [[OMP_DONE]]
// CHECK: omp.done: // CHECK: omp.done:
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
@@ -270,30 +252,12 @@ void foo() {
// CHECK-LABEL: define {{[^@]+}}@.omp_mapper._ZTS1C.default // CHECK-LABEL: define {{[^@]+}}@.omp_mapper._ZTS1C.default
// CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]], i64 noundef [[TMP3:%.*]], i64 noundef [[TMP4:%.*]], ptr noundef [[TMP5:%.*]]) #[[ATTR2]] { // CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]], i64 noundef [[TMP3:%.*]], i64 noundef [[TMP4:%.*]], ptr noundef [[TMP5:%.*]]) #[[ATTR2]] {
// CHECK-NEXT: entry: // CHECK-NEXT: entry:
-// CHECK-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8+// CHECK-NEXT: [[TMP10:%.*]] = udiv exact i64 [[TMP3]], 4
-// CHECK-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8+// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[TMP2]], i64 [[TMP10]]
-// CHECK-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[DOTADDR3:%.*]] = alloca i64, align 8
-// CHECK-NEXT: [[DOTADDR4:%.*]] = alloca i64, align 8
-// CHECK-NEXT: [[DOTADDR5:%.*]] = alloca ptr, align 8
-// CHECK-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
-// CHECK-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
-// CHECK-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 8
-// CHECK-NEXT: store i64 [[TMP3]], ptr [[DOTADDR3]], align 8
-// CHECK-NEXT: store i64 [[TMP4]], ptr [[DOTADDR4]], align 8
-// CHECK-NEXT: store ptr [[TMP5]], ptr [[DOTADDR5]], align 8
-// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[DOTADDR3]], align 8
-// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTADDR]], align 8
-// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
-// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 8
-// CHECK-NEXT: [[TMP10:%.*]] = udiv exact i64 [[TMP6]], 4
-// CHECK-NEXT: [[TMP11:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[TMP9]], i64 [[TMP10]]
-// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTADDR4]], align 8
-// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTADDR5]], align 8
// CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY:%.*]] = icmp sgt i64 [[TMP10]], 1 // CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[TMP12]], 8+// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[TMP4]], 8
-// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP8]], [[TMP9]]+// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP1]], [[TMP2]]
-// CHECK-NEXT: [[TMP16:%.*]] = and i64 [[TMP12]], 16+// CHECK-NEXT: [[TMP16:%.*]] = and i64 [[TMP4]], 16
// CHECK-NEXT: [[TMP17:%.*]] = icmp ne i64 [[TMP16]], 0 // CHECK-NEXT: [[TMP17:%.*]] = icmp ne i64 [[TMP16]], 0
// CHECK-NEXT: [[TMP18:%.*]] = and i1 [[TMP15]], [[TMP17]] // CHECK-NEXT: [[TMP18:%.*]] = and i1 [[TMP15]], [[TMP17]]
// CHECK-NEXT: [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_ISARRAY]], [[TMP18]] // CHECK-NEXT: [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_ISARRAY]], [[TMP18]]
@@ -302,20 +266,20 @@ void foo() {
// CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__INIT:%.*]], label [[OMP_ARRAYMAP_HEAD:%.*]] // CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__INIT:%.*]], label [[OMP_ARRAYMAP_HEAD:%.*]]
// CHECK: .omp.array..init: // CHECK: .omp.array..init:
// CHECK-NEXT: [[TMP21:%.*]] = mul nuw i64 [[TMP10]], 4 // CHECK-NEXT: [[TMP21:%.*]] = mul nuw i64 [[TMP10]], 4
-// CHECK-NEXT: [[TMP22:%.*]] = and i64 [[TMP12]], -4+// CHECK-NEXT: [[TMP22:%.*]] = and i64 [[TMP4]], -4
// CHECK-NEXT: [[TMP23:%.*]] = or i64 [[TMP22]], 512 // CHECK-NEXT: [[TMP23:%.*]] = or i64 [[TMP22]], 512
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP13]])+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP5]])
// CHECK-NEXT: br label [[OMP_ARRAYMAP_HEAD]] // CHECK-NEXT: br label [[OMP_ARRAYMAP_HEAD]]
// CHECK: omp.arraymap.head: // CHECK: omp.arraymap.head:
-// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP9]], [[TMP11]]+// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP2]], [[TMP11]]
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISEMPTY]], label [[OMP_DONE:%.*]], label [[OMP_ARRAYMAP_BODY:%.*]] // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISEMPTY]], label [[OMP_DONE:%.*]], label [[OMP_ARRAYMAP_BODY:%.*]]
// CHECK: omp.arraymap.body: // CHECK: omp.arraymap.body:
-// CHECK-NEXT: [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP9]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END:%.*]] ]+// CHECK-NEXT: [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP2]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END:%.*]] ]
// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 0 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 0
-// CHECK-NEXT: [[TMP24:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP7]])+// CHECK-NEXT: [[TMP24:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP0]])
// CHECK-NEXT: [[TMP25:%.*]] = shl i64 [[TMP24]], 48 // CHECK-NEXT: [[TMP25:%.*]] = shl i64 [[TMP24]], 48
// CHECK-NEXT: [[TMP26:%.*]] = add nuw i64 1, [[TMP25]] // CHECK-NEXT: [[TMP26:%.*]] = add nuw i64 1, [[TMP25]]
-// CHECK-NEXT: [[TMP27:%.*]] = and i64 [[TMP12]], 3+// CHECK-NEXT: [[TMP27:%.*]] = and i64 [[TMP4]], 3
// CHECK-NEXT: [[TMP28:%.*]] = icmp eq i64 [[TMP27]], 0 // CHECK-NEXT: [[TMP28:%.*]] = icmp eq i64 [[TMP27]], 0
// CHECK-NEXT: br i1 [[TMP28]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_ELSE:%.*]] // CHECK-NEXT: br i1 [[TMP28]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_ELSE:%.*]]
// CHECK: omp.type.alloc: // CHECK: omp.type.alloc:
@@ -335,21 +299,21 @@ void foo() {
// CHECK-NEXT: br label [[OMP_TYPE_END]] // CHECK-NEXT: br label [[OMP_TYPE_END]]
// CHECK: omp.type.end: // CHECK: omp.type.end:
// CHECK-NEXT: [[OMP_MAPTYPE:%.*]] = phi i64 [ [[TMP29]], [[OMP_TYPE_ALLOC]] ], [ [[TMP31]], [[OMP_TYPE_TO]] ], [ [[TMP33]], [[OMP_TYPE_FROM]] ], [ [[TMP26]], [[OMP_TYPE_TO_ELSE]] ] // CHECK-NEXT: [[OMP_MAPTYPE:%.*]] = phi i64 [ [[TMP29]], [[OMP_TYPE_ALLOC]] ], [ [[TMP31]], [[OMP_TYPE_TO]] ], [ [[TMP33]], [[OMP_TYPE_FROM]] ], [ [[TMP26]], [[OMP_TYPE_TO_ELSE]] ]
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[A]], i64 4, i64 [[OMP_MAPTYPE]], ptr null)+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[A]], i64 4, i64 [[OMP_MAPTYPE]], ptr null)
// CHECK-NEXT: [[OMP_ARRAYMAP_NEXT]] = getelementptr [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 1 // CHECK-NEXT: [[OMP_ARRAYMAP_NEXT]] = getelementptr [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 1
// CHECK-NEXT: [[OMP_ARRAYMAP_ISDONE:%.*]] = icmp eq ptr [[OMP_ARRAYMAP_NEXT]], [[TMP11]] // CHECK-NEXT: [[OMP_ARRAYMAP_ISDONE:%.*]] = icmp eq ptr [[OMP_ARRAYMAP_NEXT]], [[TMP11]]
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISDONE]], label [[OMP_ARRAYMAP_EXIT:%.*]], label [[OMP_ARRAYMAP_BODY]] // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISDONE]], label [[OMP_ARRAYMAP_EXIT:%.*]], label [[OMP_ARRAYMAP_BODY]]
// CHECK: omp.arraymap.exit: // CHECK: omp.arraymap.exit:
// CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY6:%.*]] = icmp sgt i64 [[TMP10]], 1 // CHECK-NEXT: [[OMP_ARRAYINIT_ISARRAY6:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT: [[TMP34:%.*]] = and i64 [[TMP12]], 8+// CHECK-NEXT: [[TMP34:%.*]] = and i64 [[TMP4]], 8
// CHECK-NEXT: [[DOTOMP_ARRAY__DEL__DELETE:%.*]] = icmp ne i64 [[TMP34]], 0 // CHECK-NEXT: [[DOTOMP_ARRAY__DEL__DELETE:%.*]] = icmp ne i64 [[TMP34]], 0
// CHECK-NEXT: [[TMP35:%.*]] = and i1 [[OMP_ARRAYINIT_ISARRAY6]], [[DOTOMP_ARRAY__DEL__DELETE]] // CHECK-NEXT: [[TMP35:%.*]] = and i1 [[OMP_ARRAYINIT_ISARRAY6]], [[DOTOMP_ARRAY__DEL__DELETE]]
// CHECK-NEXT: br i1 [[TMP35]], label [[DOTOMP_ARRAY__DEL:%.*]], label [[OMP_DONE]] // CHECK-NEXT: br i1 [[TMP35]], label [[DOTOMP_ARRAY__DEL:%.*]], label [[OMP_DONE]]
// CHECK: .omp.array..del: // CHECK: .omp.array..del:
// CHECK-NEXT: [[TMP36:%.*]] = mul nuw i64 [[TMP10]], 4 // CHECK-NEXT: [[TMP36:%.*]] = mul nuw i64 [[TMP10]], 4
-// CHECK-NEXT: [[TMP37:%.*]] = and i64 [[TMP12]], -4+// CHECK-NEXT: [[TMP37:%.*]] = and i64 [[TMP4]], -4
// CHECK-NEXT: [[TMP38:%.*]] = or i64 [[TMP37]], 512 // CHECK-NEXT: [[TMP38:%.*]] = or i64 [[TMP37]], 512
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP36]], i64 [[TMP38]], ptr [[TMP13]])+// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP36]], i64 [[TMP38]], ptr [[TMP5]])
// CHECK-NEXT: br label [[OMP_DONE]] // CHECK-NEXT: br label [[OMP_DONE]]
// CHECK: omp.done: // CHECK: omp.done:
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
clang/test/ParserOpenACC/parse-clauses.c
@@ -4,20 +4,27 @@
void func() { void func() {
+ // expected-error@+1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
#pragma acc exit data finalize #pragma acc exit data finalize
+ // expected-error@+1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
#pragma acc exit data finalize finalize #pragma acc exit data finalize finalize
+ // expected-error@+2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
// expected-error@+1{{invalid OpenACC clause 'invalid'}} // expected-error@+1{{invalid OpenACC clause 'invalid'}}
#pragma acc exit data finalize invalid #pragma acc exit data finalize invalid
+ // expected-error@+2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
// expected-error@+1{{invalid OpenACC clause 'invalid'}} // expected-error@+1{{invalid OpenACC clause 'invalid'}}
#pragma acc exit data finalize invalid invalid finalize #pragma acc exit data finalize invalid invalid finalize
+ // expected-error@+1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
#pragma acc exit data wait finalize #pragma acc exit data wait finalize
+ // expected-error@+1{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
#pragma acc host_data if_present #pragma acc host_data if_present
+ // expected-error@+1{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
#pragma acc host_data if_present, if_present #pragma acc host_data if_present, if_present
// expected-error@+4{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}} // expected-error@+4{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
@@ -443,13 +450,16 @@ void VarListClauses() {
#pragma acc serial present_or_copy(HasMem.MemArr[3:]) #pragma acc serial present_or_copy(HasMem.MemArr[3:])
for(int i = 0; i < 5;++i) {} for(int i = 0; i < 5;++i) {}
- // expected-error@+2{{expected ','}}+ // expected-error@+2 2{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}}
- // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented, clause ignored}}+ // expected-error@+1{{expected ','}}
-#pragma acc serial use_device(s.array[s.value] s.array[s.value :5] ), self+#pragma acc host_data use_device(s.array[s.value] s.array[s.value :5] ), if_present
+ for(int i = 0; i < 5;++i) {}
+
+ // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}}
+#pragma acc host_data use_device(s.array[s.value : 5]), if_present
for(int i = 0; i < 5;++i) {} for(int i = 0; i < 5;++i) {}
- // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented, clause ignored}}+#pragma acc host_data use_device(HasMem), if_present
-#pragma acc serial use_device(s.array[s.value : 5]), self
for(int i = 0; i < 5;++i) {} for(int i = 0; i < 5;++i) {}
// expected-error@+1{{expected ','}} // expected-error@+1{{expected ','}}
@@ -510,24 +520,13 @@ void VarListClauses() {
#pragma acc serial firstprivate(s.array[s.value : 5], s.value), self #pragma acc serial firstprivate(s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {} for(int i = 0; i < 5;++i) {}
- // expected-error@+2{{expected ','}}+ // expected-error@+1{{expected ','}}
- // expected-warning@+1{{OpenACC clause 'delete' not yet implemented, clause ignored}}
#pragma acc exit data delete(s.array[s.value] s.array[s.value :5] ) async #pragma acc exit data delete(s.array[s.value] s.array[s.value :5] ) async
for(int i = 0; i < 5;++i) {} for(int i = 0; i < 5;++i) {}
- // expected-warning@+1{{OpenACC clause 'delete' not yet implemented, clause ignored}}
#pragma acc exit data delete(s.array[s.value : 5], s.value),async #pragma acc exit data delete(s.array[s.value : 5], s.value),async
for(int i = 0; i < 5;++i) {} for(int i = 0; i < 5;++i) {}
- // expected-error@+2{{expected ','}}
- // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
-#pragma acc exit data use_device(s.array[s.value] s.array[s.value :5] ),async
- for(int i = 0; i < 5;++i) {}
-
- // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
-#pragma acc exit data use_device(s.array[s.value : 5], s.value), async
- for(int i = 0; i < 5;++i) {}
-
// expected-error@+2{{expected ','}} // expected-error@+2{{expected ','}}
// expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented, clause ignored}} // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented, clause ignored}}
#pragma acc serial device_resident(s.array[s.value] s.array[s.value :5] ), self #pragma acc serial device_resident(s.array[s.value] s.array[s.value :5] ), self
clang/test/ParserOpenACC/parse-clauses.cpp
@@ -35,8 +35,9 @@ void templ() {
#pragma acc parallel async #pragma acc parallel async
for(;;){} for(;;){}
- // expected-warning@+1{{OpenACC clause 'delete' not yet implemented, clause ignored}}+
-#pragma acc exit data delete(I)+ T t;
+#pragma acc exit data delete(t)
; ;
} }
clang/test/ParserOpenACC/parse-constructs.c
@@ -54,12 +54,15 @@ void func() {
// expected-error@+1{{invalid OpenACC clause 'clause'}} // expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc kernels clause list #pragma acc kernels clause list
for(;;){} for(;;){}
+ // expected-error@+2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
// expected-error@+1{{invalid OpenACC clause 'clause'}} // expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc data clause list #pragma acc data clause list
for(;;){} for(;;){}
+ // expected-error@+2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
// expected-error@+1{{invalid OpenACC clause 'clause'}} // expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc enter data clause list #pragma acc enter data clause list
for(;;){} for(;;){}
+ // expected-error@+2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
// expected-error@+1{{invalid OpenACC clause 'clause'}} // expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc exit data clause list #pragma acc exit data clause list
for(;;){} for(;;){}
@@ -75,6 +78,7 @@ void func() {
// expected-error@+1{{expected identifier}} // expected-error@+1{{expected identifier}}
#pragma acc exit } #pragma acc exit }
for(;;){} for(;;){}
+ // expected-error@+2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
// expected-error@+1{{invalid OpenACC clause 'clause'}} // expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc host_data clause list #pragma acc host_data clause list
for(;;){} for(;;){}
clang/test/Preprocessor/predefined-arch-macros.c
@@ -1953,6 +1953,8 @@
// CHECK_GNR_M32: #define __SSSE3__ 1 // CHECK_GNR_M32: #define __SSSE3__ 1
// CHECK_GNR_M32: #define __TSXLDTRK__ 1 // CHECK_GNR_M32: #define __TSXLDTRK__ 1
// CHECK_GNR_M32: #define __UINTR__ 1 // CHECK_GNR_M32: #define __UINTR__ 1
+// CHECK_GNR_M32-NOT: #define __USERMSR__ 1
+// CHECK_DMR_M32: #define __USERMSR__ 1
// CHECK_GNR_M32: #define __VAES__ 1 // CHECK_GNR_M32: #define __VAES__ 1
// CHECK_GNR_M32: #define __VPCLMULQDQ__ 1 // CHECK_GNR_M32: #define __VPCLMULQDQ__ 1
// CHECK_GNR_M32: #define __WAITPKG__ 1 // CHECK_GNR_M32: #define __WAITPKG__ 1
@@ -2061,6 +2063,8 @@
// CHECK_GNR_M64: #define __SSSE3__ 1 // CHECK_GNR_M64: #define __SSSE3__ 1
// CHECK_GNR_M64: #define __TSXLDTRK__ 1 // CHECK_GNR_M64: #define __TSXLDTRK__ 1
// CHECK_GNR_M64: #define __UINTR__ 1 // CHECK_GNR_M64: #define __UINTR__ 1
+// CHECK_GNR_M64-NOT: #define __USERMSR__ 1
+// CHECK_DMR_M64: #define __USERMSR__ 1
// CHECK_GNR_M64: #define __VAES__ 1 // CHECK_GNR_M64: #define __VAES__ 1
// CHECK_GNR_M64: #define __VPCLMULQDQ__ 1 // CHECK_GNR_M64: #define __VPCLMULQDQ__ 1
// CHECK_GNR_M64: #define __WAITPKG__ 1 // CHECK_GNR_M64: #define __WAITPKG__ 1
clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_imm.c
@@ -16,3 +16,37 @@ void test_svmopa(svbool_t pn, svbool_t pm, svmfloat8_t zn, svmfloat8_t zm,
// expected-error@+1 {{argument value 4 is outside the valid range [0, 3]}} // expected-error@+1 {{argument value 4 is outside the valid range [0, 3]}}
svmopa_za32_mf8_m_fpm(4, pn, pm, zn, zm, fpmr); svmopa_za32_mf8_m_fpm(4, pn, pm, zn, zm, fpmr);
} }
+
+void test_svmla(uint32_t slice, svmfloat8_t zn, svmfloat8x2_t znx2, svmfloat8x4_t znx4,
+ fpm_t fpmr) __arm_streaming __arm_inout("za") {
+ // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ svmla_lane_za16_mf8_vg2x1_fpm(slice, zn, zn, -1, fpmr);
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}}
+ svmla_lane_za16_mf8_vg2x1_fpm(slice, zn, zn, 16, fpmr);
+
+ // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ svmla_lane_za16_mf8_vg2x2_fpm(slice, znx2, zn, -1, fpmr);
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}}
+ svmla_lane_za16_mf8_vg2x2_fpm(slice, znx2, zn, 16, fpmr);
+
+ // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ svmla_lane_za16_mf8_vg2x4_fpm(slice, znx4, zn, -1, fpmr);
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}}
+ svmla_lane_za16_mf8_vg2x4_fpm(slice, znx4, zn, 16, fpmr);
+
+ // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ svmla_lane_za32_mf8_vg4x1_fpm(slice, zn, zn, -1, fpmr);
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}}
+ svmla_lane_za32_mf8_vg4x1_fpm(slice, zn, zn, 16, fpmr);
+
+ // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ svmla_lane_za32_mf8_vg4x2_fpm(slice, znx2, zn, -1, fpmr);
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}}
+ svmla_lane_za32_mf8_vg4x2_fpm(slice, znx2, zn, 16, fpmr);
+
+ // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ svmla_lane_za32_mf8_vg4x4_fpm(slice, znx4, zn, -1, fpmr);
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}}
+ svmla_lane_za32_mf8_vg4x4_fpm(slice, znx4, zn, 16, fpmr);
+
+}
clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_mla.c
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -verify -emit-llvm-only %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sme.h>
+
+void test_svmla(uint32_t slice, svmfloat8_t zn, svmfloat8x2_t znx2, svmfloat8x4_t znx4,
+ fpm_t fpmr) __arm_streaming __arm_inout("za") {
+ // expected-error@+1 {{'svmla_lane_za16_mf8_vg2x1_fpm' needs target feature sme,sme-f8f16}}
+ svmla_lane_za16_mf8_vg2x1_fpm(slice, zn, zn, 0, fpmr);
+
+ // expected-error@+1 {{'svmla_lane_za16_mf8_vg2x2_fpm' needs target feature sme,sme-f8f16}}
+ svmla_lane_za16_mf8_vg2x2_fpm(slice, znx2, zn, 0, fpmr);
+
+ // expected-error@+1 {{'svmla_lane_za16_mf8_vg2x4_fpm' needs target feature sme,sme-f8f16}}
+ svmla_lane_za16_mf8_vg2x4_fpm(slice, znx4, zn, 0, fpmr);
+
+ // expected-error@+1 {{'svmla_lane_za32_mf8_vg4x1_fpm' needs target feature sme,sme-f8f32}}
+ svmla_lane_za32_mf8_vg4x1_fpm(slice, zn, zn, 0, fpmr);
+
+ // expected-error@+1 {{'svmla_lane_za32_mf8_vg4x2_fpm' needs target feature sme,sme-f8f32}}
+ svmla_lane_za32_mf8_vg4x2_fpm(slice, znx2, zn, 0, fpmr);
+
+ // expected-error@+1 {{'svmla_lane_za32_mf8_vg4x4_fpm' needs target feature sme,sme-f8f32}}
+ svmla_lane_za32_mf8_vg4x4_fpm(slice, znx4, zn, 0, fpmr);
+
+ // expected-error@+1 {{'svmla_single_za16_mf8_vg2x1_fpm' needs target feature sme,sme-f8f16}}
+ svmla_single_za16_mf8_vg2x1_fpm(slice, zn, zn, fpmr);
+
+ // expected-error@+1 {{'svmla_single_za16_mf8_vg2x2_fpm' needs target feature sme,sme-f8f16}}
+ svmla_single_za16_mf8_vg2x2_fpm(slice, znx2, zn, fpmr);
+
+ // expected-error@+1 {{'svmla_single_za16_mf8_vg2x4_fpm' needs target feature sme,sme-f8f16}}
+ svmla_single_za16_mf8_vg2x4_fpm(slice, znx4, zn, fpmr);
+
+ // expected-error@+1 {{'svmla_single_za32_mf8_vg4x1_fpm' needs target feature sme,sme-f8f32}}
+ svmla_single_za32_mf8_vg4x1_fpm(slice, zn, zn, fpmr);
+
+ // expected-error@+1 {{'svmla_single_za32_mf8_vg4x2_fpm' needs target feature sme,sme-f8f32}}
+ svmla_single_za32_mf8_vg4x2_fpm(slice, znx2, zn, fpmr);
+
+ // expected-error@+1 {{'svmla_single_za32_mf8_vg4x4_fpm' needs target feature sme,sme-f8f32}}
+ svmla_single_za32_mf8_vg4x4_fpm(slice, znx4, zn, fpmr);
+
+ // expected-error@+1 {{'svmla_za16_mf8_vg2x2_fpm' needs target feature sme,sme-f8f16}}
+ svmla_za16_mf8_vg2x2_fpm(slice, znx2, znx2, fpmr);
+
+ // expected-error@+1 {{'svmla_za16_mf8_vg2x4_fpm' needs target feature sme,sme-f8f16}}
+ svmla_za16_mf8_vg2x4_fpm(slice, znx4, znx4, fpmr);
+
+ // expected-error@+1 {{'svmla_za32_mf8_vg4x2_fpm' needs target feature sme,sme-f8f32}}
+ svmla_za32_mf8_vg4x2_fpm(slice, znx2, znx2, fpmr);
+
+ // expected-error@+1 {{'svmla_za32_mf8_vg4x4_fpm' needs target feature sme,sme-f8f32}}
+ svmla_za32_mf8_vg4x4_fpm(slice, znx4, znx4, fpmr);
+}
clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_fp8_fdot.c
@@ -14,6 +14,22 @@ void test_features(uint32_t slice, svmfloat8_t f8, svmfloat8x2_t f8x2,
svdot_lane_za16_mf8_vg1x2_fpm(slice, f8x2, f8, 3, fpmr); svdot_lane_za16_mf8_vg1x2_fpm(slice, f8x2, f8, 3, fpmr);
[diff truncated]